koishi-plugin-ggcevo-game 1.2.13 → 1.2.15

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,112 @@ ${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 ? [
1096
+ ...activities.map((a) => [
1097
+ `活动名称:${a.name}`,
1098
+ `活动时间:${formatDate(a.startTime)} - ${formatDate(a.endTime)}`,
1099
+ `活动描述:${a.description}`,
1100
+ `活动奖励:${a.quantity} × ${itemMap.get(a.itemId) || "未知物品"}`,
1101
+ "━".repeat(20)
1102
+ ].join("\n")),
1103
+ "请输入「领取 活动名称」领取奖励"
1104
+ ].join("\n") : "当前没有进行中的活动。";
998
1105
  });
999
1106
  ctx.setInterval(async () => {
1000
1107
  const now = /* @__PURE__ */ new Date();
@@ -1077,7 +1184,7 @@ ID:${activity.id}
1077
1184
  }
1078
1185
  }
1079
1186
  }, 60 * 60 * 1e3);
1080
- ctx.command("ggcevo/胜点榜数据同步", { authority: 3 }).action(async () => {
1187
+ ctx.command("ggcevo/数据同步", { authority: 3 }).action(async () => {
1081
1188
  try {
1082
1189
  const ggcmap = await ctx.database.get("sc2arcade_map", { guildId: config.ggcqun });
1083
1190
  const lastdate = ggcmap[0].lastdate;
@@ -1132,13 +1239,13 @@ ID:${activity.id}
1132
1239
  lastdate: new Date(currentMaxDate.toISOString())
1133
1240
  });
1134
1241
  }
1135
- return "数据同步成功";
1242
+ return "✅ 胜点榜数据同步成功!";
1136
1243
  } catch (err) {
1137
1244
  console.error("错误:", err);
1138
1245
  return "服务器繁忙,请稍后尝试。";
1139
1246
  }
1140
1247
  });
