koishi-plugin-ggcevo-game 1.4.44 → 1.4.46

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.
@@ -340,9 +340,12 @@ export declare const BattleEffectProcessor: {
340
340
  updates: Partial<BattleStatistics>;
341
341
  } | null;
342
342
  } | null;
343
- /** 天启超载护盾处理(层数相关群体回复) */
344
343
  handleOverdriveShield: (targetBoss: any, activeBosses: any[]) => {
345
344
  messages: string[];
345
+ targetUpdates: {
346
+ name: string;
347
+ updates: Partial<BattleStatistics>;
348
+ } | null;
346
349
  otherUpdates: Array<{
347
350
  name: string;
348
351
  updates: Partial<BattleStatistics>;
@@ -362,7 +365,6 @@ export declare const BattleEffectProcessor: {
362
365
  messages: string[];
363
366
  tempMark: boolean;
364
367
  };
365
- /** 轰炸引导处理(层数相关能量回复) */
366
368
  handleBombardmentGuide: (targetBoss: any) => {
367
369
  messages: string[];
368
370
  targetUpdates: {
package/lib/database.d.ts CHANGED
@@ -22,6 +22,7 @@ declare module 'koishi' {
22
22
  ggcevo_Mining: MiningRecord;
23
23
  ggcevo_task: TaskProgress;
24
24
  ggcevo_permissions: Permissions;
25
+ ggcevo_pk_protection: PKProtection;
25
26
  }
26
27
  }
27
28
  export interface Backpack {
@@ -186,3 +187,16 @@ export interface Permissions {
186
187
  legendarypermissions: number;
187
188
  explosiondoorauthority: number;
188
189
  }
190
+ export interface PKProtection {
191
+ id: number;
192
+ handle: string;
193
+ startTime: Date;
194
+ endTime: Date;
195
+ /**
196
+ * 保护状态(建议添加)
197
+ * active - 保护中
198
+ * expired - 已过期
199
+ * canceled - 手动取消
200
+ */
201
+ status: 'active' | 'expired' | 'canceled';
202
+ }
package/lib/index.js CHANGED
@@ -1458,11 +1458,11 @@ var passiveConfig = {
1458
1458
  },
1459
1459
  "灵能构造炉": {
1460
1460
  type: "状态获得(技能获得)",
1461
- description: "受击时5%概率随机获得以下技能之一:天启超载护盾/塌缩脉冲/地毯式轰炸/轰炸引导"
1461
+ description: "受击时1%概率随机获得以下技能之一:天启超载护盾/塌缩脉冲/地毯式轰炸/轰炸引导"
1462
1462
  },
1463
1463
  "天启超载护盾": {
1464
1464
  type: "生存强化(生命回复)",
1465
- description: "受击时10%概率为所有存活异形回复(「光影之刃」层数×10)点生命"
1465
+ description: "受击时10%概率触发,消耗当前「光影之刃」层数的一半(向下取整),并为所有存活异形回复(消耗层数×10)点生命"
1466
1466
  },
1467
1467
  "塌缩脉冲": {
1468
1468
  type: "状态叠加(层数叠加)",
@@ -1470,11 +1470,11 @@ var passiveConfig = {
1470
1470
  },
1471
1471
  "地毯式轰炸": {
1472
1472
  type: "状态移除+伤害增减(正面)",
1473
- description: "移除孤立无援状态,受到的伤害降低100%"
1473
+ description: "移除孤立无援状态,受到的伤害降低80%"
1474
1474
  },
1475
1475
  "轰炸引导": {
1476
1476
  type: "生存强化(能量回复)",
1477
- description: "受击时10%概率回复(「光影之刃」层数×10)点能量"
1477
+ description: "受击时10%概率触发,消耗当前「光影之刃」层数的一半(向下取整),并回复(消耗层数×10)点能量"
1478
1478
  }
1479
1479
  };
1480
1480
 
@@ -2390,6 +2390,21 @@ async function getRankInfo(ctx, config, handle) {
2390
2390
  ------------------------------`;
2391
2391
  }
2392
2392
  __name(getRankInfo, "getRankInfo");
2393
+ function isWithinProtection(protections) {
2394
+ const now = /* @__PURE__ */ new Date();
2395
+ return protections.some(
2396
+ (p) => p.status === "active" && now >= p.startTime && now <= p.endTime
2397
+ );
2398
+ }
2399
+ __name(isWithinProtection, "isWithinProtection");
2400
+ function formatTime(date) {
2401
+ return date.toLocaleString("zh-CN", {
2402
+ year: "numeric",
2403
+ month: "2-digit",
2404
+ day: "2-digit"
2405
+ });
2406
+ }
2407
+ __name(formatTime, "formatTime");
2393
2408
 
2394
2409
  // src/boss/BattleEffectProcessor.ts
2395
2410
  var battleStatsMap = {};
@@ -3699,7 +3714,7 @@ var BattleEffectProcessor = {
3699
3714
  if (!targetBoss.skills.includes("灵能构造炉")) {
3700
3715
  return null;
3701
3716
  }
3702
- const baseProbability = 0.05;
3717
+ const baseProbability = 0.01;
3703
3718
  if (Math.random() >= baseProbability) {
3704
3719
  return null;
3705
3720
  }
@@ -3723,7 +3738,7 @@ var BattleEffectProcessor = {
3723
3738
  targetUpdates
3724
3739
  };
3725
3740
  }, "handlePsychicForge"),
3726
- /** 天启超载护盾处理(层数相关群体回复) */
3741
+ // 修改后的天启超载护盾处理函数
3727
3742
  handleOverdriveShield: /* @__PURE__ */ __name(function(targetBoss, activeBosses) {
3728
3743
  const messages = [];
3729
3744
  const otherUpdates = [];
@@ -3733,20 +3748,31 @@ var BattleEffectProcessor = {
3733
3748
  if (Math.random() >= 0.1) {
3734
3749
  return null;
3735
3750
  }
3736
- const baseHealAmount = (targetBoss.skillStacks || 0) * 10;
3751
+ const currentStacks = targetBoss.skillStacks || 0;
3752
+ const consumedStacks = Math.floor(currentStacks / 2);
3753
+ if (consumedStacks <= 0) {
3754
+ return null;
3755
+ }
3737
3756
  const survivingBosses = activeBosses.filter((boss) => boss.isActive);
3757
+ messages.push(`🛡️ 【天启超载护盾】触发:消耗${consumedStacks}层「光影之刃」`);
3738
3758
  survivingBosses.forEach((boss) => {
3739
- const bossName = boss.name;
3740
- if (baseHealAmount > 0) {
3741
- otherUpdates.push({
3742
- name: bossName,
3743
- updates: { hpChange: baseHealAmount }
3744
- });
3745
- }
3746
- messages.push(`🛡️ 【天启超载护盾】触发:为「${bossName}」回复${baseHealAmount}点生命值`);
3759
+ const healAmount = consumedStacks * 10;
3760
+ otherUpdates.push({
3761
+ name: boss.name,
3762
+ updates: { hpChange: healAmount }
3763
+ });
3764
+ messages.push(`为「${boss.name}」回复${healAmount}点生命值`);
3747
3765
  });
3766
+ const targetUpdates = {
3767
+ name: targetBoss.name,
3768
+ updates: {
3769
+ skillStacksChanged: -consumedStacks
3770
+ // 消耗层数
3771
+ }
3772
+ };
3748
3773
  return {
3749
3774
  messages,
3775
+ targetUpdates,
3750
3776
  otherUpdates
3751
3777
  };
3752
3778
  }, "handleOverdriveShield"),
@@ -3782,14 +3808,13 @@ var BattleEffectProcessor = {
3782
3808
  if (!targetBoss.skills.includes("地毯式轰炸")) {
3783
3809
  return null;
3784
3810
  }
3785
- nerfMultiplier = 1;
3786
- messages.push(`💣 【地毯式轰炸】生效:受到的伤害-100%`);
3811
+ nerfMultiplier = 0.8;
3812
+ messages.push(`💣 【地毯式轰炸】生效:受到的伤害-80%`);
3787
3813
  return { nerfMultiplier, messages, tempMark: true };
3788
3814
  }, "handleCarpetBombing"),
3789
- /** 轰炸引导处理(层数相关能量回复) */
3815
+ // 修改后的轰炸引导处理函数
3790
3816
  handleBombardmentGuide: /* @__PURE__ */ __name(function(targetBoss) {
3791
3817
  const messages = [];
3792
- let targetUpdates = null;
3793
3818
  if (!targetBoss.skills.includes("轰炸引导")) {
3794
3819
  return null;
3795
3820
  }
@@ -3797,14 +3822,21 @@ var BattleEffectProcessor = {
3797
3822
  return null;
3798
3823
  }
3799
3824
  const currentStacks = targetBoss.skillStacks || 0;
3800
- const energyGained = currentStacks * 10;
3801
- targetUpdates = {
3825
+ const consumedStacks = Math.floor(currentStacks / 2);
3826
+ if (consumedStacks <= 0) {
3827
+ return null;
3828
+ }
3829
+ const energyGained = consumedStacks * 10;
3830
+ const targetUpdates = {
3802
3831
  name: targetBoss.name,
3803
3832
  updates: {
3833
+ skillStacksChanged: -consumedStacks,
3834
+ // 消耗层数
3804
3835
  energyChange: energyGained
3836
+ // 回复能量
3805
3837
  }
3806
3838
  };
3807
- messages.push(`🎯 【轰炸引导】触发:当前${currentStacks}层「光影之刃」,获得${energyGained}点能量`);
3839
+ messages.push(`🎯 【轰炸引导】触发:消耗${consumedStacks}层「光影之刃」,获得${energyGained}点能量`);
3808
3840
  return {
3809
3841
  messages,
3810
3842
  targetUpdates
@@ -5052,6 +5084,16 @@ function apply(ctx, config) {
5052
5084
  }, {
5053
5085
  primary: "handle"
5054
5086
  });
5087
+ ctx.model.extend("ggcevo_pk_protection", {
5088
+ id: "unsigned",
5089
+ handle: "string",
5090
+ startTime: "timestamp",
5091
+ endTime: "timestamp",
5092
+ status: "string"
5093
+ }, {
5094
+ primary: "id",
5095
+ autoInc: true
5096
+ });
5055
5097
  ctx.setInterval(async () => {
5056
5098
  const totalBosses = await ctx.database.select("ggcevo_boss").execute((row) => import_koishi.$.count(row.name));
5057
5099
  const groupId = [...config.groupId];
@@ -5226,6 +5268,15 @@ function apply(ctx, config) {
5226
5268
  ctx.logger.error("监控失败:", error);
5227
5269
  }
5228
5270
  }, config.checkInterval * 1e3);
5271
+ ctx.setInterval(async () => {
5272
+ const now = /* @__PURE__ */ new Date();
5273
+ await ctx.database.set("ggcevo_pk_protection", {
5274
+ endTime: { $lt: now },
5275
+ status: "active"
5276
+ }, {
5277
+ status: "expired"
5278
+ });
5279
+ }, 24 * 60 * 60 * 1e3);
5229
5280
  ctx.command("ggcevo/抽奖").action(async (argv) => {
5230
5281
  const session = argv.session;
5231
5282
  let winCount = 0;
@@ -6416,6 +6467,38 @@ ${items.join("、")}
6416
6467
  if (!targetCareer?.group || !validGroups.has(targetCareer.group)) {
6417
6468
  return "❌ 对方尚未加入人类联盟或辛迪加海盗,不能参与PK";
6418
6469
  }
6470
+ const targetProtections = await ctx.database.get("ggcevo_pk_protection", {
6471
+ handle: targetHandle,
6472
+ status: "active"
6473
+ });
6474
+ if (isWithinProtection(targetProtections)) {
6475
+ const nearestEndTime = targetProtections.reduce(
6476
+ (max, p) => p.endTime > max ? p.endTime : max,
6477
+ /* @__PURE__ */ new Date(0)
6478
+ );
6479
+ return `🛡️ ${targetRankname}正处于PK保护期(至 ${nearestEndTime.toLocaleString("zh-CN")}),无法挑战`;
6480
+ }
6481
+ const initiatorProtections = await ctx.database.get("ggcevo_pk_protection", {
6482
+ handle: initiatorHandle,
6483
+ status: "active"
6484
+ });
6485
+ let hasProtection = isWithinProtection(initiatorProtections);
6486
+ if (hasProtection) {
6487
+ const protectionList = initiatorProtections.filter((p) => /* @__PURE__ */ new Date() < p.endTime).map((p) => `🛡️ ID:${p.id} ${formatTime(p.startTime)} ~ ${formatTime(p.endTime)}`).join("\n");
6488
+ await session.send(`⚠️ 您正处于PK保护期:
6489
+ ${protectionList}
6490
+
6491
+ 发起PK将自动解除保护,确认继续?
6492
+ 回复"是"继续PK,或回复其他内容退出`);
6493
+ const confirm = await session.prompt(3e4);
6494
+ if (confirm !== "是") return "已取消PK操作,保护期仍有效。";
6495
+ await ctx.database.set("ggcevo_pk_protection", {
6496
+ handle: initiatorHandle
6497
+ }, {
6498
+ status: "canceled"
6499
+ });
6500
+ hasProtection = false;
6501
+ }
6419
6502
  if (targetCareer.group === "人类联盟") {
6420
6503
  let joinDate;
6421
6504
  if (typeof targetCareer.date === "string") {
@@ -6435,9 +6518,9 @@ ${items.join("、")}
6435
6518
  handle: targetHandle
6436
6519
  });
6437
6520
  const isNewPlayer = !targetPKRecord;
6438
- const hasProtection = diffInDays < 30;
6521
+ const hasProtection2 = diffInDays < 30;
6439
6522
  const isPKDisabled = targetPKRecord && !targetPKRecord.enable;
6440
- if ((isNewPlayer || isPKDisabled) && hasProtection) {
6523
+ if ((isNewPlayer || isPKDisabled) && hasProtection2) {
6441
6524
  return `🛡️ 该玩家是人类联盟成员,当前处于30天保护期内(剩余${30 - diffInDays}天),无法PK`;
6442
6525
  }
6443
6526
  }
@@ -7798,6 +7881,56 @@ ${validTypes.join("、")}`;
7798
7881
  return "加入阵营时发生错误,请稍后再试";
7799
7882
  }
7800
7883
  });
7884
+ ctx.command("ggcevo/退出", "退出当前阵营").alias("退出阵营").action(async ({ session }) => {
7885
+ const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
7886
+ if (!profile) return "🔒 需要先绑定游戏句柄。";
7887
+ const { regionId, realmId, profileId } = profile;
7888
+ const handle = `${regionId}-S2-${realmId}-${profileId}`;
7889
+ const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
7890
+ if (existingEntries.length > 0) {
7891
+ return `⛔ 您已被列入黑名单。`;
7892
+ }
7893
+ const [currentCareer] = await ctx.database.get("ggcevo_careers", { handle });
7894
+ if (!currentCareer || !currentCareer.group) {
7895
+ return "您尚未加入任何阵营。";
7896
+ }
7897
+ const [signData] = await ctx.database.get("ggcevo_sign", { handle });
7898
+ const userCoins = signData?.totalRewards || 0;
7899
+ let exitCost = 0;
7900
+ let exitFactionName = "";
7901
+ if (currentCareer.group === "人类联盟") {
7902
+ exitCost = 2e3;
7903
+ exitFactionName = "人类联盟";
7904
+ } else if (currentCareer.group === "辛迪加海盗") {
7905
+ exitCost = 4e3;
7906
+ exitFactionName = "辛迪加海盗";
7907
+ }
7908
+ if (userCoins < exitCost) {
7909
+ return `退出${exitFactionName}需要${exitCost}金币,您当前只有${userCoins}金币`;
7910
+ }
7911
+ await session.send(`确定要花费${exitCost}金币退出${exitFactionName}吗?(30秒内输入"是"确认退出)`);
7912
+ const confirm = await session.prompt(3e4);
7913
+ if (confirm !== "是") return "已取消退出操作。";
7914
+ try {
7915
+ await ctx.database.upsert("ggcevo_sign", [{
7916
+ handle,
7917
+ totalRewards: Math.max(0, signData.totalRewards - exitCost)
7918
+ }], ["handle"]);
7919
+ await ctx.database.upsert("ggcevo_careers", [{
7920
+ handle,
7921
+ group: "",
7922
+ career: "",
7923
+ redcrystal: currentCareer.redcrystal,
7924
+ // 保留红晶数量
7925
+ date: null
7926
+ // 清空加入日期
7927
+ }], ["handle"]);
7928
+ return `✅ 成功花费${exitCost}金币退出${exitFactionName}!`;
7929
+ } catch (err) {
7930
+ ctx.logger.error("退出阵营失败:", err);
7931
+ return "退出阵营时发生错误,请稍后再试";
7932
+ }
7933
+ });
7801
7934
  ctx.command("ggcevo/转职 [profession]", "转职系统").action(async ({ session }, profession) => {
7802
7935
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
7803
7936
  if (!profile) return "🔒 需要先绑定游戏句柄。";
@@ -7886,39 +8019,62 @@ ${validTypes.join("、")}`;
7886
8019
  });
7887
8020
  if (!profile) return "🔒 需要先绑定游戏句柄。";
7888
8021
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
7889
- const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
7890
- if (!careerData) return "您尚未加入任何阵营。";
7891
- const factionconfig = careerData.group === "辛迪加海盗" ? syndicatePirateConfig : spaceStationCrewConfig;
7892
- const profession = factionconfig.find((p) => p.professionName === careerData.career);
7893
- const effectDisplay = profession?.effect || "暂无特殊效果";
7894
- const joinDate = new Date(careerData.date);
7895
- const formattedDate = `${joinDate.getFullYear()}年${joinDate.getMonth() + 1}月${joinDate.getDate()}日`;
7896
- const powerValue = await calculateTotalPower(ctx, config, handle);
7897
- const infoCard = [
7898
- `🎮 游戏句柄:${handle}`,
7899
- `⚔️ 当前战力:${powerValue}`,
7900
- // 新增战力显示行
7901
- `🎯 当前阵营:${careerData.group}`,
7902
- `👔 当前职业:${careerData.career}`,
7903
- `✨ 职业效果:${effectDisplay}`,
7904
- `🗓️ 加入时间:${formattedDate}`
7905
- ];
7906
- if (careerData.group === "人类联盟") {
7907
- const techEntries = await ctx.database.get("ggcevo_tech", { handle });
7908
- const activeTechs = techEntries.filter((entry) => entry.level > 0).map((entry) => {
7909
- const techConfig = Spacestationtechnology.find((t) => t.techId === entry.techId);
7910
- return techConfig ? `🛠️ ${techConfig.techname} [${entry.level}/${techConfig.maxLevel}]` : null;
7911
- }).filter(Boolean);
7912
- if (activeTechs.length > 0) {
7913
- infoCard.push("", "〓 科技研发 〓", ...activeTechs);
8022
+ let [careerData] = await ctx.database.get("ggcevo_careers", { handle });
8023
+ if (!careerData) {
8024
+ await ctx.database.create("ggcevo_careers", {
8025
+ handle,
8026
+ group: "",
8027
+ career: "",
8028
+ redcrystal: 0,
8029
+ date: null
8030
+ });
8031
+ [careerData] = await ctx.database.get("ggcevo_careers", { handle });
8032
+ }
8033
+ const infoCard = [`🎮 游戏句柄:${handle}`];
8034
+ try {
8035
+ const powerValue = await calculateTotalPower(ctx, config, handle);
8036
+ infoCard.push(`⚔️ 当前战力:${powerValue}`);
8037
+ } catch (err) {
8038
+ ctx.logger.warn("战力计算失败", err);
8039
+ }
8040
+ if (careerData.group) {
8041
+ const factionconfig = careerData.group === "辛迪加海盗" ? syndicatePirateConfig : spaceStationCrewConfig;
8042
+ const profession = factionconfig.find((p) => p.professionName === careerData.career);
8043
+ const effectDisplay = profession?.effect || "无特殊效果";
8044
+ infoCard.push(
8045
+ `🎯 当前阵营:${careerData.group}`,
8046
+ `👔 当前职业:${careerData.career}`,
8047
+ `✨ 职业效果:${effectDisplay}`
8048
+ );
8049
+ if (careerData.date) {
8050
+ const joinDate = new Date(careerData.date);
8051
+ const formattedDate = `${joinDate.getFullYear()}年${joinDate.getMonth() + 1}月${joinDate.getDate()}日`;
8052
+ infoCard.push(`🗓️ 加入时间:${formattedDate}`);
7914
8053
  }
8054
+ if (careerData.group === "人类联盟") {
8055
+ const techEntries = await ctx.database.get("ggcevo_tech", { handle });
8056
+ const activeTechs = techEntries.filter((entry) => entry.level > 0).map((entry) => {
8057
+ const techConfig = Spacestationtechnology.find((t) => t.techId === entry.techId);
8058
+ return techConfig ? `🛠️ ${techConfig.techname} [${entry.level}/${techConfig.maxLevel}]` : null;
8059
+ }).filter(Boolean);
8060
+ if (activeTechs.length > 0) {
8061
+ infoCard.push("", "〓 科技研发 〓", ...activeTechs);
8062
+ }
8063
+ }
8064
+ } else {
8065
+ infoCard.push(
8066
+ "🎯 当前阵营:无",
8067
+ "👔 当前职业:无",
8068
+ "",
8069
+ '💡 使用"加入阵营"指令选择你的阵营'
8070
+ );
7915
8071
  }
7916
- const promptMessage = careerData.group === "辛迪加海盗" ? "💡 提示:红晶可通过主动发起PK获得(无论胜负)" : "💡 提示:使用「转职」指令可变更职业";
8072
+ const divider = "〓═════════〓";
8073
+ const promptMessage = careerData.group === "辛迪加海盗" ? "💡 提示:红晶可通过主动发起PK获得(无论胜负)" : careerData.group ? "💡 提示:使用「转职」指令可变更职业" : "";
7917
8074
  return [
7918
8075
  `〓 职业档案 〓`,
7919
8076
  ...infoCard,
7920
- "〓═════════〓\n" + promptMessage
7921
- // 提示信息放在分隔线下方
8077
+ ...promptMessage ? [divider, promptMessage] : []
7922
8078
  ].join("\n");
7923
8079
  } catch (error) {
7924
8080
  ctx.logger.error("查询职业信息失败:", error);
@@ -8398,7 +8554,7 @@ ${Spacestationtechnology.map((t) => t.techname).join("、")}`;
8398
8554
  // 新增累加
8399
8555
  });
8400
8556
  });
