koishi-plugin-ggcevo-game 1.2.13 → 1.2.14

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 CHANGED
@@ -50,7 +50,7 @@ var Config = import_koishi.Schema.intersect([
50
50
  dailyPKLimit: import_koishi.Schema.number().description("每日最大发起PK次数").default(3),
51
51
  sameOpponentLimit: import_koishi.Schema.boolean().description("同玩家每日单次限制").default(true),
52
52
  maxDailyBeChallenged: import_koishi.Schema.number().description("最大被挑战次数(0=无限制)").default(5),
53
- unlimitedBossAttack: import_koishi.Schema.boolean().description("开启无限制攻击主宰").default(false)
53
+ unlimitedBossAttack: import_koishi.Schema.boolean().description("开启无限制PVE攻击").default(false)
54
54
  }).description("对战限制"),
55
55
  // 通知系统配置组
56
56
  import_koishi.Schema.object({
@@ -59,7 +59,7 @@ var Config = import_koishi.Schema.intersect([
59
59
  }).description("通知设置").collapse(),
60
60
  // 权限管理组
61
61
  import_koishi.Schema.object({
62
- admins: import_koishi.Schema.array(import_koishi.Schema.string()).description("管理员QQ列表").default([])
62
+ admins: import_koishi.Schema.array(import_koishi.Schema.string()).description("管理员列表").default([])
63
63
  }).description("权限管理")
64
64
  ]);
65
65
  var inject = {
@@ -102,8 +102,11 @@ function apply(ctx, config) {
102
102
  ctx.model.extend("ggcevo_activity", {
103
103
  id: "unsigned",
104
104
  name: "string",
105
+ // 存储活动名称
105
106
  description: "text",
106
107
  quantity: "unsigned",
108
+ itemId: "unsigned",
109
+ // 新增物品ID字段
107
110
  startTime: "timestamp",
108
111
  endTime: "timestamp",
109
112
  creator: "string",
@@ -124,7 +127,6 @@ function apply(ctx, config) {
124
127
  // 比赛次数
125
128
  Blacklist: {
126
129
  type: "boolean",
127
- // 该字段的默认值
128
130
  initial: false
129
131
  }
130
132
  }, {
@@ -196,13 +198,11 @@ function apply(ctx, config) {
196
198
  todayCount: "unsigned",
197
199
  lastPK: "timestamp",
198
200
  enable: {
199
- // 新增字段
200
201
  type: "boolean",
201
202
  initial: true
202
203
  // 默认开启
203
204
  },
204
205
  lastToggle: "timestamp"
205
- // 新增字段
206
206
  }, {
207
207
  primary: "handle"
208
208
  });
@@ -276,11 +276,11 @@ function apply(ctx, config) {
276
276
  id: 3,
277
277
  type: "热能武器",
278
278
  damage: 15,
279
- description: "基于热能的强大武器",
279
+ description: "基于热能的强大武器,烧烬一切",
280
280
  price: 450,
281
281
  tagEffects: {
282
- "生物": 1.5,
283
282
  "惧热": 2,
283
+ "生物": 1.2,
284
284
  "护盾": 0.5
285
285
  }
286
286
  },
@@ -288,11 +288,24 @@ function apply(ctx, config) {
288
288
  id: 4,
289
289
  type: "能量武器",
290
290
  damage: 28,
291
- description: "由激光步枪改良而来,高效的能量武器",
291
+ description: "由激光步枪改良而来,高效的对重甲武器",
292
292
  price: 850,
293
293
  tagEffects: {
294
294
  "重甲": 2,
295
- "护盾": 0.8
295
+ "机械": 0.5,
296
+ "护盾": 0.2
297
+ }
298
+ },
299
+ "狙击步枪": {
300
+ id: 5,
301
+ type: "实弹武器",
302
+ damage: 60,
303
+ description: "用于隐秘射击的最佳武器,但是无法穿透护甲",
304
+ price: 550,
305
+ tagEffects: {
306
+ "轻甲": 0.7,
307
+ "护盾": 0.5,
308
+ "重甲": 0.2
296
309
  }
297
310
  }
298
311
  };
@@ -326,9 +339,18 @@ function apply(ctx, config) {
326
339
  }
327
340
  };
328
341
  const passiveConfig = {
329
- "弱化形态": { effect: 0.1 },
330
- "坚固外壳": { effect: -0.2 },
331
- "孤立无援": { effect: 0.2 }
342
+ "弱化形态": {
343
+ effect: 0.1,
344
+ description: "子代的防御薄弱,受到的伤害+10%"
345
+ },
346
+ "坚固外壳": {
347
+ effect: -0.2,
348
+ description: "拥有坚硬的生物甲壳,受到的伤害-20%"
349
+ },
350
+ "孤立无援": {
351
+ effect: 0.2,
352
+ description: "没有存活的子代,受到的伤害+20%"
353
+ }
332
354
  };
333
355
  const bossPool = [
334
356
  {
@@ -353,6 +375,96 @@ function apply(ctx, config) {
353
375
  ]
354
376
  }
355
377
  ];
378
+ function calculateModifiers(equippedWeapon, weaponName) {
379
+ let totalModAdd = 0;
380
+ let hasCrit = false;
381
+ let hasCrystal = false;
382
+ let hasOverload = false;
383
+ equippedWeapon.installedMods.forEach((mod) => {
384
+ if (mod === "动能增幅") {
385
+ totalModAdd += 0.2;
386
+ }
387
+ if (mod === "裂甲核心" && weaponName === modConfig[mod].exclusiveTo) {
388
+ totalModAdd += 0.4;
389
+ }
390
+ if (mod === "棱镜水晶") hasCrystal = true;
391
+ if (mod === "棱镜超载核心" && weaponName === modConfig[mod].exclusiveTo) {
392
+ hasOverload = true;
393
+ }
394
+ });
395
+ const totalCritRate = (hasCrystal ? 20 : 0) + (hasOverload ? 80 : 0);
396
+ if (totalCritRate > 0 && Math.random() < totalCritRate / 100) {
397
+ hasCrit = true;
398
+ totalModAdd += 1;
399
+ }
400
+ return { totalModAdd, hasCrit };
401
+ }
402
+ __name(calculateModifiers, "calculateModifiers");
403
+ function calculateTagEffects(weaponData, targetBossConfig, equippedWeapon) {
404
+ let totalTagAdd = 0;
405
+ const armorTags = targetBossConfig.tags?.filter((tag) => ["重甲", "轻甲", "护盾"].includes(tag)) || [];
406
+ const voidTags = targetBossConfig.tags?.filter((tag) => ["惧热", "惧寒"].includes(tag)) || [];
407
+ const typeTags = targetBossConfig.tags?.filter((tag) => ["生物", "机械", "灵能"].includes(tag)) || [];
408
+ armorTags.forEach((tag) => {
409
+ let effectValue = weaponData.tagEffects?.[tag] ?? 1;
410
+ if (tag === "重甲" && equippedWeapon.installedMods.includes("裂甲核心")) {
411
+ effectValue = 1.2;
412
+ }
413
+ totalTagAdd += effectValue - 1;
414
+ });
415
+ voidTags.forEach((tag) => {
416
+ const effectValue = weaponData.tagEffects?.[tag] ?? 1;
417
+ totalTagAdd += effectValue - 1;
418
+ });
419
+ typeTags.forEach((tag) => {
420
+ const effectValue = weaponData.tagEffects?.[tag] ?? 1;
421
+ totalTagAdd += effectValue - 1;
422
+ });
423
+ return totalTagAdd;
424
+ }
425
+ __name(calculateTagEffects, "calculateTagEffects");
426
+ function calculatePassiveEffects(targetBossConfig, activeMinionsCount) {
427
+ let passiveEffect = 0;
428
+ const effectivePassives = [...targetBossConfig.passive || []];
429
+ if (targetBossConfig.type === "主宰" && effectivePassives.includes("孤立无援")) {
430
+ if (activeMinionsCount !== 0) {
431
+ effectivePassives.splice(effectivePassives.indexOf("孤立无援"), 1);
432
+ }
433
+ }
434
+ effectivePassives.forEach((passive) => {
435
+ const effect = passiveConfig[passive]?.effect || 0;
436
+ passiveEffect += effect;
437
+ });
438
+ return passiveEffect;
439
+ }
440
+ __name(calculatePassiveEffects, "calculatePassiveEffects");
441
+ function calculateRankBonus(rankRecord) {
442
+ if (!rankRecord || rankRecord.rank <= 0) return 0;
443
+ return Math.floor(rankRecord.rank / 400) * 0.01;
444
+ }
445
+ __name(calculateRankBonus, "calculateRankBonus");
446
+ async function calculateTotalDamage(ctx2, session, equippedWeapon, targetBoss) {
447
+ const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
448
+ const [weaponName, weaponData] = weaponConfigEntry;
449
+ let damage = weaponData.damage * (1 + 0.1 * equippedWeapon.level);
450
+ const { totalModAdd, hasCrit } = calculateModifiers(equippedWeapon, weaponName);
451
+ damage *= 1 + totalModAdd;
452
+ const targetBossConfig = targetBoss.type === "主宰" ? bossPool.find((g) => g.main.name === targetBoss.name).main : bossPool.find((g) => g.minions.some((m) => m.name === targetBoss.name)).minions[0];
453
+ const tagMultiplier = calculateTagEffects(weaponData, targetBossConfig, equippedWeapon);
454
+ damage *= 1 + tagMultiplier;
455
+ const activeMinions = await ctx2.database.get("ggcevo_boss", {
456
+ groupId: targetBoss.groupId,
457
+ type: "子代",
458
+ isActive: true
459
+ });
460
+ const passiveMultiplier = calculatePassiveEffects(targetBossConfig, activeMinions.length);
461
+ damage *= 1 + passiveMultiplier;
462
+ const [rankRecord] = await ctx2.database.get("ggcevo_rank", { handle: session.handle });
463
+ const rankBonus = calculateRankBonus(rankRecord);
464
+ damage *= 1 + rankBonus;
465
+ return { damage: Math.round(damage), hasCrit };
466
+ }
467
+ __name(calculateTotalDamage, "calculateTotalDamage");
356
468
  const initDefaultItems = {
357
469
  "咕咕币": { id: 1, type: "抽奖道具", description: "用于进行抽奖" },
358
470
  "兑换券": { id: 2, type: "兑换货币", description: "用于兑换赞助物品" },
@@ -522,7 +634,7 @@ function apply(ctx, config) {
522
634
  await activateNextBossGroup(group.groupId);
523
635
  ctx.broadcast(
524
636
  config.groupId,
525
- `🔄 BOSS已刷新!新的BOSS组已出现,快去挑战吧!`
637
+ `🔄 新的主宰已刷新,快去挑战吧!`
526
638
  );
527
639
  }
528
640
  }, 60 * 1e3);
@@ -532,21 +644,21 @@ function apply(ctx, config) {
532
644
  let hiddenWinCount = 0;
533
645
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
534
646
  if (!profile) {
535
- return "您的 QQ 未绑定句柄。";
647
+ return "您暂未绑定句柄。";
536
648
  }
537
649
  const { regionId, realmId, profileId } = profile;
538
650
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
539
651
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
540
652
  if (existingEntries.length > 0) {
541
- return `❌拒绝访问,您已被列入活动黑名单。`;
653
+ return `❌ 拒绝访问,您已被列入黑名单。`;
542
654
  }
543
655
  const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 1 });