1141
- ctx.command("ggcevo/胜点榜 [page]").alias("排行榜").usage("输入 rank [页码] 查看对应页的排行榜,每页10条").action(async (_, page) => {
1248
+ ctx.command("ggcevo/胜点榜 [page]").alias("排行榜").usage("输入 胜点榜 [页码] 查看对应页的排行榜,每页10条").action(async (_, page) => {
1142
1249
  const pageNum = parseInt(page) || 1;
1143
1250
  if (pageNum < 1) return "请输入有效的页码。";
1144
1251
  const offset = (pageNum - 1) * 10;
@@ -1160,9 +1267,8 @@ ID:${activity.id}
1160
1267
  (item, index) => `${offset + index + 1}. ${item.displayName} | 积分: ${item.rank} | 胜率: ${item.matches === 0 ? "0.00%" : (item.wins / item.matches * 100).toFixed(2) + "%"}`
1161
1268
  ).join("\n");
1162
1269
  return [
1163
- `🏆 GGCEvo S1赛季胜点榜 🏆`,
1164
- `本赛季从4月1日至5月15日23点`,
1165
- `数据同步时间: ${lastdate.toLocaleString("zh-CN", {
1270
+ `🏆 咕咕胜点榜 ${config.rankseason}赛季 🏆`,
1271
+ `数据最新同步时间: ${lastdate.toLocaleString("zh-CN", {
1166
1272
  timeZone: "Asia/Shanghai",
1167
1273
  year: "numeric",
1168
1274
  month: "2-digit",
@@ -1175,7 +1281,7 @@ ID:${activity.id}
1175
1281
  rankingText,
1176
1282
  "------------------------------",
1177
1283
  `第 ${pageNum} 页 / 共 ${totalPages} 页`,
1178
- pageNum < totalPages ? `输入 胜点榜 ${pageNum + 1} 查看下一页` : "已是最后一页"
1284
+ pageNum < totalPages ? `输入“胜点榜 ${pageNum + 1}”查看下一页` : "已是最后一页"
1179
1285
  ].join("\n");
1180
1286
  });
1181
1287
  ctx.command("ggcevo/排名 [player]", "查询个人排名").alias("rank").usage("输入“排名”查看自己的排名信息").action(async (argv, player) => {
@@ -1183,29 +1289,29 @@ ID:${activity.id}
1183
1289
  if (!player) {
1184
1290
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1185
1291
  if (!profile) {
1186
- return "您的 QQ 未绑定句柄。";
1292
+ return "您暂未绑定句柄。";
1187
1293
  }
1188
1294
  const { regionId, realmId, profileId } = profile;
1189
1295
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
1190
1296
  const [user] = await ctx.database.get("ggcevo_rank", {
1191
1297
  handle
1192
1298
  });
1193
- if (!user) return "未找到您的排名信息。";
1194
- if (user.Blacklist) return "❌您已经被禁止参加本赛季胜点榜。";
1299
+ if (!user) return "暂未找到您的排名信息。";
1300
+ if (user.Blacklist) return "❌ 您已经被禁止参加本赛季胜点榜。";
1195
1301
  const allRanks = await ctx.database.select("ggcevo_rank").where({ Blacklist: false }).orderBy("rank", "desc").execute();
1196
1302
  const userRank = allRanks.findIndex(
1197
1303
  (u) => u.handle === handle
1198
1304
  ) + 1;
1199
1305
  const isSafe = await checkSensitiveWord(user.name);
1200
1306
  const displayName = isSafe ? user.name : (user.name[0] || "") + "***";
1201
- return `🎮 您的 GGCEvo 排名信息 🎮
1307
+ return `🎮 您的咕咕胜点榜排名信息 🎮
1202
1308
  ------------------------------
1203
1309
  昵称:${displayName}
1204
1310
  句柄:${user.handle}
1205
1311
  当前积分:${user.rank}
1206
1312
  参赛次数:${user.matches} 次
1207
1313
  胜率: ${user.matches === 0 ? "0.00%" : (user.wins / user.matches * 100).toFixed(2) + "%"}
1208
- 全服排名:第 ${userRank}
1314
+ 全服排名:第 ${userRank}
1209
1315
  ------------------------------`;
1210
1316
  } else {
1211
1317
  const parsedUser = import_koishi.h.parse(player)[0];
@@ -1216,51 +1322,67 @@ ID:${activity.id}
1216
1322
  let targetUsername = parsedUser.attrs.name || targetUserId;
1217
1323
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: targetUsername });
1218
1324
  if (!profile) {
1219
- return "对方的 QQ 未绑定句柄。";
1325
+ return "对方暂未绑定句柄。";
1220
1326
  }
1221
1327
  const { regionId, realmId, profileId } = profile;
1222
1328
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
1223
1329
  const [user] = await ctx.database.get("ggcevo_rank", {
1224
1330
  handle
1225
1331
  });
1226
- if (!user) return "未找到对方的排名信息。";
1227
- if (user.Blacklist) return "❌对方已经被禁止参加本赛季胜点榜。";
1332
+ if (!user) return "暂未找到对方的排名信息。";
1333
+ if (user.Blacklist) return "❌ 对方已经被禁止参加本赛季胜点榜。";
1228
1334
  const allRanks = await ctx.database.select("ggcevo_rank").where({ Blacklist: false }).orderBy("rank", "desc").execute();
1229
1335
  const userRank = allRanks.findIndex(
1230
1336
  (u) => u.handle === handle
1231
1337
  ) + 1;
1232
1338
  const isSafe = await checkSensitiveWord(user.name);
1233
1339
  const displayName = isSafe ? user.name : (user.name[0] || "") + "***";
1234
- return `🎮 对方的 GGCEvo 排名信息 🎮
1340
+ return `🎮 对方的咕咕胜点榜排名信息 🎮
1235
1341
  ------------------------------
1236
1342
  昵称:${displayName}
1237
1343
  句柄:${user.handle}
1238
1344
  当前积分:${user.rank}
1239
1345
  参赛次数:${user.matches} 次
1240
1346
  胜率: ${user.matches === 0 ? "0.00%" : (user.wins / user.matches * 100).toFixed(2) + "%"}
1241
- 全服排名:第 ${userRank}
1347
+ 全服排名:第 ${userRank}
1242
1348
  ------------------------------`;
1243
1349
  }
1244
1350
  });
1245
- ctx.command("ggcevo/给予 <handle> <itemId:number> <amount:number>", "增加指定用户的物品", { authority: 3 }).action(async (_, handle, itemId, amount) => {
1351
+ ctx.command("ggcevo/给予 <handle> <itemName:string> <amount:number>", "增加用户物品/金币", { authority: 3 }).action(async (_, handle, itemName, amount) => {
1246
1352
  try {
1247
- if (!handle || !itemId || !amount) {
1248
- return `请输入正确的指令格式`;
1353
+ if (!handle || !itemName || amount <= 0) {
1354
+ return "参数格式错误,正确格式:给予 用户句柄 物品名称 数量";
1249
1355
  }
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 });
1356
+ if (itemName === "金币") {
1357
+ const [signData] = await ctx.database.get("ggcevo_sign", { handle });
1358
+ await ctx.database.upsert("ggcevo_sign", [{
1359
+ handle,
1360
+ totalRewards: (signData?.totalRewards || 0) + Math.floor(amount),
1361
+ lastSign: signData?.lastSign || /* @__PURE__ */ new Date(0),
1362
+ // 保持原有最后签到时间
1363
+ monthlyDays: signData?.monthlyDays || 0
1364
+ // 保持月签到天数
1365
+ }]);
1366
+ return `成功为 ${handle} 添加 ${amount} 金币!当前金币总数:${(signData?.totalRewards || 0) + amount}`;
1367
+ }
1368
+ const validItems = Object.keys(initDefaultItems);
1369
+ if (!validItems.includes(itemName)) {
1370
+ return `无效物品名称,可用物品:${validItems.join("、")}`;
1371
+ }
1372
+ const itemId = initDefaultItems[itemName].id;
1373
+ const [backpack] = await ctx.database.get("ggcevo_backpack", {
1374
+ handle,
1375
+ itemId
1376
+ });
1255
1377
  await ctx.database.upsert("ggcevo_backpack", [{
1256
1378
  handle,
1257
1379
  itemId,
1258
- quantity: (backpack?.quantity || 0) + amount
1380
+ quantity: (backpack?.quantity || 0) + Math.floor(amount)
1259
1381
  }], ["handle", "itemId"]);
1260
- return `成功为 ${handle} 增加 ${amount} 个${itemName}!`;
1382
+ return `成功为 ${handle} 添加 ${amount} 个${itemName}!当前总数:${(backpack?.quantity || 0) + amount}`;
1261
1383
  } catch (err) {
1262
- console.error("数据库操作失败:", err);
1263
- return "操作失败,请稍后再试";
1384
+ console.error("[给予命令错误]", err);
1385
+ return "操作失败:" + (err instanceof Error ? err.message : "数据库异常");
1264
1386
  }
1265
1387
  });
1266
1388
  ctx.command("ggcevo/违规记录 [user]", "违规记录查询").usage("输入 违规记录 [@用户] -p 页码 查看处罚记录,每页1条").option("p", "-p <page:number> 指定页码").action(async (argv) => {
@@ -1270,7 +1392,7 @@ ID:${activity.id}
1270
1392
  let handle;
1271
1393
  if (!user) {
1272
1394
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1273
- if (!profile) return "您的 QQ 未绑定句柄。";
1395
+ if (!profile) return "您暂未绑定句柄。";
1274
1396
  handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1275
1397
  } else {
1276
1398
  const parsedUser = import_koishi.h.parse(user)[0];
@@ -1281,7 +1403,7 @@ ID:${activity.id}
1281
1403
  let targetUsername = parsedUser.attrs.name || targetUserId;
1282
1404
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: targetUsername });
1283
1405
  if (!profile) {
1284
- return "对方的 QQ 未绑定句柄。";
1406
+ return "对方暂未绑定句柄。";
1285
1407
  }
1286
1408
  const { regionId, realmId, profileId } = profile;
1287
1409
  handle = `${regionId}-S2-${realmId}-${profileId}`;
@@ -1313,17 +1435,17 @@ ID:${activity.id}
1313
1435
  "------------------------------",
1314
1436
  recordText,
1315
1437
  "------------------------------",
1316
- pageNum < totalPages ? `输入 违规记录 -p ${pageNum + 1} 查看下一条` : "已是最后一页"
1438
+ pageNum < totalPages ? `输入 违规记录 (@用户) -p ${pageNum + 1} 查看下一条` : "已是最后一页"
1317
1439
  ].join("\n");
1318
1440
  });
1319
1441
  ctx.command("ggcevo/兑换", "兑换物品").action(async ({ session }) => {
1320
1442
  try {
1321
1443
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1322
- if (!profile) return "您的 QQ 未绑定句柄";
1444
+ if (!profile) return "您暂未绑定句柄";
1323
1445
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1324
1446
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
1325
1447
  if (existingEntries.length > 0) {
1326
- return `❌拒绝访问,您已被列入活动黑名单。`;
1448
+ return `❌ 拒绝访问,您已被列入黑名单。`;
1327
1449
  }
1328
1450
  const currentSeason = config.rankseason;
1329
1451
  const qualityGroups = {};
@@ -1349,7 +1471,7 @@ ID:${activity.id}
1349
1471
  qualityGroups[quality].push(`${itemName}${quantityText}`);
1350
1472
  }
1351
1473
  const order = ["t0", "t1", "t2", "t3"];
1352
- let message = "请在30秒内输入可兑换物品(显示格式:物品名 [剩余/总量]):\n";
1474
+ let message = "请在30秒内输入可兑换物品(显示格式:物品名 [剩余/总量]):\n";
1353
1475
  for (const quality of order) {
1354
1476
  const items = qualityGroups[quality] || [];
1355
1477
  if (!items.length) continue;
@@ -1360,11 +1482,11 @@ ${items.join("、")}
1360
1482
  }
1361
1483
  await session.send(message);
1362
1484
  const name2 = await session.prompt(3e4);
1363
- if (!name2) return "输入超时,请重新输入指令。";
1485
+ if (!name2) return "输入超时,请重新输入。";
1364
1486
  const configname = itemConfig[name2];
1365
- if (!configname) return "无效的物品名称,请重新输入";
1487
+ if (!configname) return "无效的物品名称,请重新输入。";
1366
1488
  const userRecords = await ctx.database.get("ggcevo_exchange", { handle, item: name2 });
1367
- if (userRecords.length > 0) return "您已经兑换过该物品";
1489
+ if (userRecords.length > 0) return "您已经兑换过该物品。";
1368
1490
  if (configname.quantity !== void 0 && (configname.isLimited || config.ignoreGlobalLimit === false)) {
1369
1491
  const queryConditions = {
1370
1492
  item: name2,
@@ -1374,7 +1496,7 @@ ${items.join("、")}
1374
1496
  queryConditions.season = currentSeason;
1375
1497
  }
1376
1498
  const globalRecords = await ctx.database.get("ggcevo_exchange", queryConditions);
1377
- if (globalRecords.length >= configname.quantity) return "该物品已被兑换尽";
1499
+ if (globalRecords.length >= configname.quantity) return "该物品已被兑换完了。";
1378
1500
  }
1379
1501
  const qualityMap = { "t3": 4, "t2": 5, "t1": 6, "t0": 7 };
1380
1502
  const petItems = new Set(
@@ -1397,7 +1519,7 @@ ${items.join("、")}
1397
1519
  }
1398
1520
  const [coupon] = await ctx.database.get("ggcevo_backpack", { handle, itemId });
1399
1521
  if (!coupon || coupon.quantity < cost) {
1400
- const requireMsg = petItems.has(name2) ? `需要 1 个${configname.quality}级宠物扭蛋 或 ${configname.cost}个兑奖券` : `需要 ${configname.cost}个兑奖券`;
1522
+ const requireMsg = petItems.has(name2) ? `需要1个${configname.quality}级宠物扭蛋 或${configname.cost}张兑奖券` : `需要${configname.cost}张兑奖券`;
1401
1523
  return `${requireMsg}
1402
1524
  当前持有:${coupon?.quantity || 0}个${couponName}`;
1403
1525
  }
@@ -1420,7 +1542,7 @@ ${items.join("、")}
1420
1542
  season: currentSeason
1421
1543
  });
1422
1544
  });
1423
- return `兑换成功!消耗 ${cost} 个${couponName}获得【${name2}】`;
1545
+ return `兑换成功!消耗${cost}个${couponName}获得【${name2}】`;
1424
1546
  } catch (error) {
1425
1547
  console.error("兑换失败:", error);
1426
1548
  return "兑换失败";
@@ -1428,7 +1550,7 @@ ${items.join("、")}
1428
1550
  });