8401
- const formatTime = /* @__PURE__ */ __name((mins) => {
8557
+ const formatTime2 = /* @__PURE__ */ __name((mins) => {
8402
8558
  const hours = Math.floor(mins / 60);
8403
8559
  const minutes = mins % 60;
8404
8560
  return `${hours}小时${minutes}分钟`;
@@ -8407,7 +8563,7 @@ ${Spacestationtechnology.map((t) => t.techname).join("、")}`;
8407
8563
  "⛏️ 挖矿报告",
8408
8564
  `🕒 开始时间:${record.startTime.toLocaleString("zh-CN", { hour12: false })}`,
8409
8565
  `⏱️ 结束时间:${nowtime.toLocaleString("zh-CN", { hour12: false })}`,
8410
- `⏳ 持续时间:${formatTime(duration)}`
8566
+ `⏳ 持续时间:${formatTime2(duration)}`
8411
8567
  ];
8412
8568
  const maxHours = tech.level === 5 ? 48 : 24;
8413
8569
  if (duration > maxHours * 60) {
@@ -8559,6 +8715,67 @@ ${Spacestationtechnology.map((t) => t.techname).join("、")}`;
8559
8715
  return "处理任务时发生错误,请稍后重试。";
8560
8716
  }
8561
8717
  });
8718
+ ctx.command("ggcevo/购买保护卡", "花费600金币购买一周PK保护卡").action(async ({ session }) => {
8719
+ try {
8720
+ const userId = session.userId;
8721
+ const [profile] = await ctx.database.get("sc2arcade_player", { userId });
8722
+ if (!profile) return "🔒 请先绑定游戏句柄。";
8723
+ const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
8724
+ const isBlacklisted = await ctx.database.get("ggcevo_blacklist", { handle });
8725
+ if (isBlacklisted.length > 0) return "⛔ 您已被列入黑名单。";
8726
+ const [signRecord] = await ctx.database.get("ggcevo_sign", { handle });
8727
+ if (!signRecord) return "您还没有签到记录,请先签到一次。";
8728
+ const currentGold = signRecord.totalRewards;
8729
+ const protectionCost = 600;
8730
+ if (currentGold < protectionCost) {
8731
+ return `金币不足,购买保护卡需要${protectionCost}金币(当前:${currentGold}金币)`;
8732
+ }
8733
+ await session.send(`⚠️ 请问您是否花费${protectionCost}金币购买一周的PK保护卡?
8734
+ 回复"是"购买,或回复其他内容退出`);
8735
+ const confirm = await session.prompt(3e4);
8736
+ if (confirm !== "是") return "已取消购买操作,金币未扣除。";
8737
+ const startTime = /* @__PURE__ */ new Date();
8738
+ const endTime = /* @__PURE__ */ new Date();
8739
+ endTime.setDate(startTime.getDate() + 7);
8740
+ const formatTime2 = /* @__PURE__ */ __name((date) => {
8741
+ return date.toLocaleString("zh-CN", {
8742
+ year: "numeric",
8743
+ month: "2-digit",
8744
+ day: "2-digit"
8745
+ });
8746
+ }, "formatTime");
8747
+ const existingProtections = await ctx.database.get("ggcevo_pk_protection", {
8748
+ handle,
8749
+ endTime: { $gt: startTime },
8750
+ status: "active"
8751
+ });
8752
+ if (existingProtections.length > 0) {
8753
+ const nearestEnd = existingProtections.reduce(
8754
+ (max, p) => p.endTime > max ? p.endTime : max,
8755
+ /* @__PURE__ */ new Date(0)
8756
+ );
8757
+ return `您已拥有保护卡(至 ${formatTime2(nearestEnd)}),请到期后再购买`;
8758
+ }
8759
+ await ctx.database.withTransaction(async () => {
8760
+ await ctx.database.set("ggcevo_sign", handle, {
8761
+ totalRewards: currentGold - protectionCost
8762
+ });
8763
+ await ctx.database.create("ggcevo_pk_protection", {
8764
+ handle,
8765
+ startTime,
8766
+ endTime,
8767
+ status: "active"
8768
+ });
8769
+ });
8770
+ return `✅ 成功购买PK保护卡!
8771
+ 💰 扣除金币: ${protectionCost}
8772
+ ⏱️ 生效时间: ${formatTime2(startTime)}
8773
+ 🛡️ 保护结束: ${formatTime2(endTime)}`;
8774
+ } catch (error) {
8775
+ console.error("购买保护卡出错:", error);
8776
+ return "购买过程中发生错误,请稍后再试";
8777
+ }
8778
+ });
8562
8779
  }