544
656
  if (!backpack) {
545
- return "您还没有进行过签到。";
657
+ return "您还没有签到。";
546
658
  }
547
659
  const quantity = backpack.quantity;
548
660
  if (quantity < 1) {
549
- return "您的咕咕币不足~";
661
+ return "您的咕咕币不足。";
550
662
  }
551
663
  await ctx.database.upsert("ggcevo_backpack", [{
552
664
  handle,
@@ -571,20 +683,20 @@ function apply(ctx, config) {
571
683
  const session = argv.session;
572
684
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
573
685
  if (!profile) {
574
- return "您的 QQ 未绑定句柄。";
686
+ return "您暂未绑定句柄。";
575
687
  }
576
688
  const { regionId, realmId, profileId } = profile;
577
689
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
578
690
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
579
691
  if (existingEntries.length > 0) {
580
- return `❌拒绝访问,您已被列入活动黑名单。`;
692
+ return `❌ 拒绝访问,您已被列入黑名单。`;
581
693
  }
582
694
  const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 1 });
583
695
  if (!backpack) {
584
- return "您还没有进行过签到。";
696
+ return "您还没有签到。";
585
697
  }
586
698
  if (backpack.quantity < 1) {
587
- return "您的咕咕币不足~";
699
+ return "您的咕咕币不足。";
588
700
  }
589
701
  await ctx.database.upsert("ggcevo_backpack", [{
590
702
  handle,
@@ -604,20 +716,20 @@ function apply(ctx, config) {
604
716
  let hiddenWinCount = 0;
605
717
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
606
718
  if (!profile) {
607
- return "您的 QQ 未绑定句柄。";
719
+ return "您暂未绑定句柄。";
608
720
  }
609
721
  const { regionId, realmId, profileId } = profile;
610
722
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
611
723
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
612
724
  if (existingEntries.length > 0) {
613
- return `❌拒绝访问,您已被列入活动黑名单。`;
725
+ return `❌ 拒绝访问,您已被列入黑名单。`;
614
726
  }
615
727
  const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 1 });
616
728
  if (!backpack) {
617
- return "您还没有进行过签到。";
729
+ return "您还没有签到。";
618
730
  }
619
731
  if (backpack.quantity < 10) {
620
- return "您的咕咕币不足~";
732
+ return "您的咕咕币不足。";
621
733
  }
622
734
  await ctx.database.upsert("ggcevo_backpack", [{
623
735
  handle,
@@ -642,7 +754,7 @@ function apply(ctx, config) {
642
754
  const session = argv.session;
643
755
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
644
756
  if (!profile) {
645
- return "您的 QQ 未绑定句柄。";
757
+ return "您暂未绑定句柄。";
646
758
  }
647
759
  const { regionId, realmId, profileId } = profile;
648
760
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
@@ -661,7 +773,7 @@ function apply(ctx, config) {
661
773
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
662
774
  const items = await ctx.database.get("ggcevo_backpack", { handle });
663
775
  const validItems = items.filter((item) => item.quantity > 0);
664
- if (!validItems.length) return "你的背包空空如也~";
776
+ if (!validItems.length) return "你的背包空空如也。";
665
777
  const itemDetails = validItems.map((userItem) => {
666
778
  const entry = Object.entries(initDefaultItems).find(
667
779
  ([, item]) => item.id === userItem.itemId
@@ -678,11 +790,11 @@ ${itemDetails.join("\n")}`;
678
790
  const session = argv.session;
679
791
  let latestTime;
680
792
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
681
- if (!profile) return "您的 QQ 未绑定句柄。";
793
+ if (!profile) return "您暂未绑定句柄。";
682
794
  const { regionId, realmId, profileId } = profile;
683
795
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
684
796
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
685
- if (existingEntries.length > 0) return "❌拒绝访问,您已被列入活动黑名单。";
797
+ if (existingEntries.length > 0) return "❌ 拒绝访问,您已被列入黑名单。";
686
798
  const now = /* @__PURE__ */ new Date();
687
799
  const currentChinaTime = convertUTCtoChinaTime(now);
688
800
  if (config.signrequire) {
@@ -700,18 +812,18 @@ ${itemDetails.join("\n")}`;
700
812
  } else {
701
813
  latestTime = currentChinaTime;
702
814
  }
703
- if (!latestTime) return "您还没有游玩过 咕咕虫-evolved 地图";
815
+ if (!latestTime) return "您还没有游玩过“咕咕虫-evolved”。";
704
816
  const targetDateChina = new Date(latestTime);
705
817
  targetDateChina.setUTCDate(targetDateChina.getUTCDate() + 1);
706
818
  if (!isSameDate(latestTime, currentChinaTime) && !isSameDate(targetDateChina, currentChinaTime)) {
707
- return "暂未查询到您最近两天内游玩过 咕咕虫-evolved 地图,请游玩1次后签到(对局记录上传有延迟)";
819
+ return "暂未查询到您最近两天内游玩过“咕咕虫-evolved”,请游玩1次后签到(对局记录上传有延迟)";
708
820
  }
709
821
  const [record] = await ctx.database.get("ggcevo_sign", { handle });
710
822
  const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 1 });
711
823
  if (record) {
712
824
  const lastSignChina = convertUTCtoChinaTime(record.lastSign);
713
825
  if (lastSignChina.getUTCDate() === currentChinaTime.getUTCDate()) {
714
- return `您今天已经签到过了!本月累计签到 ${record.monthlyDays} 天`;
826
+ return `您今天已经签到过了!本月累计签到${record.monthlyDays}天。`;
715
827
  }
716
828
  }
717
829
  let monthlyDays = 1;
@@ -754,7 +866,7 @@ ${itemDetails.join("\n")}`;
754
866
  itemId: 1,
755
867
  quantity: (backpack?.quantity || 0) + tickets
756
868
  }]);
757
- return `签到成功!本月累计签到 ${monthlyDays} 天,获得 ${points} 金币和 ${tickets} 枚咕咕币`;
869
+ return `签到成功!本月累计签到${monthlyDays}天,获得${points}枚金币和${tickets}枚咕咕币`;
758
870
  } catch (error) {
759
871
  console.error("签到命令时发生错误:", error);
760
872
  return "服务器繁忙,请稍后尝试。";
@@ -764,13 +876,13 @@ ${itemDetails.join("\n")}`;
764
876
  try {
765
877
  const session = argv.session;
766
878
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
767
- if (!profile) return "您的 QQ 未绑定句柄。";
879
+ if (!profile) return "您暂未绑定句柄。";
768
880
  const { regionId, realmId, profileId } = profile;
769
881
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
770
882
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
771
- if (existingEntries.length > 0) return "❌拒绝访问,您已被列入活动黑名单。";
883
+ if (existingEntries.length > 0) return "❌ 拒绝访问,您已被列入黑名单。";
772
884
  const [record] = await ctx.database.get("ggcevo_sign", { handle });
773
- if (!record) return "请先完成一次正常签到后再进行补签。";
885
+ if (!record) return "您还没有签到。";
774
886
  const lastSignChina = convertUTCtoChinaTime(record.lastSign);
775
887
  const targetDateChina = new Date(lastSignChina);
776
888
  const nowChina = convertUTCtoChinaTime(/* @__PURE__ */ new Date());
@@ -783,7 +895,7 @@ ${itemDetails.join("\n")}`;
783
895
  }
784
896
  const costPoints = 50;
785
897
  if (record.totalRewards < costPoints) {
786
- return `补签需要消耗 ${costPoints} 金币,当前金币不足。`;
898
+ return `补签需要消耗${costPoints}枚金币,您的金币不足。`;
787
899
  }
788
900
  const newMonthlyDays = record.monthlyDays + 1;
789
901
  let tickets = 3, points = 0;
@@ -809,14 +921,8 @@ ${itemDetails.join("\n")}`;
809
921
  await ctx.database.set("ggcevo_backpack", { handle, itemId: 1 }, {
810
922
  quantity: (backpack?.quantity || 0) + tickets
811
923
  });
812
- const formattedDate = targetDateChina.toLocaleString("zh-CN", {
813
- timeZone: "Asia/Shanghai",
814
- year: "numeric",
815
- month: "2-digit",
816
- day: "2-digit"
817
- });
818
- const rewardsMessage = points > 0 ? `获得 ${points} 金币和 ${tickets} 枚咕咕币` : `获得 ${tickets} 枚咕咕币`;
819
- return `补签成功!本月累计签到 ${newMonthlyDays} 天,消耗 ${costPoints} 金币,${rewardsMessage}`;
924
+ const rewardsMessage = points > 0 ? `获得${points}枚金币和${tickets}枚咕咕币` : `获得${tickets}枚咕咕币`;
925
+ return `补签成功!本月累计签到${newMonthlyDays}天,消耗${costPoints}枚金币,${rewardsMessage}`;
820
926
  } catch (error) {
821
927
  console.error("补签错误:", error);
822
928
  return "补签失败,请稍后重试。";
@@ -825,11 +931,11 @@ ${itemDetails.join("\n")}`;
825
931
  ctx.command("ggcevo/签到记录").action(async (argv) => {
826
932
  const session = argv.session;
827
933
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
828
- if (!profile) return "您的 QQ 未绑定句柄。";
934
+ if (!profile) return "您暂未绑定句柄。";
829
935
  const { regionId, realmId, profileId } = profile;
830
936
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
831
937
  const [record] = await ctx.database.get("ggcevo_sign", { handle });
832
- if (!record) return "您还没有签到过哦";
938
+ if (!record) return "您还没有签到。";
833
939
  const chinaTime = record.lastSign.toLocaleString("zh-CN", {
834
940
  timeZone: "Asia/Shanghai",
835
941
  year: "numeric",
@@ -843,25 +949,25 @@ ${itemDetails.join("\n")}`;
843
949
  return [
844
950
  `您的句柄:${handle}`,
845
951
  `📅 最后签到时间:${chinaTime}`,
846
- `🔥 累计签到:${record.monthlyDays} 天`,
847
- `💰 累计获得:${record.totalRewards} 金币`
952
+ `🔥 累计签到:${record.monthlyDays}天`,
953
+ `💰 拥有财富:${record.totalRewards}枚金币`
848
954
  ].join("\n");
849
955
  });
850
956
  ctx.guild().command("ggcevo/每月津贴").action(async (argv) => {
851
957
  const session = argv.session;
852
958
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
853
- if (!profile) return "您的 QQ 未绑定句柄。";
959
+ if (!profile) return "您暂未绑定句柄。";
854
960
  const { regionId, realmId, profileId } = profile;
855
961
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
856
962
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
857
963
  if (existingEntries.length > 0) {
858
- return `❌拒绝访问,您已被列入活动黑名单。`;
964
+ return `❌ 拒绝访问,您已被列入黑名单。`;
859
965
  }
860
966
  const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 1 });
861
- if (!backpack) return "您还没有签到过哦";
967
+ if (!backpack) return "您还没有签到。";
862
968
  const memberInfo = await session.event?.member?.roles;
863
969
  if (memberInfo?.includes("member")) {
864
- return "仅限管理员和群主领取每月津贴";
970
+ return "❌拒绝访问,仅限管理员和群主领取每月津贴。";
865
971
  }
866
972
  const now = /* @__PURE__ */ new Date();
867
973
  const chinatime = convertUTCtoChinaTime(now);
@@ -875,7 +981,7 @@ ${itemDetails.join("\n")}`;
875
981
  const lastYear = lastSignTime.getUTCFullYear();
876
982
  const lastMonth = lastSignTime.getUTCMonth();
877
983
  if (lastYear === currentYear && lastMonth === currentMonth) {
878
- return `本月管理津贴已领取,${currentMonth + 2} 月1日可再次领取`;
984
+ return `您的本月管理津贴已领取,${currentMonth + 2}月1日后可再次领取`;
879
985
  }
880
986
  }
881
987
  await ctx.database.upsert("ggcevo_adminbenefit", [{
@@ -890,111 +996,109 @@ ${itemDetails.join("\n")}`;
890
996
  itemId: 1,
891
997
  quantity: (backpack.quantity || 0) + 50
892
998
  }]);
893
- return `[管理专属] 成功领取本月津贴!累计领取 ${adminRecord ? adminRecord.signmonth + 1 : 1} 个月`;
999
+ return `[管理专属] 成功领取本月津贴,获得了50枚咕咕币!`;
894
1000
  });
895
- ctx.command("ggcevo/领取福利").action(async (argv) => {
1001
+ ctx.command("ggcevo/领取 [name]").action(async (argv, name2) => {
896
1002
  const session = argv.session;
897
- await session.send("请在30秒内输入活动名称:");
898
- const name2 = await session.prompt(3e4);
899
1003
  if (!name2) {
900
- return "输入超时,请重新输入指令。";
1004
+ await session.send("请在30秒内输入活动名称");
1005
+ name2 = await session.prompt(3e4);
1006
+ if (!name2) return "输入超时,请重新输入。";
1007
+ }
1008
+ const itemIdToName = {};
1009
+ for (const [name3, item] of Object.entries(initDefaultItems)) {
1010
+ itemIdToName[item.id] = name3;
901
1011
  }
902
1012
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
903
- if (!profile) return "您的 QQ 未绑定句柄。";
904
- const { regionId, realmId, profileId } = profile;
905
- const handle = `${regionId}-S2-${realmId}-${profileId}`;
1013
+ if (!profile) return "您暂未绑定句柄。";
1014
+ const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
906
1015
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
907
- if (existingEntries.length > 0) {
908
- return `❌拒绝访问,您已被列入活动黑名单。`;
909
- }
910
- const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 1 });
911
- if (!backpack) return "您还没有签到过哦";
1016
+ if (existingEntries.length > 0) return "❌ 拒绝访问,您已被列入黑名单。";
912
1017
  const [activity] = await ctx.database.get("ggcevo_activity", {
913
1018
  name: name2,
914
1019
  status: "进行中"
915
- // 新增状态条件
916
1020
  });
917
- if (!activity) {
918
- return "当前咕咕币活动未在进行中,请输入 咕咕币活动 查询活动名称。";
919
- }
920
- const id = activity.id;
921
- const quantity = activity.quantity;
1021
+ if (!activity) return "活动未进行中。";
922
1022
  const existing = await ctx.database.get("ggcevo_welfare", {
923
1023
  handle,
924
- activity: id
1024
+ activity: activity.id
925
1025
  });
926
- if (existing.length > 0) {
927
- const chinaTime = existing[0].lastdate.toLocaleString("zh-CN", {
928
- timeZone: "Asia/Shanghai",
929
- year: "numeric",
930
- month: "2-digit",
931
- day: "2-digit",
932
- hour: "2-digit",
933
- minute: "2-digit",
934
- second: "2-digit",
935
- hour12: false
1026
+ if (existing.length) {
1027
+ const time = existing[0].lastdate.toLocaleString("zh-CN", {
1028
+ timeZone: "Asia/Shanghai"
1029
+ });
1030
+ return `您已领取过该活动奖励(领取时间:${time})。`;
1031
+ }
1032
+ if (activity.itemId === 0) {
1033
+ const [sign] = await ctx.database.get("ggcevo_sign", { handle });
1034
+ await ctx.database.upsert("ggcevo_sign", [{
1035
+ handle,
1036
+ totalRewards: (sign?.totalRewards || 0) + activity.quantity,
1037
+ lastSign: sign?.lastSign || /* @__PURE__ */ new Date(0),
1038
+ monthlyDays: sign?.monthlyDays || 0
1039
+ }]);
1040
+ } else {
1041
+ const [item] = await ctx.database.get("ggcevo_backpack", {
1042
+ handle,
1043
+ itemId: activity.itemId
936
1044
  });
937
- return `您已领取过该咕咕币活动福利(领取时间:${chinaTime})`;
1045
+ await ctx.database.upsert("ggcevo_backpack", [{
1046
+ handle,
1047
+ itemId: activity.itemId,
1048
+ quantity: (item?.quantity || 0) + activity.quantity
1049
+ }]);
938
1050
  }
939
1051
  await ctx.database.create("ggcevo_welfare", {
940
1052
  handle,
941
- activity: id,
1053
+ activity: activity.id,
942
1054
  lastdate: /* @__PURE__ */ new Date()
943
1055
  });
944
- await ctx.database.upsert("ggcevo_backpack", [{
945
- handle,
946
- itemId: 1,
947
- quantity: (backpack.quantity || 0) + quantity
948
- }]);
949
- return `[活动福利] 成功领取 ${name2} 咕咕币活动奖励,获得 ${quantity} 枚咕咕币`;
1056
+ return `您成功领取 ${name2} 活动奖励:${activity.itemId === 0 ? `${activity.quantity}枚金币` : `${activity.quantity}个${itemIdToName[activity.itemId] || "未知物品"}`}`;
950
1057
  });
951
- ctx.command("ggcevo/创建活动 <name> <description> <quantity:number>", "创建新活动", { authority: 3 }).option("start", "-s <startTime:date>", { fallback: Date.now() }).option("duration", "-d <days:number>", { fallback: 7 }).action(async ({ session, options }, name2, description, quantity) => {
952
- if (!name2 || !name2.trim()) {
953
- return "活动名称不能为空";
954
- }
955
- const existing = await ctx.database.get("ggcevo_activity", { name: name2 });
956
- if (existing.length > 0) {
957
- return `活动名称 "${name2}" 已存在,请换用其他名称`;
958
- }
959
- const now = Date.now();
960
- const startTime = new Date(options.start);
961
- const endTime = new Date(startTime.getTime() + options.duration * 864e5);
962
- const status = startTime.getTime() <= now ? "进行中" : "未开始";
963
- const activity = await ctx.database.create("ggcevo_activity", {
964
- name: name2,
1058
+ ctx.command("ggcevo/创建活动 <activityName> <itemName> <quantity:number> <description>", "创建新活动", { authority: 3 }).option("start", "-s <startTime:date>", { fallback: Date.now() }).option("duration", "-d <days:number>", { fallback: 7 }).action(async ({ session, options }, activityName, itemName, quantity, description) => {
1059
+ if (!activityName) return "活动名称不能为空。";
1060
+ if (!itemName) return "物品名称不能为空。";
1061
+ let itemId;
1062
+ if (itemName === "金币") {
1063
+ itemId = 0;
1064
+ } else {
1065
+ const entry = Object.entries(initDefaultItems).find(([name2]) => name2 === itemName);
1066
+ if (!entry) return `物品 ${itemName} 不存在`;
1067
+ itemId = entry[1].id;
1068
+ }
1069
+ const [existing] = await ctx.database.get("ggcevo_activity", { name: activityName });
1070
+ if (existing) return "同名活动已存在。";
1071
+ const start = new Date(options.start);
1072
+ const end = new Date(start.getTime() + options.duration * 864e5);
1073
+ const status = start <= /* @__PURE__ */ new Date() ? "进行中" : "未开始";
1074
+ await ctx.database.create("ggcevo_activity", {
1075
+ name: activityName,
965
1076
  description,
966
1077
  quantity,
967
- startTime,
968
- endTime,
969
- creator: session.userId,
970
- status
971
- // 动态状态
1078
+ itemId,
1079
+ startTime: start,
1080
+ endTime: end,
1081
+ status,
1082
+ creator: session.userId
972
1083
  });
973
- return `活动创建成功!
974
- ID:${activity.id}
975
- 状态:${status}`;
1084
+ return `活动【${activityName}】创建成功!奖励内容:${itemName} ×${quantity}。`;
976
1085
  });
977
- ctx.command("ggcevo/咕咕币活动", "查看进行中的咕咕币活动").action(async () => {
978
- const activities = await ctx.database.get("ggcevo_activity", {
979
- status: "进行中"
980
- // 完全依赖数据库状态
981
- }, {
982
- sort: { startTime: "desc" }
983
- });
984
- const formatTime = /* @__PURE__ */ __name((date) => date.toLocaleString("zh-CN", {
985
- timeZone: "Asia/Shanghai",
986
- year: "numeric",
987
- month: "2-digit",
988
- day: "2-digit"
989
- }), "formatTime");
990
- const output = activities.map((activity) => [
991
- `活动: ${activity.name}`,
992
- `时间:${formatTime(activity.startTime)} ~ ${formatTime(activity.endTime)}`,
993
- `描述:${activity.description}`,
994
- `奖励:${activity.quantity} 枚咕咕币`,
995
- "━━━━━━━━━━━━━━"
996
- ].join("\n"));
997
- return output.length ? output.join("\n\n") : "当前没有进行中的咕咕币活动";
1086
+ ctx.command("ggcevo/活动列表").action(async () => {
1087
+ const activities = await ctx.database.get(
1088
+ "ggcevo_activity",
1089
+ { status: "进行中" },
1090
+ { sort: { startTime: "desc" } }
1091
+ );
1092
+ const itemMap = /* @__PURE__ */ new Map();
1093
+ Object.entries(initDefaultItems).forEach(([name2, data]) => itemMap.set(data.id, name2));
1094
+ itemMap.set(0, "金币");
1095
+ return activities.length ? activities.map((a) => [
1096
+ `活动名称:${a.name}`,
1097
+ `活动时间:${formatDate(a.startTime)} - ${formatDate(a.endTime)}`,
1098
+ `活动描述:${a.description}`,
1099
+ `活动奖励:${a.quantity} × ${itemMap.get(a.itemId) || "未知物品"}`,
1100
+ "━".repeat(20)
1101
+ ].join("\n")).join("\n\n") : "当前没有进行中的活动。";
998
1102
  });
999
1103
  ctx.setInterval(async () => {
1000
1104
  const now = /* @__PURE__ */ new Date();
@@ -1077,7 +1181,7 @@ ID:${activity.id}
1077
1181
  }
1078
1182
  }
1079
1183
  }, 60 * 60 * 1e3);
1080
- ctx.command("ggcevo/胜点榜数据同步", { authority: 3 }).action(async () => {
1184
+ ctx.command("ggcevo/数据同步", { authority: 3 }).action(async () => {
1081
1185
  try {
1082
1186
  const ggcmap = await ctx.database.get("sc2arcade_map", { guildId: config.ggcqun });
1083
1187
  const lastdate = ggcmap[0].lastdate;
@@ -1132,13 +1236,13 @@ ID:${activity.id}
1132
1236
  lastdate: new Date(currentMaxDate.toISOString())
1133
1237
  });
1134
1238
  }
1135
- return "数据同步成功";
1239
+ return "✅ 胜点榜数据同步成功!";
1136
1240
  } catch (err) {
1137
1241
  console.error("错误:", err);
1138
1242
  return "服务器繁忙,请稍后尝试。";
1139
1243
  }
1140
1244
  });
1141
- ctx.command("ggcevo/胜点榜 [page]").alias("排行榜").usage("输入 rank [页码] 查看对应页的排行榜,每页10条").action(async (_, page) => {
1245
+ ctx.command("ggcevo/胜点榜 [page]").alias("排行榜").usage("输入 胜点榜 [页码] 查看对应页的排行榜,每页10条").action(async (_, page) => {
1142
1246
  const pageNum = parseInt(page) || 1;
1143
1247
  if (pageNum < 1) return "请输入有效的页码。";
1144
1248
  const offset = (pageNum - 1) * 10;
@@ -1160,9 +1264,8 @@ ID:${activity.id}
1160
1264
  (item, index) => `${offset + index + 1}. ${item.displayName} | 积分: ${item.rank} | 胜率: ${item.matches === 0 ? "0.00%" : (item.wins / item.matches * 100).toFixed(2) + "%"}`
1161
1265
  ).join("\n");
1162
1266
  return [
1163
- `🏆 GGCEvo S1赛季胜点榜 🏆`,
1164
- `本赛季从4月1日至5月15日23点`,
1165
- `数据同步时间: ${lastdate.toLocaleString("zh-CN", {
1267
+ `🏆 咕咕胜点榜 ${config.rankseason}赛季 🏆`,
1268
+ `数据最新同步时间: ${lastdate.toLocaleString("zh-CN", {
1166
1269
  timeZone: "Asia/Shanghai",
1167
1270
  year: "numeric",
1168
1271
  month: "2-digit",
@@ -1175,7 +1278,7 @@ ID:${activity.id}
1175
1278
  rankingText,
1176
1279
  "------------------------------",
1177
1280
  `第 ${pageNum} 页 / 共 ${totalPages} 页`,
1178
- pageNum < totalPages ? `输入 胜点榜 ${pageNum + 1} 查看下一页` : "已是最后一页"
1281
+ pageNum < totalPages ? `输入“胜点榜 ${pageNum + 1}”查看下一页` : "已是最后一页"
1179
1282
  ].join("\n");
1180
1283
  });
1181
1284
  ctx.command("ggcevo/排名 [player]", "查询个人排名").alias("rank").usage("输入“排名”查看自己的排名信息").action(async (argv, player) => {
@@ -1183,29 +1286,29 @@ ID:${activity.id}
1183
1286
  if (!player) {
1184
1287
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1185
1288
  if (!profile) {
1186
- return "您的 QQ 未绑定句柄。";
1289
+ return "您暂未绑定句柄。";
1187
1290
  }
1188
1291
  const { regionId, realmId, profileId } = profile;
1189
1292
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
1190
1293
  const [user] = await ctx.database.get("ggcevo_rank", {
1191
1294
  handle
1192
1295
  });
1193
- if (!user) return "未找到您的排名信息。";
1194
- if (user.Blacklist) return "❌您已经被禁止参加本赛季胜点榜。";
1296
+ if (!user) return "暂未找到您的排名信息。";
1297
+ if (user.Blacklist) return "❌ 您已经被禁止参加本赛季胜点榜。";
1195
1298
  const allRanks = await ctx.database.select("ggcevo_rank").where({ Blacklist: false }).orderBy("rank", "desc").execute();
1196
1299
  const userRank = allRanks.findIndex(
1197
1300
  (u) => u.handle === handle
1198
1301
  ) + 1;
1199
1302
  const isSafe = await checkSensitiveWord(user.name);
1200
1303
  const displayName = isSafe ? user.name : (user.name[0] || "") + "***";
1201
- return `🎮 您的 GGCEvo 排名信息 🎮
1304
+ return `🎮 您的咕咕胜点榜排名信息 🎮
1202
1305
  ------------------------------
1203
1306
  昵称:${displayName}
1204
1307
  句柄:${user.handle}
1205
1308
  当前积分:${user.rank}
1206
1309
  参赛次数:${user.matches} 次
1207
1310
  胜率: ${user.matches === 0 ? "0.00%" : (user.wins / user.matches * 100).toFixed(2) + "%"}
1208
- 全服排名:第 ${userRank}
1311
+ 全服排名:第 ${userRank}
1209
1312
  ------------------------------`;
1210
1313
  } else {
1211
1314
  const parsedUser = import_koishi.h.parse(player)[0];
@@ -1216,51 +1319,67 @@ ID:${activity.id}
1216
1319
  let targetUsername = parsedUser.attrs.name || targetUserId;
1217
1320
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: targetUsername });
1218
1321
  if (!profile) {
1219
- return "对方的 QQ 未绑定句柄。";
1322
+ return "对方暂未绑定句柄。";
1220
1323
  }
1221
1324
  const { regionId, realmId, profileId } = profile;
1222
1325
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
1223
1326
  const [user] = await ctx.database.get("ggcevo_rank", {
1224
1327
  handle
1225
1328
  });
1226
- if (!user) return "未找到对方的排名信息。";
1227
- if (user.Blacklist) return "❌对方已经被禁止参加本赛季胜点榜。";
1329
+ if (!user) return "暂未找到对方的排名信息。";
1330
+ if (user.Blacklist) return "❌ 对方已经被禁止参加本赛季胜点榜。";
1228
1331
  const allRanks = await ctx.database.select("ggcevo_rank").where({ Blacklist: false }).orderBy("rank", "desc").execute();
1229
1332
  const userRank = allRanks.findIndex(
1230
1333
  (u) => u.handle === handle
1231
1334
  ) + 1;
1232
1335
  const isSafe = await checkSensitiveWord(user.name);
1233
1336
  const displayName = isSafe ? user.name : (user.name[0] || "") + "***";
1234
- return `🎮 对方的 GGCEvo 排名信息 🎮
1337
+ return `🎮 对方的咕咕胜点榜排名信息 🎮
1235
1338
  ------------------------------
1236
1339
  昵称:${displayName}
1237
1340
  句柄:${user.handle}
1238
1341
  当前积分:${user.rank}
1239
1342
  参赛次数:${user.matches} 次
1240
1343
  胜率: ${user.matches === 0 ? "0.00%" : (user.wins / user.matches * 100).toFixed(2) + "%"}
1241
- 全服排名:第 ${userRank}
1344
+ 全服排名:第 ${userRank}
1242
1345
  ------------------------------`;
1243
1346
  }
1244
1347
  });
1245
- ctx.command("ggcevo/给予 <handle> <itemId:number> <amount:number>", "增加指定用户的物品", { authority: 3 }).action(async (_, handle, itemId, amount) => {
1348
+ ctx.command("ggcevo/给予 <handle> <itemName:string> <amount:number>", "增加用户物品/金币", { authority: 3 }).action(async (_, handle, itemName, amount) => {
1246
1349
  try {
1247
- if (!handle || !itemId || !amount) {
1248
- return `请输入正确的指令格式`;
1350
+ if (!handle || !itemName || amount <= 0) {
1351
+ return "参数格式错误,正确格式:给予 用户句柄 物品名称 数量";
1249
1352
  }
1250
- const itemIdToNameMap = Object.fromEntries(
1251
- Object.entries(initDefaultItems).map(([name2, item]) => [item.id, name2])
1252
- );
1253
- const itemName = itemIdToNameMap[itemId];
1254
- const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId });
1353
+ if (itemName === "金币") {
1354
+ const [signData] = await ctx.database.get("ggcevo_sign", { handle });
1355
+ await ctx.database.upsert("ggcevo_sign", [{
1356
+ handle,
1357
+ totalRewards: (signData?.totalRewards || 0) + Math.floor(amount),
1358
+ lastSign: signData?.lastSign || /* @__PURE__ */ new Date(0),
1359
+ // 保持原有最后签到时间
1360
+ monthlyDays: signData?.monthlyDays || 0
1361
+ // 保持月签到天数
1362
+ }]);
1363
+ return `成功为 ${handle} 添加 ${amount} 金币!当前金币总数:${(signData?.totalRewards || 0) + amount}`;
1364
+ }
1365
+ const validItems = Object.keys(initDefaultItems);
1366
+ if (!validItems.includes(itemName)) {
1367
+ return `无效物品名称,可用物品:${validItems.join("、")}`;
1368
+ }
1369
+ const itemId = initDefaultItems[itemName].id;
1370
+ const [backpack] = await ctx.database.get("ggcevo_backpack", {
1371
+ handle,
1372
+ itemId
1373
+ });
1255
1374
  await ctx.database.upsert("ggcevo_backpack", [{
1256
1375
  handle,
1257
1376
  itemId,
1258
- quantity: (backpack?.quantity || 0) + amount
1377
+ quantity: (backpack?.quantity || 0) + Math.floor(amount)
1259
1378
  }], ["handle", "itemId"]);
1260
- return `成功为 ${handle} 增加 ${amount} 个${itemName}!`;
1379
+ return `成功为 ${handle} 添加 ${amount} 个${itemName}!当前总数:${(backpack?.quantity || 0) + amount}`;
1261
1380
  } catch (err) {
1262
- console.error("数据库操作失败:", err);
1263
- return "操作失败,请稍后再试";
1381
+ console.error("[给予命令错误]", err);
1382
+ return "操作失败:" + (err instanceof Error ? err.message : "数据库异常");
1264
1383
  }
1265
1384
  });
1266
1385
  ctx.command("ggcevo/违规记录 [user]", "违规记录查询").usage("输入 违规记录 [@用户] -p 页码 查看处罚记录,每页1条").option("p", "-p <page:number> 指定页码").action(async (argv) => {
@@ -1270,7 +1389,7 @@ ID:${activity.id}
1270
1389
  let handle;
1271
1390
  if (!user) {
1272
1391
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1273
- if (!profile) return "您的 QQ 未绑定句柄。";
1392
+ if (!profile) return "您暂未绑定句柄。";
1274
1393
  handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1275
1394
  } else {
1276
1395
  const parsedUser = import_koishi.h.parse(user)[0];
@@ -1281,7 +1400,7 @@ ID:${activity.id}
1281
1400
  let targetUsername = parsedUser.attrs.name || targetUserId;
1282
1401
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: targetUsername });
1283
1402
  if (!profile) {
1284
- return "对方的 QQ 未绑定句柄。";
1403
+ return "对方暂未绑定句柄。";
1285
1404
  }
1286
1405
  const { regionId, realmId, profileId } = profile;
1287
1406
  handle = `${regionId}-S2-${realmId}-${profileId}`;
@@ -1313,17 +1432,17 @@ ID:${activity.id}
1313
1432
  "------------------------------",
1314
1433
  recordText,
1315
1434
  "------------------------------",
1316
- pageNum < totalPages ? `输入 违规记录 -p ${pageNum + 1} 查看下一条` : "已是最后一页"
1435
+ pageNum < totalPages ? `输入 违规记录 (@用户) -p ${pageNum + 1} 查看下一条` : "已是最后一页"
1317
1436
  ].join("\n");
1318
1437
  });
1319
1438
  ctx.command("ggcevo/兑换", "兑换物品").action(async ({ session }) => {
1320
1439
  try {
1321
1440
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1322
- if (!profile) return "您的 QQ 未绑定句柄";
1441
+ if (!profile) return "您暂未绑定句柄";
1323
1442
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1324
1443
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
1325
1444
  if (existingEntries.length > 0) {
1326
- return `❌拒绝访问,您已被列入活动黑名单。`;
1445
+ return `❌ 拒绝访问,您已被列入黑名单。`;
1327
1446
  }
1328
1447
  const currentSeason = config.rankseason;
1329
1448
  const qualityGroups = {};
@@ -1349,7 +1468,7 @@ ID:${activity.id}
1349
1468
  qualityGroups[quality].push(`${itemName}${quantityText}`);
1350
1469
  }
1351
1470
  const order = ["t0", "t1", "t2", "t3"];
1352
- let message = "请在30秒内输入可兑换物品(显示格式:物品名 [剩余/总量]):\n";
1471
+ let message = "请在30秒内输入可兑换物品(显示格式:物品名 [剩余/总量]):\n";
1353
1472
  for (const quality of order) {
1354
1473
  const items = qualityGroups[quality] || [];
1355
1474
  if (!items.length) continue;
@@ -1360,11 +1479,11 @@ ${items.join("、")}
1360
1479
  }
1361
1480
  await session.send(message);
1362
1481
  const name2 = await session.prompt(3e4);
1363
- if (!name2) return "输入超时,请重新输入指令。";
1482
+ if (!name2) return "输入超时,请重新输入。";
1364
1483
  const configname = itemConfig[name2];
1365
- if (!configname) return "无效的物品名称,请重新输入";
1484
+ if (!configname) return "无效的物品名称,请重新输入。";
1366
1485
  const userRecords = await ctx.database.get("ggcevo_exchange", { handle, item: name2 });
1367
- if (userRecords.length > 0) return "您已经兑换过该物品";
1486
+ if (userRecords.length > 0) return "您已经兑换过该物品。";
1368
1487
  if (configname.quantity !== void 0 && (configname.isLimited || config.ignoreGlobalLimit === false)) {
1369
1488
  const queryConditions = {
1370
1489
  item: name2,
@@ -1374,7 +1493,7 @@ ${items.join("、")}
1374
1493
  queryConditions.season = currentSeason;
1375
1494
  }
1376
1495
  const globalRecords = await ctx.database.get("ggcevo_exchange", queryConditions);
1377
- if (globalRecords.length >= configname.quantity) return "该物品已被兑换尽";
1496
+ if (globalRecords.length >= configname.quantity) return "该物品已被兑换完了。";
1378
1497
  }
1379
1498
  const qualityMap = { "t3": 4, "t2": 5, "t1": 6, "t0": 7 };
1380
1499
  const petItems = new Set(
@@ -1397,7 +1516,7 @@ ${items.join("、")}
1397
1516
  }
1398
1517
  const [coupon] = await ctx.database.get("ggcevo_backpack", { handle, itemId });
1399
1518
  if (!coupon || coupon.quantity < cost) {
1400
- const requireMsg = petItems.has(name2) ? `需要 1 个${configname.quality}级宠物扭蛋 或 ${configname.cost}个兑奖券` : `需要 ${configname.cost}个兑奖券`;
1519
+ const requireMsg = petItems.has(name2) ? `需要1个${configname.quality}级宠物扭蛋 或${configname.cost}张兑奖券` : `需要${configname.cost}张兑奖券`;
1401
1520
  return `${requireMsg}
1402
1521
  当前持有:${coupon?.quantity || 0}个${couponName}`;
1403
1522
  }
@@ -1420,7 +1539,7 @@ ${items.join("、")}
1420
1539
  season: currentSeason
1421
1540
  });
1422
1541
  });
1423
- return `兑换成功!消耗 ${cost} 个${couponName}获得【${name2}】`;
1542
+ return `兑换成功!消耗${cost}个${couponName}获得【${name2}】`;
1424
1543
  } catch (error) {
1425
1544
  console.error("兑换失败:", error);
1426
1545
  return "兑换失败";
@@ -1428,7 +1547,7 @@ ${items.join("、")}
1428
1547
  });
1429
1548
  ctx.command("ggcevo/兑换记录").action(async ({ session }) => {
1430
1549
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1431
- if (!profile) return "您的 QQ 未绑定句柄";
1550
+ if (!profile) return "您暂未绑定句柄";
1432
1551
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1433
1552
  const exchanges = await ctx.database.get("ggcevo_exchange", { handle });
1434
1553
  if (!exchanges.length) return "您暂无兑换记录";
@@ -1447,16 +1566,16 @@ ${output}`;
1447
1566
  });
1448
1567
  ctx.command("ggcevo/兑换扭蛋币").action(async ({ session }) => {
1449
1568
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1450
- if (!profile) return "您的 QQ 未绑定句柄";
1569
+ if (!profile) return "您暂未绑定句柄。";
1451
1570
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1452
1571
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
1453
1572
  if (existingEntries.length > 0) {
1454
- return `❌拒绝访问,您已被列入活动黑名单。`;
1573
+ return `❌ 拒绝访问,您已被列入黑名单。`;
1455
1574
  }
1456
1575
  const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 3 });
1457
1576
  const [coupon] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 2 });
1458
1577
  if (!coupon || coupon.quantity < 3) {
1459
- return `兑换扭蛋币需要 3 张兑奖券,当前持有:${coupon?.quantity || 0}`;
1578
+ return `兑换扭蛋币需要3张兑奖券,当前持有:${coupon?.quantity || 0}`;
1460
1579
  }
1461
1580
  await ctx.database.set(
1462
1581
  "ggcevo_backpack",
@@ -1468,19 +1587,19 @@ ${output}`;
1468
1587
  itemId: 3,
1469
1588
  quantity: (backpack?.quantity || 0) + 1
1470
1589
  }]);
1471
- return `兑换成功!消耗 3 张兑奖券获得 1 个扭蛋币`;
1590
+ return `兑换成功!消耗3张兑奖券获得1枚扭蛋币`;
1472
1591
  });
1473
1592
  ctx.command("ggcevo/扭蛋").action(async (argv) => {
1474
1593
  const session = argv.session;
1475
1594
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1476
1595
  if (!profile) {
1477
- return "您的 QQ 未绑定句柄。";
1596
+ return "您暂未绑定句柄。";
1478
1597
  }
1479
1598
  const { regionId, realmId, profileId } = profile;
1480
1599
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
1481
1600
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
1482
1601
  if (existingEntries.length > 0) {
1483
- return `❌拒绝访问,您已被列入活动黑名单。`;
1602
+ return `❌ 拒绝访问,您已被列入黑名单。`;
1484
1603
  }
1485
1604
  const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 3 });
1486
1605
  if (!backpack || backpack.quantity < 1) {
@@ -1506,16 +1625,16 @@ ${output}`;
1506
1625
  itemId: itemData.id,
1507
1626
  quantity: currentQuantity + 1
1508
1627
  }]);
1509
- return `🎉 恭喜获得:${itemName}`;
1628
+ return `🎉 恭喜您获得:${itemName}`;
1510
1629
  });
1511
- ctx.command("ggcevo/活动拉黑", "添加用户到活动黑名单").action(async (argv) => {
1630
+ ctx.command("ggcevo/拉黑", "添加用户到黑名单").action(async (argv) => {
1512
1631
  const session = argv.session;
1513
1632
  if (!ctx.config.admins.includes(session.userId)) {
1514
- return "⚠️ 没有操作权限,请联系机器人管理员";
1633
+ return "⚠️ 没有操作权限。";
1515
1634
  }
1516
1635
  await session.send("请在30秒内输入需要拉黑的句柄:\n(句柄格式为: [区域ID]-S2-[服务器ID]-[档案ID])");
1517
1636
  const handle = await session.prompt(3e4);
1518
- if (!handle) return "输入超时,请重新输入指令。";
1637
+ if (!handle) return "输入超时,请重新输入。";
1519
1638
  try {
1520
1639
  const handleRegex = /^([1235])-S2-([12])-(\d+)$/;
1521
1640
  if (!handleRegex.test(handle)) {
@@ -1523,40 +1642,40 @@ ${output}`;
1523
1642
  }
1524
1643
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
1525
1644
  if (existingEntries.length > 0) {
1526
- return `${handle} 已在活动黑名单中`;
1645
+ return `${handle}已在黑名单中。`;
1527
1646
  }
1528
1647
  await ctx.database.create("ggcevo_blacklist", {
1529
1648
  handle,
1530
1649
  createdAt: /* @__PURE__ */ new Date()
1531
1650
  });
1532
- return `✅ 用户 ${handle} 已被列入活动黑名单(永久)`;
1651
+ return `✅ 用户${handle}已被列入黑名单。`;
1533
1652
  } catch (error) {
1534
1653
  console.error("黑名单操作失败:", error);
1535
1654
  return "操作失败,请稍后重试。错误详情已记录";
1536
1655
  }
1537
1656
  });
1538
- ctx.command("ggcevo/胜点榜拉黑", "添加用户到胜点榜黑名单").action(async (argv) => {
1657
+ ctx.command("ggcevo/标记", "标记用户到胜点榜黑名单").action(async (argv) => {
1539
1658
  const session = argv.session;
1540
1659
  if (!ctx.config.admins.includes(session.userId)) {
1541
- return "⚠️ 没有操作权限,请联系机器人管理员";
1660
+ return "⚠️ 没有操作权限。";
1542
1661
  }
1543
- await session.send("请在30秒内输入需要拉黑的句柄:\n(句柄格式为: [区域ID]-S2-[服务器ID]-[档案ID])");
1662
+ await session.send("请在30秒内输入需要标记的句柄:\n(句柄格式为: [区域ID]-S2-[服务器ID]-[档案ID])");
1544
1663
  const handle = await session.prompt(3e4);
1545
- if (!handle) return "输入超时,请重新输入指令。";
1664
+ if (!handle) return "输入超时,请重新输入。";
1546
1665
  try {
1547
1666
  const handleRegex = /^([1235])-S2-([12])-(\d+)$/;
1548
1667
  if (!handleRegex.test(handle)) {
1549
- return "句柄格式错误,请重新输入";
1668
+ return "句柄格式错误,请重新输入。";
1550
1669
  }
1551
1670
  const existingEntries = await ctx.database.get("ggcevo_rank", { handle, Blacklist: true });
1552
1671
  if (existingEntries.length > 0) {
1553
- return `${handle} 已在胜点榜黑名单中`;
1672
+ return `${handle}已被标记在咕咕胜点榜黑名单中。`;
1554
1673
  }
1555
1674
  await ctx.database.upsert("ggcevo_rank", [{
1556
1675
  handle,
1557
1676
  Blacklist: true
1558
1677
  }]);
1559
- return `✅ 用户 ${handle} 已被列入胜点榜黑名单(仅限当前赛季)`;
1678
+ return `✅ 用户${handle}已被标记在咕咕胜点榜黑名单。`;
1560
1679
  } catch (error) {
1561
1680
  console.error("黑名单操作失败:", error);
1562
1681
  return "操作失败,请稍后重试。错误详情已记录";
@@ -1565,14 +1684,14 @@ ${output}`;
1565
1684
  ctx.command("ggcevo/成就").action(async ({ session }) => {
1566
1685
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1567
1686
  if (!profile) {
1568
- return "您的 QQ 未绑定句柄。";
1687
+ return "您暂未绑定句柄。";
1569
1688
  }
1570
1689
  const { regionId, realmId, profileId } = profile;
1571
1690
  const achievements = await ctx.database.get("ggcevo_achievements", {
1572
1691
  handle: `${regionId}-S2-${realmId}-${profileId}`
1573
1692
  });
1574
1693
  if (!achievements.length) {
1575
- return "你还没有获得任何成就哦~";
1694
+ return "你还没有获得任何成就。";
1576
1695
  }
1577
1696
  const achievementList = achievements.map((achievement) => {
1578
1697
  const date = new Date(achievement.gaintime);
@@ -1590,7 +1709,7 @@ ${achievementList.join("\n")}`;
1590
1709
  const session = argv.session;
1591
1710
  const output = [];
1592
1711
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1593
- if (!profile) return "您的 QQ 未绑定游戏句柄。";
1712
+ if (!profile) return "您暂未绑定句柄。";
1594
1713
  const { regionId, realmId, profileId } = profile;
1595
1714
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
1596
1715
  output.push(`🎮 游戏句柄:${handle}
@@ -1721,22 +1840,22 @@ ${achievementList.join("\n")}`;
1721
1840
  ctx.command("ggcevo/pk [user]", "发起玩家对战").alias("挑战").action(async (argv, user) => {
1722
1841
  try {
1723
1842
  const session = argv.session;
1724
- if (!user) return '缺少参数,请输入"pk @指定对战玩家"';
1843
+ if (!user) return "缺少参数,请输入“pk @指定pk玩家”。";
1725
1844
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1726
- if (!profile) return "您的 QQ 未绑定句柄。";
1845
+ if (!profile) return "您暂未绑定句柄。";
1727
1846
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1728
1847
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
1729
1848
  if (existingEntries.length > 0) {
1730
- return `❌拒绝访问,您已被列入活动黑名单。`;
1849
+ return `❌ 拒绝访问,您已被列入黑名单。`;
1731
1850
  }
1732
1851
  const parsedUser = import_koishi.h.parse(user)[0];
1733
- if (!parsedUser || parsedUser.type !== "at" || !parsedUser.attrs.id) return '参数格式错误,请输入"pk @指定对战玩家"';
1852
+ if (!parsedUser || parsedUser.type !== "at" || !parsedUser.attrs.id) return "参数格式错误,请输入“pk @指定pk玩家”。";
1734
1853
  const targetUserId = parsedUser.attrs.id;
1735
1854
  const [targetprofile] = await ctx.database.get("sc2arcade_player", { userId: targetUserId });
1736
- if (!targetprofile) return "对方尚未绑定句柄";
1855
+ if (!targetprofile) return "对方尚未绑定句柄。";
1737
1856
  const initiatorHandle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1738
1857
  const targetHandle = `${targetprofile.regionId}-S2-${targetprofile.realmId}-${targetprofile.profileId}`;
1739
- if (initiatorHandle === targetHandle) return "不能挑战自己哦~";
1858
+ if (initiatorHandle === targetHandle) return "不能挑战自己。";
1740
1859
  let initiatorPK = {
1741
1860
  handle: initiatorHandle,
1742
1861
  total: 0,
@@ -1767,17 +1886,17 @@ ${achievementList.join("\n")}`;
1767
1886
  if (dbTarget) Object.assign(targetPK, dbTarget);
1768
1887
  });
1769
1888
  if (!initiatorPK.enable) {
1770
- return "您已关闭PK功能,无法发起挑战";
1889
+ return "您已关闭PK功能,无法发起挑战。";
1771
1890
  }
1772
1891
  if (!targetPK.enable) {
1773
- return "对方已关闭PK功能,无法接受挑战";
1892
+ return "对方已关闭PK功能,无法接受挑战。";
1774
1893
  }
1775
1894
  const now = convertUTCtoChinaTime(/* @__PURE__ */ new Date());
1776
1895
  if (!isSameDate(convertUTCtoChinaTime(initiatorPK.lastPK), now)) {
1777
1896
  initiatorPK.todayCount = 0;
1778
1897
  }
1779
1898
  if (initiatorPK.todayCount >= config.dailyPKLimit) {
1780
- return `今日挑战次数已用尽(${config.dailyPKLimit}次/日)`;
1899
+ return `今日挑战次数已用尽(${config.dailyPKLimit}次/日)。`;
1781
1900
  }
1782
1901
  const nowChina = convertUTCtoChinaTime(/* @__PURE__ */ new Date());
1783
1902
  const todayStart = new Date(nowChina);
@@ -1790,7 +1909,7 @@ ${achievementList.join("\n")}`;
1790
1909
  date: { $gte: adjustedTime }
1791
1910
  }).execute((row) => import_koishi.$.count(row.id));
1792
1911
  if (sameOpponentCount > 0) {
1793
- return "您今天已经挑战过该玩家,请明天再试";
1912
+ return "您今天已经挑战过该玩家,请明天再试。";
1794
1913
  }
1795
1914
  }
1796
1915
  if (config.maxDailyBeChallenged > 0) {
@@ -1799,7 +1918,7 @@ ${achievementList.join("\n")}`;
1799
1918
  date: { $gte: adjustedTime }
1800
1919
  }).execute((row) => import_koishi.$.count(row.id));
1801
1920
  if (beChallengedCount >= config.maxDailyBeChallenged) {
1802
- return `该玩家今日已被挑战太多次(最多${config.maxDailyBeChallenged}次)`;
1921
+ return `该玩家今日已被挑战太多次(最多${config.maxDailyBeChallenged}次)。`;
1803
1922
  }
1804
1923
  }
1805
1924
  const [initiatorData, targetData] = await Promise.all([
@@ -1816,8 +1935,8 @@ ${achievementList.join("\n")}`;
1816
1935
  ]);
1817
1936
  const initiatorGold = initiatorSign[0]?.totalRewards || 0;
1818
1937
  const targetGold = targetSign[0]?.totalRewards || 0;
1819
- if (initiatorGold < 100) return "发起者需要至少100金币才能挑战!";
1820
- if (targetGold < 100) return "对方金币不足100,无法应战";
1938
+ if (initiatorGold < 100) return "发起者需要至少100金币才能发起挑战。";
1939
+ if (targetGold < 100) return "对方金币不足100,无法应战。";
1821
1940
  const rankDiff = initiatorRank - targetRank;
1822
1941
  const clampedDiff = Math.min(Math.max(rankDiff, -1e4), 1e4);
1823
1942
  const winRate = Math.min(Math.max(50 + clampedDiff * 5e-3, 5), 95);
@@ -1874,8 +1993,8 @@ ${achievementList.join("\n")}`;
1874
1993
  });
1875
1994
  const result = [
1876
1995
  `⚔️【对战结果】${isWin ? "胜利" : "失败"}`,
1877
- `🏅 挑战者:${initiatorRankname}(积分 ${initiatorRank})`,
1878
- `🛡️ 应战者:${targetRankname}(积分 ${targetRank})`,
1996
+ `🏅 挑战者:${initiatorRankname}(积分 ${initiatorRank})`,
1997
+ `🛡️ 应战者:${targetRankname}(积分 ${targetRank})`,
1879
1998
  `📊 胜率预测:${winRate.toFixed(1)}%`,
1880
1999
  `🎰 金币变动:${stealPercentage}%`
1881
2000
  ];
@@ -1889,12 +2008,8 @@ ${achievementList.join("\n")}`;
1889
2008
  });
1890
2009
  ctx.command("ggcevo/切换pk状态", "切换玩家对战状态").action(async ({ session }) => {
1891
2010
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1892
- if (!profile) return "您的 QQ 未绑定句柄";
2011
+ if (!profile) return "您暂未绑定句柄。";
1893
2012
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1894
- const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
1895
- if (existingEntries.length > 0) {
1896
- return `❌拒绝访问,您已被列入活动黑名单。`;
1897
- }
1898
2013
  const [pkRecord] = await ctx.database.get("ggcevo_pk", { handle }) || [null];
1899
2014
  const currentState = pkRecord?.enable ?? true;
1900
2015
  const lastToggle = pkRecord?.lastToggle ?? /* @__PURE__ */ new Date(0);
@@ -1915,10 +2030,10 @@ ${achievementList.join("\n")}`;
1915
2030
  const diffDays = Math.floor((now.getTime() - lastToggleTime.getTime()) / (1e3 * 3600 * 24));
1916
2031
  if (diffDays < 3 && lastToggleTime.getTime() !== 0) {
1917
2032
  const remaining = 3 - diffDays;
1918
- return `状态切换冷却中,${remaining}天后再试(下次可切换时间:${new Date(lastToggle.getTime() + 3 * 864e5).toLocaleDateString("zh-CN")})`;
2033
+ return `状态切换冷却中,${remaining}天后再试(下次可切换时间:${new Date(lastToggle.getTime() + 3 * 864e5).toLocaleDateString("zh-CN")})。`;
1919
2034
  }
1920
2035
  const action = currentState ? "关闭" : "开启";
1921
- await session.send(`您当前的PK状态为【${currentState ? "开启" : "关闭"}】,确认要${action}吗?(30秒内回复“是”确认)`);
2036
+ await session.send(`您当前的PK状态为【${currentState ? "开启" : "关闭"}】,确认要${action}吗?(s30秒内回复“是”确认)`);
1922
2037
  const confirm = await session.prompt(3e4);
1923
2038
  if (confirm !== "是") return "已取消操作";
1924
2039
  await ctx.database.upsert("ggcevo_pk", [{
@@ -1937,8 +2052,26 @@ ${achievementList.join("\n")}`;
1937
2052
  day: "2-digit"
1938
2053
  })}`;
1939
2054
  });
1940
- ctx.command("ggcevo/武器库").action(async ({ session }) => {
1941
- const items = Object.entries(weaponConfig).map(([name2, config2]) => {
2055
+ ctx.command("ggcevo/武器库 [type]").usage("输入“武器库”查看类型,或“武器库 类型”查看详细武器信息").action(async ({ session }, type) => {
2056
+ const typeStats = Object.values(weaponConfig).reduce((stats, weapon) => {
2057
+ stats[weapon.type] = (stats[weapon.type] || 0) + 1;
2058
+ return stats;
2059
+ }, {});
2060
+ if (!type) {
2061
+ return [
2062
+ "🏪 咕咕军火武器库分类 🏪",
2063
+ '使用 "武器库 类型名称" 查看详细列表',
2064
+ "====================",
2065
+ ...Object.entries(typeStats).map(([typeName, count]) => `▸ ${typeName} (${count}种)`)
2066
+ ].join("\n");
2067
+ }
2068
+ const validTypes = Object.keys(typeStats);
2069
+ const normalizedType = validTypes.find((t) => t === type);
2070
+ if (!normalizedType) {
2071
+ return `无效武器类型,可用类型:
2072
+ ${validTypes.join("、")}`;
2073
+ }
2074
+ const items = Object.entries(weaponConfig).filter(([_, config2]) => config2.type === normalizedType).map(([name2, config2]) => {
1942
2075
  const tagEffectsDesc = config2.tagEffects ? Object.entries(config2.tagEffects).map(([tag, multiplier]) => `▸ 对${tag}目标造成${(multiplier * 100).toFixed(0)}%伤害`).join("\n") : "▸ 无特殊加成效果";
1943
2076
  return [
1944
2077
  `【${name2}】`,
@@ -1951,7 +2084,7 @@ ${achievementList.join("\n")}`;
1951
2084
  ].join("\n");
1952
2085
  });
1953
2086
  return [
1954
- "🏪 咕咕军火武器库 🏪",
2087
+ `🏪 咕咕军火武器库 - ${normalizedType} 🏪`,
1955
2088
  "使用“购买 武器名称”命令进行购买",
1956
2089
  "====================",
1957
2090
  ...items
@@ -2009,15 +2142,14 @@ ${achievementList.join("\n")}`;
2009
2142
  ].join("\n");
2010
2143
  }));
2011
2144
  return [
2012
- "🛡️ 当前武器列表",
2145
+ "🛡️ 当前拥有的武器列表",
2013
2146
  '使用"装备 武器名称"切换武器',
2014
2147
  "⚡表示当前装备武器",
2015
2148
  "────────────────",
2016
2149
  ...weaponDetails.length ? weaponDetails : ["空空如也,快去武器库看看吧!"],
2017
2150
  "────────────────",
2018
2151
  "💡 武器效果说明:",
2019
- " 已装备武器会在战斗中生效",
2020
- "🔧 改装效果仅在战斗时计算"
2152
+ "🔧 改装效果会在战斗中生效"
2021
2153
  ].join("\n");
2022
2154
  });
2023
2155
  ctx.command("ggcevo/装备 <weapon>").action(async ({ session }, weapon) => {
@@ -2159,6 +2291,7 @@ ${achievementList.join("\n")}`;
2159
2291
  });
2160
2292
  ctx.command("ggcevo/攻击 <targetType>").usage("使用 攻击 主宰/zz 或 攻击 子代/zd 来选择攻击目标").action(async (argv, targetType) => {
2161
2293
  const session = argv.session;
2294
+ let broadcastMessage = null;
2162
2295
  const targetAliases = {
2163
2296
  "主宰": ["主宰", "zz"],
2164
2297
  "子代": ["子代", "zd"]
@@ -2172,10 +2305,10 @@ ${achievementList.join("\n")}`;
2172
2305
  }
2173
2306
  if (!normalizedTarget) return "请指定正确的攻击目标:主宰/zz 或 子代/zd";
2174
2307
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
2175
- if (!profile) return "您的 QQ 未绑定句柄。";
2308
+ if (!profile) return "您暂未绑定句柄。";
2176
2309
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
2177
2310
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
2178
- if (existingEntries.length > 0) return "❌拒绝访问,您已被列入活动黑名单。";
2311
+ if (existingEntries.length > 0) return "❌ 拒绝访问,您已被列入黑名单。";
2179
2312
  const config2 = ctx.config;
2180
2313
  const unlimitedBossAttack = config2.unlimitedBossAttack;
2181
2314
  if (!unlimitedBossAttack) {
@@ -2192,93 +2325,17 @@ ${achievementList.join("\n")}`;
2192
2325
  handle,
2193
2326
  equipped: true
2194
2327
  });
2195
- if (!equippedWeapon) return "请先装备武器再挑战主宰";
2328
+ if (!equippedWeapon) return "请先装备武器再挑战主宰。";
2196
2329
  const activeBosses = await ctx.database.get("ggcevo_boss", { isActive: true });
2197
- if (!activeBosses.length) return "当前没有存活的主宰";
2330
+ if (!activeBosses.length) return "当前没有存活的主宰。";
2198
2331
  const targetBoss = normalizedTarget === "主宰" ? activeBosses.find((b) => b.type === "主宰") : activeBosses.find((b) => b.type === "子代");
2199
- if (!targetBoss) return `当前没有可攻击的${normalizedTarget === "主宰" ? "主宰" : "子代"}`;
2332
+ if (!targetBoss) return `当前没有可攻击的${normalizedTarget === "主宰" ? "主宰" : "子代"}。`;
2200
2333
  const bossGroup = bossPool.find((group) => group.main.id === targetBoss.groupId);
2201
- if (!bossGroup) return "无法获取BOSS组信息,请联系管理员";
2334
+ if (!bossGroup) return "无法获取BOSS组信息,请联系管理员。";
2202
2335
  const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
2203
2336
  const [weaponName, weaponData] = weaponConfigEntry;
2204
- let damage = weaponData.damage * (1 + 0.1 * equippedWeapon.level);
2205
- let totalModAdd = 0;
2206
- let hasCrit = false;
2207
- let hasCrystal = false;
2208
- let hasOverload = false;
2209
- equippedWeapon.installedMods.forEach((mod) => {
2210
- if (mod === "动能增幅") {
2211
- totalModAdd += 0.2;
2212
- }
2213
- if (mod === "裂甲核心") {
2214
- if (weaponName === modConfig["裂甲核心"].exclusiveTo) {
2215
- totalModAdd += 0.4;
2216
- }
2217
- }
2218
- if (mod === "棱镜水晶") {
2219
- hasCrystal = true;
2220
- }
2221
- if (mod === "棱镜超载核心") {
2222
- if (weaponName === modConfig["棱镜超载核心"].exclusiveTo) {
2223
- hasOverload = true;
2224
- }
2225
- }
2226
- });
2227
- const totalCritRate = (hasCrystal ? 20 : 0) + (hasOverload ? 80 : 0);
2228
- if (totalCritRate > 0 && Math.random() < totalCritRate / 100) {
2229
- hasCrit = true;
2230
- totalModAdd += 1;
2231
- }
2232
- damage = damage * (1 + totalModAdd);
2233
- const targetBossConfig = targetBoss.type === "主宰" ? bossGroup.main : bossGroup.minions[0];
2234
- if (targetBossConfig.tags && targetBossConfig.tags.length > 0) {
2235
- const armorTags = targetBossConfig.tags.filter((tag) => ["重甲", "轻甲", "护盾"].includes(tag));
2236
- const voidTags = targetBossConfig.tags.filter((tag) => ["惧热", "惧寒"].includes(tag));
2237
- const typeTags = targetBossConfig.tags.filter((tag) => ["生物", "机械", "灵能"].includes(tag));
2238
- let totalTagAdd = 0;
2239
- armorTags.forEach((tag) => {
2240
- let effectValue = weaponData.tagEffects?.[tag] ?? 1;
2241
- if (tag === "重甲" && equippedWeapon.installedMods.includes("裂甲核心")) {
2242
- effectValue = 1.2;
2243
- }
2244
- totalTagAdd += effectValue - 1;
2245
- });
2246
- voidTags.forEach((tag) => {
2247
- const effectValue = weaponData.tagEffects?.[tag] ?? 1;
2248
- totalTagAdd += effectValue - 1;
2249
- });
2250
- typeTags.forEach((tag) => {
2251
- const effectValue = weaponData.tagEffects?.[tag] ?? 1;
2252
- totalTagAdd += effectValue - 1;
2253
- });
2254
- damage *= 1 + totalTagAdd;
2255
- }
2256
- if (targetBossConfig.passive?.length) {
2257
- let passiveEffect = 0;
2258
- const effectivePassives = [...targetBossConfig.passive];
2259
- if (targetBoss.type === "主宰" && effectivePassives.includes("孤立无援")) {
2260
- const activeMinions = await ctx.database.get("ggcevo_boss", {
2261
- groupId: targetBoss.groupId,
2262
- type: "子代",
2263
- isActive: true
2264
- });
2265
- if (activeMinions.length !== 0) {
2266
- effectivePassives.splice(effectivePassives.indexOf("孤立无援"), 1);
2267
- }
2268
- }
2269
- effectivePassives.forEach((passive) => {
2270
- const effect = passiveConfig[passive]?.effect || 0;
2271
- passiveEffect += effect;
2272
- });
2273
- damage *= 1 + passiveEffect;
2274
- }
2275
- const [rankRecord] = await ctx.database.get("ggcevo_rank", { handle });
2276
- if (rankRecord?.rank > 0) {
2277
- const rankBonus = Math.floor(rankRecord.rank / 400) * 0.01;
2278
- damage *= 1 + rankBonus;
2279
- }
2280
- damage = Math.round(damage);
2281
- const actualDamage = Math.min(damage, targetBoss.HP);
2337
+ const { damage: baseDamage, hasCrit } = await calculateTotalDamage(ctx, session, equippedWeapon, targetBoss);
2338
+ const actualDamage = Math.min(baseDamage, targetBoss.HP);
2282
2339
  const updatedHP = targetBoss.HP - actualDamage;
2283
2340
  const isDefeated = updatedHP <= 0;
2284
2341
  const [existingRecord] = await ctx.database.get("ggcevo_boss_damage", {
@@ -2290,6 +2347,7 @@ ${achievementList.join("\n")}`;
2290
2347
  handle,
2291
2348
  bossGroupId: targetBoss.groupId
2292
2349
  }, {
2350
+ playerName: session.username,
2293
2351
  totalDamage: existingRecord.totalDamage + actualDamage,
2294
2352
  // 改为实际伤害
2295
2353
  attackCount: existingRecord.attackCount + 1,
@@ -2413,13 +2471,13 @@ ${achievementList.join("\n")}`;
2413
2471
  await ctx.database.remove("ggcevo_boss_damage", {
2414
2472
  bossGroupId: targetBoss.groupId
2415
2473
  });
2416
- ctx.broadcast(config2.groupId, [
2417
- `🎯 主宰 ${targetBoss.name} 已被击败!`,
2418
- `所有子代已消失,下一个主宰将在1小时后出现`,
2474
+ broadcastMessage = [
2475
+ `🎯 主宰 ${targetBoss.name} 已被 ${session.username} 击破!`,
2476
+ `所有子代已消失,下一个主宰将在1小时后重生`,
2419
2477
  "",
2420
- "🎁 奖励发放结果:",
2478
+ "🏆 伤害排行榜奖励:",
2421
2479
  ...rewardMessages
2422
- ].join("\n"));
2480
+ ];
2423
2481
  } else {
2424
2482
  await ctx.database.set(
2425
2483
  "ggcevo_boss",
@@ -2429,11 +2487,10 @@ ${achievementList.join("\n")}`;
2429
2487
  HP: 0
2430
2488
  }
2431
2489
  );
2432
- ctx.broadcast(
2433
- config2.groupId,
2434
- `🎯 子代 ${targetBoss.name} 已被击败!
2435
- 主宰仍然存在,但是将额外遭受20%的易伤,继续战斗!`
2436
- );
2490
+ broadcastMessage = [
2491
+ `⚡ ${session.username} 击破了子代 ${targetBoss.name}!`,
2492
+ `【连锁效果】主宰获得 20% 易伤状态!`
2493
+ ];
2437
2494
  }
2438
2495
  } else {
2439
2496
  await ctx.database.set(
@@ -2455,15 +2512,20 @@ ${achievementList.join("\n")}`;
2455
2512
  // 改为实际伤害
2456
2513
  });
2457
2514
  }
2458
- return [
2515
+ const resultMessage = [
2459
2516
  `🔥 ${session.username} 使用武器 ${weaponName} 对 ${targetBoss.name} 发起攻击!`,
2460
2517
  `造成伤害:${actualDamage}${hasCrit ? "(✨ 暴击!)" : ""}`,
2461
- // 改为实际伤害
2462
2518
  `获得金币:${actualDamage}`,
2463
- // 改为实际伤害
2464
2519
  `目标剩余HP:${isDefeated ? 0 : updatedHP}/${targetBoss.type === "主宰" ? bossGroup.main.maxHP : bossGroup.minions[0].maxHP}`,
2465
2520
  isDefeated ? `🎉 成功击败 ${targetBoss.name}!` : ""
2466
- ].filter((line) => line !== "").join("\n");
2521
+ ].filter((line) => line).join("\n");
2522
+ await session.send(resultMessage);
2523
+ if (broadcastMessage) {
2524
+ const finalBroadcast = Array.isArray(broadcastMessage) ? broadcastMessage.join("\n") : broadcastMessage;
2525
+ await new Promise((resolve) => setTimeout(resolve, 500));
2526
+ ctx.broadcast(config2.groupId, finalBroadcast);
2527
+ }
2528
+ return;
2467
2529
  });
2468
2530
  ctx.command("ggcevo/初始化主宰", "初始化或重置主宰系统", { authority: 3 }).action(async () => {
2469
2531
  try {
@@ -2509,19 +2571,15 @@ ${achievementList.join("\n")}`;
2509
2571
  pageNum < totalPages ? `输入 伤害榜 ${pageNum + 1} 查看下一页` : "已是最后一页"
2510
2572
  ].join("\n");
2511
2573
  });
2512
- ctx.command("ggcevo/主宰状态", "查看当前主宰信息").alias("zz状态").action(async () => {
2574
+ ctx.command("ggcevo/主宰信息", "查看当前主宰信息").alias("zz信息").action(async () => {
2513
2575
  const activeBosses = await ctx.database.get("ggcevo_boss", { isActive: true });
2514
- if (!activeBosses.length) return "当前没有激活的BOSS";
2576
+ if (!activeBosses.length) return "当前没有存活的主宰。";
2515
2577
  const mainBoss = activeBosses.find((b) => b.type === "主宰");
2516
2578
  const minions = activeBosses.filter((b) => b.type === "子代");
2517
2579
  if (!mainBoss) return "当前BOSS数据异常,请联系管理员";
2518
2580
  const bossGroup = bossPool.find((group) => group.main.name === mainBoss.name);
2519
2581
  if (!bossGroup) return "BOSS配置数据异常,请联系管理员";
2520
2582
  const mainBossHpBar = createHpBar(mainBoss.HP, bossGroup.main.maxHP);
2521
- const formatEffect = /* @__PURE__ */ __name((value) => {
2522
- const percentage = Math.abs(value * 100);
2523
- return value > 0 ? `受到的伤害+${percentage}%` : `受到的伤害-${percentage}%`;
2524
- }, "formatEffect");
2525
2583
  let passiveDisplay = [];
2526
2584
  if (bossGroup.main.passive) {
2527
2585
  const activeMinions = await ctx.database.get("ggcevo_boss", {
@@ -2533,8 +2591,7 @@ ${achievementList.join("\n")}`;
2533
2591
  if (p === "孤立无援") return activeMinions.length === 0;
2534
2592
  return true;
2535
2593
  }).map((p) => {
2536
- const effect = passiveConfig[p].effect;
2537
- return `${p}:${formatEffect(effect)}`;
2594
+ return `${p}:${passiveConfig[p].description}`;
2538
2595
  });
2539
2596
  }
2540
2597
  const result = [
@@ -2544,12 +2601,12 @@ ${achievementList.join("\n")}`;
2544
2601
  `被动:${passiveDisplay.join(",") || "无"}`
2545
2602
  ];
2546
2603
  if (minions.length > 0) {
2547
- result.push("", "🟠 子代信息:");
2604
+ result.push("", "🟠 子代:");
2548
2605
  minions.forEach((minion) => {
2549
2606
  const minionConfig = bossGroup.minions.find((m) => m.name === minion.name);
2550
2607
  if (minionConfig) {
2551
2608
  const minionHpBar = createHpBar(minion.HP, minionConfig.maxHP);
2552
- const minionPassives = (minionConfig.passive || []).map((p) => `${p}:${formatEffect(passiveConfig[p].effect)}`).join(",");
2609
+ const minionPassives = (minionConfig.passive || []).map((p) => `${p}:${passiveConfig[p].description}`).join(",");
2553
2610
  result.push(
2554
2611
  `${minion.name}`,
2555
2612
  `${minionHpBar} (${minion.HP}/${minionConfig.maxHP})`,
@@ -2618,6 +2675,17 @@ function convertUTCtoChinaTime(input) {
2618
2675
  return new Date(chinaTimestamp);
2619
2676
  }
2620
2677
  __name(convertUTCtoChinaTime, "convertUTCtoChinaTime");
2678
+ function formatDate(d) {
2679
+ return d.toLocaleString("zh-CN", {
2680
+ timeZone: "Asia/Shanghai",
2681
+ year: "numeric",
2682
+ month: "2-digit",
2683
+ day: "2-digit",
2684
+ hour: "2-digit",
2685
+ minute: "2-digit"
2686
+ });
2687
+ }
2688
+ __name(formatDate, "formatDate");
2621
2689
  // Annotate the CommonJS export names for ESM import in node:
2622
2690
  0 && (module.exports = {
2623
2691
  Config,