1429
1551
  ctx.command("ggcevo/兑换记录").action(async ({ session }) => {
1430
1552
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1431
- if (!profile) return "您的 QQ 未绑定句柄";
1553
+ if (!profile) return "您暂未绑定句柄";
1432
1554
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1433
1555
  const exchanges = await ctx.database.get("ggcevo_exchange", { handle });
1434
1556
  if (!exchanges.length) return "您暂无兑换记录";
@@ -1447,16 +1569,16 @@ ${output}`;
1447
1569
  });
1448
1570
  ctx.command("ggcevo/兑换扭蛋币").action(async ({ session }) => {
1449
1571
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1450
- if (!profile) return "您的 QQ 未绑定句柄";
1572
+ if (!profile) return "您暂未绑定句柄。";
1451
1573
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1452
1574
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
1453
1575
  if (existingEntries.length > 0) {
1454
- return `❌拒绝访问,您已被列入活动黑名单。`;
1576
+ return `❌ 拒绝访问,您已被列入黑名单。`;
1455
1577
  }
1456
1578
  const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 3 });
1457
1579
  const [coupon] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 2 });
1458
1580
  if (!coupon || coupon.quantity < 3) {
1459
- return `兑换扭蛋币需要 3 张兑奖券,当前持有:${coupon?.quantity || 0}`;
1581
+ return `兑换扭蛋币需要3张兑奖券,当前持有:${coupon?.quantity || 0}`;
1460
1582
  }
1461
1583
  await ctx.database.set(
1462
1584
  "ggcevo_backpack",
@@ -1468,19 +1590,19 @@ ${output}`;
1468
1590
  itemId: 3,
1469
1591
  quantity: (backpack?.quantity || 0) + 1
1470
1592
  }]);
1471
- return `兑换成功!消耗 3 张兑奖券获得 1 个扭蛋币`;
1593
+ return `兑换成功!消耗3张兑奖券获得1枚扭蛋币`;
1472
1594
  });
1473
1595
  ctx.command("ggcevo/扭蛋").action(async (argv) => {
1474
1596
  const session = argv.session;
1475
1597
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1476
1598
  if (!profile) {
1477
- return "您的 QQ 未绑定句柄。";
1599
+ return "您暂未绑定句柄。";
1478
1600
  }
1479
1601
  const { regionId, realmId, profileId } = profile;
1480
1602
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
1481
1603
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
1482
1604
  if (existingEntries.length > 0) {
1483
- return `❌拒绝访问,您已被列入活动黑名单。`;
1605
+ return `❌ 拒绝访问,您已被列入黑名单。`;
1484
1606
  }
1485
1607
  const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 3 });
1486
1608
  if (!backpack || backpack.quantity < 1) {
@@ -1506,16 +1628,16 @@ ${output}`;
1506
1628
  itemId: itemData.id,
1507
1629
  quantity: currentQuantity + 1
1508
1630
  }]);
1509
- return `🎉 恭喜获得:${itemName}`;
1631
+ return `🎉 恭喜您获得:${itemName}`;
1510
1632
  });
1511
- ctx.command("ggcevo/活动拉黑", "添加用户到活动黑名单").action(async (argv) => {
1633
+ ctx.command("ggcevo/拉黑", "添加用户到黑名单").action(async (argv) => {
1512
1634
  const session = argv.session;
1513
1635
  if (!ctx.config.admins.includes(session.userId)) {
1514
- return "⚠️ 没有操作权限,请联系机器人管理员";
1636
+ return "⚠️ 没有操作权限。";
1515
1637
  }
1516
1638
  await session.send("请在30秒内输入需要拉黑的句柄:\n(句柄格式为: [区域ID]-S2-[服务器ID]-[档案ID])");
1517
1639
  const handle = await session.prompt(3e4);
1518
- if (!handle) return "输入超时,请重新输入指令。";
1640
+ if (!handle) return "输入超时,请重新输入。";
1519
1641
  try {
1520
1642
  const handleRegex = /^([1235])-S2-([12])-(\d+)$/;
1521
1643
  if (!handleRegex.test(handle)) {
@@ -1523,40 +1645,40 @@ ${output}`;
1523
1645
  }
1524
1646
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
1525
1647
  if (existingEntries.length > 0) {
1526
- return `${handle} 已在活动黑名单中`;
1648
+ return `${handle}已在黑名单中。`;
1527
1649
  }
1528
1650
  await ctx.database.create("ggcevo_blacklist", {
1529
1651
  handle,
1530
1652
  createdAt: /* @__PURE__ */ new Date()
1531
1653
  });
1532
- return `✅ 用户 ${handle} 已被列入活动黑名单(永久)`;
1654
+ return `✅ 用户${handle}已被列入黑名单。`;
1533
1655
  } catch (error) {
1534
1656
  console.error("黑名单操作失败:", error);
1535
1657
  return "操作失败,请稍后重试。错误详情已记录";
1536
1658
  }
1537
1659
  });
1538
- ctx.command("ggcevo/胜点榜拉黑", "添加用户到胜点榜黑名单").action(async (argv) => {
1660
+ ctx.command("ggcevo/标记", "标记用户到胜点榜黑名单").action(async (argv) => {
1539
1661
  const session = argv.session;
1540
1662
  if (!ctx.config.admins.includes(session.userId)) {
1541
- return "⚠️ 没有操作权限,请联系机器人管理员";
1663
+ return "⚠️ 没有操作权限。";
1542
1664
  }
1543
- await session.send("请在30秒内输入需要拉黑的句柄:\n(句柄格式为: [区域ID]-S2-[服务器ID]-[档案ID])");
1665
+ await session.send("请在30秒内输入需要标记的句柄:\n(句柄格式为: [区域ID]-S2-[服务器ID]-[档案ID])");
1544
1666
  const handle = await session.prompt(3e4);
1545
- if (!handle) return "输入超时,请重新输入指令。";
1667
+ if (!handle) return "输入超时,请重新输入。";
1546
1668
  try {
1547
1669
  const handleRegex = /^([1235])-S2-([12])-(\d+)$/;
1548
1670
  if (!handleRegex.test(handle)) {
1549
- return "句柄格式错误,请重新输入";
1671
+ return "句柄格式错误,请重新输入。";
1550
1672
  }
1551
1673
  const existingEntries = await ctx.database.get("ggcevo_rank", { handle, Blacklist: true });
1552
1674
  if (existingEntries.length > 0) {
1553
- return `${handle} 已在胜点榜黑名单中`;
1675
+ return `${handle}已被标记在咕咕胜点榜黑名单中。`;
1554
1676
  }
1555
1677
  await ctx.database.upsert("ggcevo_rank", [{
1556
1678
  handle,
1557
1679
  Blacklist: true
1558
1680
  }]);
1559
- return `✅ 用户 ${handle} 已被列入胜点榜黑名单(仅限当前赛季)`;
1681
+ return `✅ 用户${handle}已被标记在咕咕胜点榜黑名单。`;
1560
1682
  } catch (error) {
1561
1683
  console.error("黑名单操作失败:", error);
1562
1684
  return "操作失败,请稍后重试。错误详情已记录";
@@ -1565,14 +1687,14 @@ ${output}`;
1565
1687
  ctx.command("ggcevo/成就").action(async ({ session }) => {
1566
1688
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1567
1689
  if (!profile) {
1568
- return "您的 QQ 未绑定句柄。";
1690
+ return "您暂未绑定句柄。";
1569
1691
  }
1570
1692
  const { regionId, realmId, profileId } = profile;
1571
1693
  const achievements = await ctx.database.get("ggcevo_achievements", {
1572
1694
  handle: `${regionId}-S2-${realmId}-${profileId}`
1573
1695
  });
1574
1696
  if (!achievements.length) {
1575
- return "你还没有获得任何成就哦~";
1697
+ return "你还没有获得任何成就。";
1576
1698
  }
1577
1699
  const achievementList = achievements.map((achievement) => {
1578
1700
  const date = new Date(achievement.gaintime);
@@ -1590,7 +1712,7 @@ ${achievementList.join("\n")}`;
1590
1712
  const session = argv.session;
1591
1713
  const output = [];
1592
1714
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1593
- if (!profile) return "您的 QQ 未绑定游戏句柄。";
1715
+ if (!profile) return "您暂未绑定句柄。";
1594
1716
  const { regionId, realmId, profileId } = profile;
1595
1717
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
1596
1718
  output.push(`🎮 游戏句柄:${handle}
@@ -1721,22 +1843,22 @@ ${achievementList.join("\n")}`;
1721
1843
  ctx.command("ggcevo/pk [user]", "发起玩家对战").alias("挑战").action(async (argv, user) => {
1722
1844
  try {
1723
1845
  const session = argv.session;
1724
- if (!user) return '缺少参数,请输入"pk @指定对战玩家"';
1846
+ if (!user) return "缺少参数,请输入“pk @指定pk玩家”。";
1725
1847
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1726
- if (!profile) return "您的 QQ 未绑定句柄。";
1848
+ if (!profile) return "您暂未绑定句柄。";
1727
1849
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1728
1850
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
1729
1851
  if (existingEntries.length > 0) {
1730
- return `❌拒绝访问,您已被列入活动黑名单。`;
1852
+ return `❌ 拒绝访问,您已被列入黑名单。`;
1731
1853
  }
1732
1854
  const parsedUser = import_koishi.h.parse(user)[0];
1733
- if (!parsedUser || parsedUser.type !== "at" || !parsedUser.attrs.id) return '参数格式错误,请输入"pk @指定对战玩家"';
1855
+ if (!parsedUser || parsedUser.type !== "at" || !parsedUser.attrs.id) return "参数格式错误,请输入“pk @指定pk玩家”。";
1734
1856
  const targetUserId = parsedUser.attrs.id;
1735
1857
  const [targetprofile] = await ctx.database.get("sc2arcade_player", { userId: targetUserId });
1736
- if (!targetprofile) return "对方尚未绑定句柄";
1858
+ if (!targetprofile) return "对方尚未绑定句柄。";
1737
1859
  const initiatorHandle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
1738
1860
  const targetHandle = `${targetprofile.regionId}-S2-${targetprofile.realmId}-${targetprofile.profileId}`;
1739
- if (initiatorHandle === targetHandle) return "不能挑战自己哦~";
1861
+ if (initiatorHandle === targetHandle) return "不能挑战自己。";
1740
1862
  let initiatorPK = {
1741
1863
  handle: initiatorHandle,
1742
1864
  total: 0,
@@ -1767,17 +1889,17 @@ ${achievementList.join("\n")}`;
1767
1889
  if (dbTarget) Object.assign(targetPK, dbTarget);
1768
1890
  });
1769
1891
  if (!initiatorPK.enable) {
1770
- return "您已关闭PK功能,无法发起挑战";
1892
+ return "您已关闭PK功能,无法发起挑战。";
1771
1893
  }
1772
1894
  if (!targetPK.enable) {
1773
- return "对方已关闭PK功能,无法接受挑战";
1895
+ return "对方已关闭PK功能,无法接受挑战。";
1774
1896
  }
1775
1897
  const now = convertUTCtoChinaTime(/* @__PURE__ */ new Date());
1776
1898
  if (!isSameDate(convertUTCtoChinaTime(initiatorPK.lastPK), now)) {
1777
1899
  initiatorPK.todayCount = 0;
1778
1900
  }
1779
1901
  if (initiatorPK.todayCount >= config.dailyPKLimit) {
1780
- return `今日挑战次数已用尽(${config.dailyPKLimit}次/日)`;
1902
+ return `今日挑战次数已用尽(${config.dailyPKLimit}次/日)。`;
1781
1903
  }
1782
1904
  const nowChina = convertUTCtoChinaTime(/* @__PURE__ */ new Date());
1783
1905
  const todayStart = new Date(nowChina);
@@ -1790,7 +1912,7 @@ ${achievementList.join("\n")}`;
1790
1912
  date: { $gte: adjustedTime }
1791
1913
  }).execute((row) => import_koishi.$.count(row.id));
1792
1914
  if (sameOpponentCount > 0) {
1793
- return "您今天已经挑战过该玩家,请明天再试";
1915
+ return "您今天已经挑战过该玩家,请明天再试。";
1794
1916
  }
1795
1917
  }
1796
1918
  if (config.maxDailyBeChallenged > 0) {
@@ -1799,7 +1921,7 @@ ${achievementList.join("\n")}`;
1799
1921
  date: { $gte: adjustedTime }
1800
1922
  }).execute((row) => import_koishi.$.count(row.id));
1801
1923
  if (beChallengedCount >= config.maxDailyBeChallenged) {
1802
- return `该玩家今日已被挑战太多次(最多${config.maxDailyBeChallenged}次)`;
1924
+ return `该玩家今日已被挑战太多次(最多${config.maxDailyBeChallenged}次)。`;
1803
1925
  }
1804
1926
  }
1805
1927
  const [initiatorData, targetData] = await Promise.all([
@@ -1816,8 +1938,8 @@ ${achievementList.join("\n")}`;
1816
1938
  ]);
1817
1939
  const initiatorGold = initiatorSign[0]?.totalRewards || 0;
1818
1940
  const targetGold = targetSign[0]?.totalRewards || 0;
1819
- if (initiatorGold < 100) return "发起者需要至少100金币才能挑战!";
1820
- if (targetGold < 100) return "对方金币不足100,无法应战";
1941
+ if (initiatorGold < 100) return "发起者需要至少100金币才能发起挑战。";
1942
+ if (targetGold < 100) return "对方金币不足100,无法应战。";
1821
1943
  const rankDiff = initiatorRank - targetRank;
1822
1944
  const clampedDiff = Math.min(Math.max(rankDiff, -1e4), 1e4);
1823
1945
  const winRate = Math.min(Math.max(50 + clampedDiff * 5e-3, 5), 95);
@@ -1874,8 +1996,8 @@ ${achievementList.join("\n")}`;
1874
1996
  });
1875
1997
  const result = [
1876
1998
  `⚔️【对战结果】${isWin ? "胜利" : "失败"}`,
1877
- `🏅 挑战者:${initiatorRankname}(积分 ${initiatorRank})`,
1878
- `🛡️ 应战者:${targetRankname}(积分 ${targetRank})`,
1999
+ `🏅 挑战者:${initiatorRankname}(积分 ${initiatorRank})`,
2000
+ `🛡️ 应战者:${targetRankname}(积分 ${targetRank})`,
1879
2001
  `📊 胜率预测:${winRate.toFixed(1)}%`,
1880
2002
  `🎰 金币变动:${stealPercentage}%`
1881
2003
  ];
@@ -1889,12 +2011,8 @@ ${achievementList.join("\n")}`;
1889
2011
  });
1890
2012
  ctx.command("ggcevo/切换pk状态", "切换玩家对战状态").action(async ({ session }) => {
1891
2013
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
1892
- if (!profile) return "您的 QQ 未绑定句柄";
2014
+ if (!profile) return "您暂未绑定句柄。";
1893
2015
  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
2016
  const [pkRecord] = await ctx.database.get("ggcevo_pk", { handle }) || [null];
1899
2017
  const currentState = pkRecord?.enable ?? true;
1900
2018
  const lastToggle = pkRecord?.lastToggle ?? /* @__PURE__ */ new Date(0);
@@ -1915,10 +2033,10 @@ ${achievementList.join("\n")}`;
1915
2033
  const diffDays = Math.floor((now.getTime() - lastToggleTime.getTime()) / (1e3 * 3600 * 24));
1916
2034
  if (diffDays < 3 && lastToggleTime.getTime() !== 0) {
1917
2035
  const remaining = 3 - diffDays;
1918
- return `状态切换冷却中,${remaining}天后再试(下次可切换时间:${new Date(lastToggle.getTime() + 3 * 864e5).toLocaleDateString("zh-CN")})`;
2036
+ return `状态切换冷却中,${remaining}天后再试(下次可切换时间:${new Date(lastToggle.getTime() + 3 * 864e5).toLocaleDateString("zh-CN")})。`;
1919
2037
  }
1920
2038
  const action = currentState ? "关闭" : "开启";
1921
- await session.send(`您当前的PK状态为【${currentState ? "开启" : "关闭"}】,确认要${action}吗?(30秒内回复“是”确认)`);
2039
+ await session.send(`您当前的PK状态为【${currentState ? "开启" : "关闭"}】,确认要${action}吗?(s30秒内回复“是”确认)`);
1922
2040
  const confirm = await session.prompt(3e4);
1923
2041
  if (confirm !== "是") return "已取消操作";
1924
2042
  await ctx.database.upsert("ggcevo_pk", [{
@@ -1937,8 +2055,26 @@ ${achievementList.join("\n")}`;
1937
2055
  day: "2-digit"
1938
2056
  })}`;
1939
2057
  });
1940
- ctx.command("ggcevo/武器库").action(async ({ session }) => {
1941
- const items = Object.entries(weaponConfig).map(([name2, config2]) => {
2058
+ ctx.command("ggcevo/武器库 [type]").usage("输入“武器库”查看类型,或“武器库 类型”查看详细武器信息").action(async ({ session }, type) => {
2059
+ const typeStats = Object.values(weaponConfig).reduce((stats, weapon) => {
2060
+ stats[weapon.type] = (stats[weapon.type] || 0) + 1;
2061
+ return stats;
2062
+ }, {});
2063
+ if (!type) {
2064
+ return [
2065
+ "🏪 咕咕军火武器库分类 🏪",
2066
+ '使用 "武器库 类型名称" 查看详细列表',
2067
+ "====================",
2068
+ ...Object.entries(typeStats).map(([typeName, count]) => `▸ ${typeName} (${count}种)`)
2069
+ ].join("\n");
2070
+ }
2071
+ const validTypes = Object.keys(typeStats);
2072
+ const normalizedType = validTypes.find((t) => t === type);
2073
+ if (!normalizedType) {
2074
+ return `无效武器类型,可用类型:
2075
+ ${validTypes.join("、")}`;
2076
+ }
2077
+ const items = Object.entries(weaponConfig).filter(([_, config2]) => config2.type === normalizedType).map(([name2, config2]) => {
1942
2078
  const tagEffectsDesc = config2.tagEffects ? Object.entries(config2.tagEffects).map(([tag, multiplier]) => `▸ 对${tag}目标造成${(multiplier * 100).toFixed(0)}%伤害`).join("\n") : "▸ 无特殊加成效果";
1943
2079
  return [
1944
2080
  `【${name2}】`,
@@ -1951,7 +2087,7 @@ ${achievementList.join("\n")}`;
1951
2087
  ].join("\n");
1952
2088
  });
1953
2089
  return [
1954
- "🏪 咕咕军火武器库 🏪",
2090
+ `🏪 咕咕军火武器库 - ${normalizedType} 🏪`,
1955
2091
  "使用“购买 武器名称”命令进行购买",
1956
2092
  "====================",
1957
2093
  ...items
@@ -2009,15 +2145,14 @@ ${achievementList.join("\n")}`;
2009
2145
  ].join("\n");
2010
2146
  }));
2011
2147
  return [
2012
- "🛡️ 当前武器列表",
2148
+ "🛡️ 当前拥有的武器列表",
2013
2149
  '使用"装备 武器名称"切换武器',
2014
2150
  "⚡表示当前装备武器",
2015
2151
  "────────────────",
2016
2152
  ...weaponDetails.length ? weaponDetails : ["空空如也,快去武器库看看吧!"],
2017
2153
  "────────────────",
2018
2154
  "💡 武器效果说明:",
2019
- " 已装备武器会在战斗中生效",
2020
- "🔧 改装效果仅在战斗时计算"
2155
+ "🔧 改装效果会在战斗中生效"
2021
2156
  ].join("\n");
2022
2157
  });
2023
2158
  ctx.command("ggcevo/装备 <weapon>").action(async ({ session }, weapon) => {
@@ -2159,6 +2294,7 @@ ${achievementList.join("\n")}`;
2159
2294
  });
2160
2295
  ctx.command("ggcevo/攻击 <targetType>").usage("使用 攻击 主宰/zz 或 攻击 子代/zd 来选择攻击目标").action(async (argv, targetType) => {
2161
2296
  const session = argv.session;
2297
+ let broadcastMessage = null;
2162
2298
  const targetAliases = {
2163
2299
  "主宰": ["主宰", "zz"],
2164
2300
  "子代": ["子代", "zd"]
@@ -2172,10 +2308,10 @@ ${achievementList.join("\n")}`;
2172
2308
  }
2173
2309
  if (!normalizedTarget) return "请指定正确的攻击目标:主宰/zz 或 子代/zd";
2174
2310
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
2175
- if (!profile) return "您的 QQ 未绑定句柄。";
2311
+ if (!profile) return "您暂未绑定句柄。";
2176
2312
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
2177
2313
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
2178
- if (existingEntries.length > 0) return "❌拒绝访问,您已被列入活动黑名单。";
2314
+ if (existingEntries.length > 0) return "❌ 拒绝访问,您已被列入黑名单。";
2179
2315
  const config2 = ctx.config;
2180
2316
  const unlimitedBossAttack = config2.unlimitedBossAttack;
2181
2317
  if (!unlimitedBossAttack) {
@@ -2192,93 +2328,17 @@ ${achievementList.join("\n")}`;
2192
2328
  handle,
2193
2329
  equipped: true
2194
2330
  });
2195
- if (!equippedWeapon) return "请先装备武器再挑战主宰";
2331
+ if (!equippedWeapon) return "请先装备武器再挑战主宰。";
2196
2332
  const activeBosses = await ctx.database.get("ggcevo_boss", { isActive: true });
2197
- if (!activeBosses.length) return "当前没有存活的主宰";
2333
+ if (!activeBosses.length) return "当前没有存活的主宰。";
2198
2334
  const targetBoss = normalizedTarget === "主宰" ? activeBosses.find((b) => b.type === "主宰") : activeBosses.find((b) => b.type === "子代");
2199
- if (!targetBoss) return `当前没有可攻击的${normalizedTarget === "主宰" ? "主宰" : "子代"}`;
2335
+ if (!targetBoss) return `当前没有可攻击的${normalizedTarget === "主宰" ? "主宰" : "子代"}。`;
2200
2336
  const bossGroup = bossPool.find((group) => group.main.id === targetBoss.groupId);
2201
- if (!bossGroup) return "无法获取BOSS组信息,请联系管理员";
2337
+ if (!bossGroup) return "无法获取BOSS组信息,请联系管理员。";
2202
2338
  const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
2203
2339
  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);
2340
+ const { damage: baseDamage, hasCrit } = await calculateTotalDamage(ctx, session, equippedWeapon, targetBoss);
2341
+ const actualDamage = Math.min(baseDamage, targetBoss.HP);
2282
2342
  const updatedHP = targetBoss.HP - actualDamage;
2283
2343
  const isDefeated = updatedHP <= 0;
2284
2344
  const [existingRecord] = await ctx.database.get("ggcevo_boss_damage", {
@@ -2290,6 +2350,7 @@ ${achievementList.join("\n")}`;
2290
2350
  handle,
2291
2351
  bossGroupId: targetBoss.groupId
2292
2352
  }, {
2353
+ playerName: session.username,
2293
2354
  totalDamage: existingRecord.totalDamage + actualDamage,
2294
2355
  // 改为实际伤害
2295
2356
  attackCount: existingRecord.attackCount + 1,
@@ -2413,13 +2474,13 @@ ${achievementList.join("\n")}`;
2413
2474
  await ctx.database.remove("ggcevo_boss_damage", {
2414
2475
  bossGroupId: targetBoss.groupId
2415
2476
  });
2416
- ctx.broadcast(config2.groupId, [
2417
- `🎯 主宰 ${targetBoss.name} 已被击败!`,
2418
- `所有子代已消失,下一个主宰将在1小时后出现`,
2477
+ broadcastMessage = [
2478
+ `🎯 主宰 ${targetBoss.name} 已被 ${session.username} 击破!`,
2479
+ `所有子代已消失,下一个主宰将在1小时后重生`,
2419
2480
  "",
2420
- "🎁 奖励发放结果:",
2481
+ "🏆 伤害排行榜奖励:",
2421
2482
  ...rewardMessages
2422
- ].join("\n"));
2483
+ ];
2423
2484
  } else {
2424
2485
  await ctx.database.set(
2425
2486
  "ggcevo_boss",
@@ -2429,11 +2490,10 @@ ${achievementList.join("\n")}`;
2429
2490
  HP: 0
2430
2491
  }
2431
2492
  );
2432
- ctx.broadcast(
2433
- config2.groupId,
2434
- `🎯 子代 ${targetBoss.name} 已被击败!
2435
- 主宰仍然存在,但是将额外遭受20%的易伤,继续战斗!`
2436
- );
2493
+ broadcastMessage = [
2494
+ `⚡ ${session.username} 击破了子代 ${targetBoss.name}!`,
2495
+ `【连锁效果】主宰获得 20% 易伤状态!`
2496
+ ];
2437
2497
  }
2438
2498
  } else {
2439
2499
  await ctx.database.set(
@@ -2455,15 +2515,20 @@ ${achievementList.join("\n")}`;
2455
2515
  // 改为实际伤害
2456
2516
  });
2457
2517
  }
2458
- return [
2518
+ const resultMessage = [
2459
2519
  `🔥 ${session.username} 使用武器 ${weaponName} 对 ${targetBoss.name} 发起攻击!`,
2460
2520
  `造成伤害:${actualDamage}${hasCrit ? "(✨ 暴击!)" : ""}`,
2461
- // 改为实际伤害
2462
2521
  `获得金币:${actualDamage}`,
2463
- // 改为实际伤害
2464
2522
  `目标剩余HP:${isDefeated ? 0 : updatedHP}/${targetBoss.type === "主宰" ? bossGroup.main.maxHP : bossGroup.minions[0].maxHP}`,
2465
2523
  isDefeated ? `🎉 成功击败 ${targetBoss.name}!` : ""
2466
- ].filter((line) => line !== "").join("\n");
2524
+ ].filter((line) => line).join("\n");
2525
+ await session.send(resultMessage);
2526
+ if (broadcastMessage) {
2527
+ const finalBroadcast = Array.isArray(broadcastMessage) ? broadcastMessage.join("\n") : broadcastMessage;
2528
+ await new Promise((resolve) => setTimeout(resolve, 500));
2529
+ ctx.broadcast(config2.groupId, finalBroadcast);
2530
+ }
2531
+ return;
2467
2532
  });
2468
2533
  ctx.command("ggcevo/初始化主宰", "初始化或重置主宰系统", { authority: 3 }).action(async () => {
2469
2534
  try {
@@ -2509,19 +2574,15 @@ ${achievementList.join("\n")}`;
2509
2574
  pageNum < totalPages ? `输入 伤害榜 ${pageNum + 1} 查看下一页` : "已是最后一页"
2510
2575
  ].join("\n");
2511
2576
  });
2512
- ctx.command("ggcevo/主宰状态", "查看当前主宰信息").alias("zz状态").action(async () => {
2577
+ ctx.command("ggcevo/主宰信息", "查看当前主宰信息").alias("zz信息").action(async () => {
2513
2578
  const activeBosses = await ctx.database.get("ggcevo_boss", { isActive: true });
2514
- if (!activeBosses.length) return "当前没有激活的BOSS";
2579
+ if (!activeBosses.length) return "当前没有存活的主宰。";
2515
2580
  const mainBoss = activeBosses.find((b) => b.type === "主宰");
2516
2581
  const minions = activeBosses.filter((b) => b.type === "子代");
2517
2582
  if (!mainBoss) return "当前BOSS数据异常,请联系管理员";
2518
2583
  const bossGroup = bossPool.find((group) => group.main.name === mainBoss.name);
2519
2584
  if (!bossGroup) return "BOSS配置数据异常,请联系管理员";
2520
2585
  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
2586
  let passiveDisplay = [];
2526
2587
  if (bossGroup.main.passive) {
2527
2588
  const activeMinions = await ctx.database.get("ggcevo_boss", {
@@ -2533,8 +2594,7 @@ ${achievementList.join("\n")}`;
2533
2594
  if (p === "孤立无援") return activeMinions.length === 0;
2534
2595
  return true;
2535
2596
  }).map((p) => {
2536
- const effect = passiveConfig[p].effect;
2537
- return `${p}:${formatEffect(effect)}`;
2597
+ return `${p}:${passiveConfig[p].description}`;
2538
2598
  });
2539
2599
  }
2540
2600
  const result = [
@@ -2544,12 +2604,12 @@ ${achievementList.join("\n")}`;
2544
2604
  `被动:${passiveDisplay.join(",") || "无"}`
2545
2605
  ];
2546
2606
  if (minions.length > 0) {
2547
- result.push("", "🟠 子代信息:");
2607
+ result.push("", "🟠 子代:");
2548
2608
  minions.forEach((minion) => {
2549
2609
  const minionConfig = bossGroup.minions.find((m) => m.name === minion.name);
2550
2610
  if (minionConfig) {
2551
2611
  const minionHpBar = createHpBar(minion.HP, minionConfig.maxHP);
2552
- const minionPassives = (minionConfig.passive || []).map((p) => `${p}:${formatEffect(passiveConfig[p].effect)}`).join(",");
2612
+ const minionPassives = (minionConfig.passive || []).map((p) => `${p}:${passiveConfig[p].description}`).join(",");
2553
2613
  result.push(
2554
2614
  `${minion.name}`,
2555
2615
  `${minionHpBar} (${minion.HP}/${minionConfig.maxHP})`,
@@ -2618,6 +2678,17 @@ function convertUTCtoChinaTime(input) {
2618
2678
  return new Date(chinaTimestamp);
2619
2679
  }
2620
2680
  __name(convertUTCtoChinaTime, "convertUTCtoChinaTime");
2681
+ function formatDate(d) {
2682
+ return d.toLocaleString("zh-CN", {
2683
+ timeZone: "Asia/Shanghai",
2684
+ year: "numeric",
2685
+ month: "2-digit",
2686
+ day: "2-digit",
2687
+ hour: "2-digit",
2688
+ minute: "2-digit"
2689
+ });
2690
+ }
2691
+ __name(formatDate, "formatDate");
2621
2692
  // Annotate the CommonJS export names for ESM import in node:
2622
2693
  0 && (module.exports = {
2623
2694
  Config,