8563
8780
  __name(apply, "apply");
8564
8781
  // Annotate the CommonJS export names for ESM import in node:
package/lib/utils.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Context } from 'koishi';
2
2
  import { Config } from './index';
3
+ import { PKProtection } from './database';
3
4
  export declare function gachaWithPity(ctx: Context, handle: string): Promise<boolean>;
4
5
  export declare function gachaWithHiddenAward(ctx: Context, handle: string): Promise<boolean>;
5
6
  export declare function checkSensitiveWord(ctx: Context, content: string): Promise<boolean>;
@@ -20,3 +21,5 @@ export declare function handleTechUpgrade(ctx: Context, handle: string, target:
20
21
  export declare function handleWeaponUpgrade(ctx: Context, handle: string, target: string): Promise<string>;
21
22
  export declare function generateUpgradePriceList(ctx: Context, handle: string): Promise<string>;
22
23
  export declare function getRankInfo(ctx: Context, config: Config, handle: string): Promise<string>;
24
+ export declare function isWithinProtection(protections: PKProtection[]): boolean;
25
+ export declare function formatTime(date: Date): string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-ggcevo-game",
3
3
  "description": "《星际争霸2》咕咕虫-evolved地图的专属游戏助手插件,集成天梯排行、抽奖系统、签到福利、兑换商城等丰富功能。",
4
- "version": "1.4.44",
4
+ "version": "1.4.46",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [