koishi-plugin-ggcevo-game 1.2.72 → 1.3.0

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.d.ts CHANGED
@@ -41,6 +41,7 @@ declare module 'koishi' {
41
41
  ggcevo_careers: careers;
42
42
  ggcevo_warehouse: warehouse;
43
43
  ggcevo_tech: tech;
44
+ ggcevo_Mining: Mining;
44
45
  }
45
46
  }
46
47
  export interface backpack {
@@ -189,4 +190,8 @@ export interface tech {
189
190
  techId: number;
190
191
  level: number;
191
192
  }
193
+ export interface Mining {
194
+ handle: string;
195
+ startTime: Date;
196
+ }
192
197
  export declare function apply(ctx: Context, config: Config): void;
package/lib/index.js CHANGED
@@ -284,6 +284,12 @@ function apply(ctx, config) {
284
284
  }, {
285
285
  primary: ["handle", "techId"]
286
286
  });
287
+ ctx.model.extend("ggcevo_Mining", {
288
+ handle: "string",
289
+ startTime: "timestamp"
290
+ }, {
291
+ primary: "handle"
292
+ });
287
293
  const weaponConfig = {
288
294
  // 武器配置
289
295
  "高斯步枪": {
@@ -408,6 +414,14 @@ function apply(ctx, config) {
408
414
  price: 0,
409
415
  redCrystalCost: 30,
410
416
  effects: "当主宰为“空间站感染虫”时才能使用,对“空间站哨枪塔”造成其当前血量值的伤害(获得等同于伤害值的金币)"
417
+ },
418
+ "闪光弹": {
419
+ id: 2,
420
+ type: "手榴弹",
421
+ description: "非致命军用炸药",
422
+ price: 75,
423
+ redCrystalCost: 0,
424
+ effects: "对目标使用后,清空其累计技能计数"
411
425
  }
412
426
  };
413
427
  const modConfig = {
@@ -696,9 +710,9 @@ function apply(ctx, config) {
696
710
  },
697
711
  {
698
712
  professionName: "情报副官",
699
- effect: "升级联盟空间站科技享有80%的折扣",
700
- requirements: "拥有500枚金币",
701
- Jobtransfer: false,
713
+ effect: "升级空间站科技花费的金币是原价的80%",
714
+ requirements: "将一个空间站科技升至3级或以上",
715
+ Jobtransfer: true,
702
716
  costcoins: 3e3
703
717
  },
704
718
  {
@@ -734,7 +748,7 @@ function apply(ctx, config) {
734
748
  {
735
749
  professionName: "能量武器专家",
736
750
  effect: "能量武器攻击伤害+20%,解锁MK-4激光步枪(传奇)购买权限",
737
- requirements: "拥有一把3级及以上等级的能量武器",
751
+ requirements: "拥有一把3级或以上等级的能量武器",
738
752
  Jobtransfer: true,
739
753
  costcoins: 0,
740
754
  costredcrystal: 20
@@ -749,7 +763,7 @@ function apply(ctx, config) {
749
763
  },
750
764
  {
751
765
  professionName: "枪手",
752
- effect: "武器等级上限为7级,升级武器享有80%的折扣(可与祈愿叠加)",
766
+ effect: "武器等级上限为7",
753
767
  requirements: "拥有2把武器等级为6的武器",
754
768
  Jobtransfer: false,
755
769
  costcoins: 0,
@@ -766,7 +780,7 @@ function apply(ctx, config) {
766
780
  {
767
781
  professionName: "纵火狂",
768
782
  effect: "热能武器攻击伤害+20%,解锁龙息散弹枪(传奇)购买权限",
769
- requirements: "拥有一把3级及以上等级的热能武器",
783
+ requirements: "拥有一把3级或以上等级的热能武器",
770
784
  Jobtransfer: true,
771
785
  costcoins: 0,
772
786
  costredcrystal: 20
@@ -832,74 +846,78 @@ function apply(ctx, config) {
832
846
  {
833
847
  techId: 1,
834
848
  techname: "采掘系统",
849
+ careerNames: ["深空矿工", "情报副官"],
850
+ // 新增职业名称字段
835
851
  maxLevel: 5,
836
852
  levels: [
837
853
  {
838
854
  level: 1,
839
855
  cost: 500,
840
- description: "提高挖矿效率,每日签到奖励+5%",
841
- careerBonus: "深空矿工/情报副官: 每日签到奖励+10%"
856
+ description: "提高挖矿效率,每日签到金币奖励+5%",
857
+ careerBonus: "深空矿工/情报副官: 每日签到金币奖励+10%"
842
858
  },
843
859
  {
844
860
  level: 2,
845
861
  cost: 1750,
846
- description: "提高挖矿效率,每日签到奖励+10%",
847
- careerBonus: "深空矿工/情报副官: 每日签到奖励+20%,解锁专属“挖矿”指令"
862
+ description: "提高挖矿效率,每日签到金币奖励+10%",
863
+ careerBonus: "深空矿工/情报副官: 每日签到金币奖励+20%,解锁专属“挖矿”权限"
848
864
  },
849
865
  {
850
866
  level: 3,
851
867
  cost: 2950,
852
- description: "提高挖矿效率,每日签到奖励+15%",
853
- careerBonus: "深空矿工/情报副官: 每日签到奖励+30%,解锁专属“挖矿”指令"
868
+ description: "提高挖矿效率,每日签到金币奖励+15%",
869
+ careerBonus: "深空矿工/情报副官: 每日签到金币奖励+30%,解锁专属“挖矿”权限,并且挖矿效率提高10%"
854
870
  },
855
871
  {
856
872
  level: 4,
857
873
  cost: 4250,
858
- description: "提高挖矿效率,每日签到奖励+20%",
859
- careerBonus: "深空矿工/情报副官: 每日签到奖励+40%,解锁专属“挖矿”指令,并且挖矿效率提高25%"
874
+ description: "提高挖矿效率,每日签到金币奖励+20%",
875
+ careerBonus: "深空矿工/情报副官: 每日签到金币奖励+40%,解锁专属“挖矿”权限,并且挖矿效率提高20%"
860
876
  },
861
877
  {
862
878
  level: 5,
863
879
  cost: 5375,
864
- description: "提高挖矿效率,每日签到奖励+25%",
865
- careerBonus: "深空矿工/情报副官: 每日签到奖励+50%,解锁专属“挖矿”指令,并且挖矿效率提高50%"
880
+ description: "提高挖矿效率,每日签到金币奖励+25%",
881
+ careerBonus: "深空矿工/情报副官: 每日签到金币奖励+50%,解锁专属“挖矿”权限,并且挖矿效率提高30%"
866
882
  }
867
883
  ]
868
884
  },
869
885
  {
870
886
  techId: 2,
871
887
  techname: "武器系统",
888
+ careerNames: ["武器中士", "情报副官"],
889
+ // 新增职业名称字段
872
890
  maxLevel: 5,
873
891
  levels: [
874
892
  {
875
893
  level: 1,
876
894
  cost: 500,
877
- description: "提升空间站武器等级,升级/改装武器享有5%的折扣",
878
- careerBonus: "武器中士/情报副官: 升级/改装武器享有10%的折扣"
895
+ description: "提升空间站武器等级,升级武器享有5%的折扣",
896
+ careerBonus: "武器中士/情报副官: 升级武器享有10%的折扣"
879
897
  },
880
898
  {
881
899
  level: 2,
882
900
  cost: 1500,
883
- description: "提升空间站武器等级,升级/改装武器享有10%的折扣",
884
- careerBonus: "武器中士/情报副官: 升级/改装武器享有20%的折扣,购买武器享有10%的折扣(非传奇)"
901
+ description: "提升空间站武器等级,升级武器享有10%的折扣",
902
+ careerBonus: "武器中士/情报副官: 升级武器享有20%的折扣,购买武器享有10%的折扣(非传奇)"
885
903
  },
886
904
  {
887
905
  level: 3,
888
906
  cost: 2550,
889
- description: "提升空间站武器等级,升级/改装武器享有15%的折扣",
890
- careerBonus: "武器中士/情报副官: 升级/改装武器享有30%的折扣,购买武器享有15%的折扣(非传奇)"
907
+ description: "提升空间站武器等级,升级武器享有15%的折扣",
908
+ careerBonus: "武器中士/情报副官: 升级武器享有30%的折扣,购买武器享有15%的折扣(非传奇)"
891
909
  },
892
910
  {
893
911
  level: 4,
894
912
  cost: 3950,
895
- description: "提升空间站武器等级,升级/改装武器享有20%的折扣",
896
- careerBonus: "武器中士/情报副官: 在升级/改装武器享有40%的折扣,购买武器享有20%的折扣(非传奇)"
913
+ description: "提升空间站武器等级,升级武器享有20%的折扣",
914
+ careerBonus: "武器中士/情报副官: 在升级武器享有40%的折扣,购买武器享有20%的折扣(非传奇)"
897
915
  },
898
916
  {
899
917
  level: 5,
900
918
  cost: 4650,
901
- description: "提升空间站武器等级,升级/改装武器享有25%的折扣,可以以原价购买传奇武器(仅限一把)",
902
- careerBonus: "武器中士/情报副官: 升级/改装武器享有50%的折扣,购买武器享有25%的折扣(非传奇),可以以80%的价格购买传奇武器(仅限一把)"
919
+ description: "提升空间站武器等级,升级武器享有25%的折扣,可以以原价购买传奇武器(仅限一把)",
920
+ careerBonus: "武器中士/情报副官: 升级武器享有50%的折扣,购买武器享有25%的折扣(非传奇),可以以80%的价格购买传奇武器(仅限一把)"
903
921
  }
904
922
  ]
905
923
  }
@@ -932,31 +950,25 @@ function apply(ctx, config) {
932
950
  return { totalModAdd, hasCrit };
933
951
  }
934
952
  __name(calculateModifiers, "calculateModifiers");
935
- async function calculateTagMultiplier(weaponData, bossName, equippedWeapon) {
936
- const bossRecord = await ctx.database.get("ggcevo_boss", { name: bossName });
937
- if (!bossRecord || !bossRecord.length) {
938
- throw new Error(`未找到BOSS记录: ${bossName}`);
939
- }
940
- const bossTags = Array.isArray(bossRecord[0].tags) ? bossRecord[0].tags : JSON.parse(bossRecord[0].tags || "[]");
953
+ async function calculateTagMultiplier(weaponData, tags, equippedWeapon) {
954
+ const MOD_EFFECTS = [
955
+ { mod: "裂甲核心", tag: "重甲", value: 1.2 },
956
+ { mod: "助燃核心", tag: "惧热", value: 4 }
957
+ ];
941
958
  let totalAdditive = 0;
942
- bossTags.forEach((tag) => {
943
- let effectValue;
944
- if (tag === "重甲" && equippedWeapon.installedMods.includes("裂甲核心")) {
945
- effectValue = 1.2;
946
- } else if (tag === "惧热" && equippedWeapon.installedMods.includes("助燃核心")) {
947
- effectValue = 4;
948
- } else {
949
- effectValue = weaponData.tagEffects?.[tag] ?? 1;
950
- }
959
+ for (const tag of tags) {
960
+ const activeMod = MOD_EFFECTS.find(
961
+ (me) => me.tag === tag && equippedWeapon.installedMods?.includes(me.mod)
962
+ );
963
+ const effectValue = activeMod ? activeMod.value : weaponData.tagEffects?.[tag] ?? 1;
951
964
  totalAdditive += effectValue - 1;
952
- });
965
+ }
953
966
  return totalAdditive;
954
967
  }
955
968
  __name(calculateTagMultiplier, "calculateTagMultiplier");
956
- function calculatePassiveEffects(targetBoss) {
969
+ function calculatePassiveEffects(passives) {
957
970
  let passiveEffect = 0;
958
- const effectivePassives = [...targetBoss.skills || []];
959
- effectivePassives.forEach((passive) => {
971
+ passives.forEach((passive) => {
960
972
  const effect = passiveConfig[passive]?.effect || 0;
961
973
  passiveEffect += effect;
962
974
  });
@@ -1003,8 +1015,10 @@ function apply(ctx, config) {
1003
1015
  return Math.floor(rankRecord.rank / 400) * 0.01;
1004
1016
  }
1005
1017
  __name(calculateRankBonus, "calculateRankBonus");
1006
- async function calculateTotalDamage(ctx2, session, equippedWeapon, targetBoss) {
1018
+ async function calculateTotalDamage(ctx2, session, equippedWeapon, targetBoss, options) {
1007
1019
  let effectMessage = [];
1020
+ const finalTags = options?.customTags || targetBoss.tags || [];
1021
+ const finalPassives = options?.customPassives || targetBoss.skills || [];
1008
1022
  const [profile] = await ctx2.database.get("sc2arcade_player", { userId: session.userId });
1009
1023
  const { regionId, realmId, profileId } = profile;
1010
1024
  const handle = `${regionId}-S2-${realmId}-${profileId}`;
@@ -1027,10 +1041,9 @@ function apply(ctx, config) {
1027
1041
  if (critRhythmEffect) {
1028
1042
  effectMessage.push("🎵 暴击韵律祈愿生效(暴击率+20%)");
1029
1043
  }
1030
- const targetBossConfig = targetBoss.name;
1031
- const tagMultiplier = await calculateTagMultiplier(weaponData, targetBossConfig, equippedWeapon);
1044
+ const tagMultiplier = await calculateTagMultiplier(weaponData, finalTags, equippedWeapon);
1032
1045
  damage *= 1 + tagMultiplier;
1033
- const passiveMultiplier = calculatePassiveEffects(targetBoss);
1046
+ const passiveMultiplier = calculatePassiveEffects(finalPassives);
1034
1047
  damage *= 1 + passiveMultiplier;
1035
1048
  const { damage: careerDamage, message: careerMessage } = await calculateCareerBonus(
1036
1049
  ctx2,
@@ -1797,6 +1810,13 @@ function apply(ctx, config) {
1797
1810
  success: totalDamage >= 300,
1798
1811
  message: `需要累计造成300伤害(当前${totalDamage})`
1799
1812
  };
1813
+ case "情报副官":
1814
+ const techs = await ctx2.database.get("ggcevo_tech", { handle });
1815
+ const hasValidTech = techs.some((t) => t.level >= 3);
1816
+ return {
1817
+ success: hasValidTech,
1818
+ message: hasValidTech ? "" : "需要至少一个科技等级≥3级"
1819
+ };
1800
1820
  case "能量武器专家":
1801
1821
  const hasEnergyWeapon = weapons.some((weapon) => {
1802
1822
  const weaponConfigEntry = Object.values(weaponConfig).find((c) => c.id === weapon.weaponId);
@@ -1835,12 +1855,20 @@ function apply(ctx, config) {
1835
1855
  }
1836
1856
  }
1837
1857
  __name(checkTransferRequirements, "checkTransferRequirements");
1838
- async function applyItemEffect(session, handle, itemConfig2) {
1839
- const itemName = Object.entries(SyndicatedItems).find(
1840
- ([_, item]) => item.id === itemConfig2.id
1841
- )?.[0] || "未知物品";
1858
+ async function applyItemEffect(session, handle, itemConfig2, target) {
1842
1859
  try {
1860
+ const itemName = Object.entries(SyndicatedItems).find(
1861
+ ([_, item]) => item.id === itemConfig2.id
1862
+ )?.[0] || "未知物品";
1843
1863
  if (itemConfig2.id === 1) {
1864
+ const activeSentry = await ctx.database.get("ggcevo_boss", {
1865
+ name: "空间站哨枪塔",
1866
+ isActive: true
1867
+ });
1868
+ if (!activeSentry.length) return {
1869
+ success: false,
1870
+ message: "⚠️ 目标「空间站哨枪塔」未激活"
1871
+ };
1844
1872
  const [SentryTower] = await ctx.database.get("ggcevo_boss", {
1845
1873
  name: "空间站哨枪塔",
1846
1874
  isActive: true
@@ -1849,39 +1877,188 @@ function apply(ctx, config) {
1849
1877
  await ctx.database.set(
1850
1878
  "ggcevo_boss",
1851
1879
  { name: "空间站哨枪塔" },
1852
- {
1853
- isActive: false,
1854
- HP: 0
1855
- }
1880
+ { isActive: false, HP: 0 }
1856
1881
  );
1857
1882
  await ctx.database.withTransaction(async () => {
1858
1883
  const signRecords = await ctx.database.get("ggcevo_sign", { handle });
1859
- const currentRewards = signRecords[0]?.totalRewards || 0;
1860
1884
  await ctx.database.upsert("ggcevo_sign", [{
1861
1885
  handle,
1862
- totalRewards: currentRewards + damageValue
1886
+ totalRewards: (signRecords[0]?.totalRewards || 0) + damageValue
1863
1887
  }], ["handle"]);
1864
1888
  const damageRecords = await ctx.database.get("ggcevo_boss_damage", { handle });
1865
- const currentDamage = damageRecords[0]?.totalDamage || 0;
1866
- const currentCount = damageRecords[0]?.attackCount || 0;
1867
1889
  await ctx.database.upsert("ggcevo_boss_damage", [{
1868
1890
  handle,
1869
1891
  playerName: session.username,
1870
- totalDamage: currentDamage + damageValue,
1871
- attackCount: currentCount,
1872
- // 保持原攻击次数
1892
+ totalDamage: (damageRecords[0]?.totalDamage || 0) + damageValue,
1893
+ attackCount: damageRecords[0]?.attackCount || 0,
1873
1894
  bossGroupId: 4
1874
1895
  }], ["handle"]);
1875
1896
  });
1876
- return `成功引爆${itemName},造成 ${damageValue} 点伤害,获得等额金币`;
1897
+ return {
1898
+ success: true,
1899
+ message: `成功引爆${itemName},造成 ${damageValue} 点伤害,获得等额金币`
1900
+ };
1901
+ }
1902
+ if (itemConfig2.id === 2) {
1903
+ if (!target) return {
1904
+ success: false,
1905
+ message: "该武器使用需要选择合适的目标。"
1906
+ };
1907
+ const targetboss = await ctx.database.get("ggcevo_boss", {
1908
+ name: target,
1909
+ isActive: true
1910
+ });
1911
+ if (!targetboss.length || targetboss[0].Skillcountpoints === 0) return {
1912
+ success: false,
1913
+ message: "您选择的不是合法目标(目标未存活/目标无技能计数)。"
1914
+ };
1915
+ await ctx.database.set(
1916
+ "ggcevo_boss",
1917
+ { name: target },
1918
+ { Skillcountpoints: 0 }
1919
+ );
1920
+ return {
1921
+ success: true,
1922
+ message: `成功使用${itemName},您的目标${target}已重置其技能计数`
1923
+ };
1877
1924
  }
1878
- return `${itemName} 效果已生效(开发中)`;
1925
+ return {
1926
+ success: true,
1927
+ message: `${itemName} 效果已生效(开发中)`
1928
+ };
1879
1929
  } catch (error) {
1880
1930
  console.error("物品效果处理失败:", error);
1881
- return "⚠️ 物品效果处理异常,已回滚操作";
1931
+ return {
1932
+ success: false,
1933
+ message: "⚠️ 物品效果处理异常,已回滚操作"
1934
+ };
1882
1935
  }
1883
1936
  }
1884
1937
  __name(applyItemEffect, "applyItemEffect");
1938
+ async function handleTechUpgrade(handle, target) {
1939
+ const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
1940
+ if (!careerData || careerData.group !== "人类联盟") {
1941
+ return "🚫 该功能需要【人类联盟】阵营权限";
1942
+ }
1943
+ const tech = Spacestationtechnology.find(
1944
+ (t) => t.techname === target || t.techId == target
1945
+ );
1946
+ const [techEntry] = await ctx.database.get("ggcevo_tech", { handle, techId: tech.techId });
1947
+ const currentLevel = techEntry?.level || 0;
1948
+ if (currentLevel >= tech.maxLevel) return `❌ ${tech.techname}已达最高等级`;
1949
+ const nextLevel = currentLevel + 1;
1950
+ const levelData = tech.levels.find((l) => l.level === nextLevel);
1951
+ let actualCost = levelData.cost;
1952
+ if (careerData.career === "情报副官") {
1953
+ actualCost = Math.floor(actualCost * 0.8);
1954
+ }
1955
+ const [signInfo] = await ctx.database.get("ggcevo_sign", { handle });
1956
+ if (signInfo?.totalRewards < actualCost) {
1957
+ const originalHint = careerData.career === "情报副官" ? `(原价${levelData.cost})` : "";
1958
+ return `❌ 需要 ${actualCost} 金币${originalHint},当前持有:${signInfo?.totalRewards || 0}`;
1959
+ }
1960
+ await ctx.database.withTransaction(async () => {
1961
+ await ctx.database.set("ggcevo_sign", { handle }, {
1962
+ totalRewards: signInfo.totalRewards - actualCost
1963
+ });
1964
+ await ctx.database.upsert("ggcevo_tech", [{
1965
+ handle,
1966
+ techId: tech.techId,
1967
+ level: nextLevel
1968
+ }], ["handle", "techId"]);
1969
+ });
1970
+ const costHint = careerData.career === "情报副官" ? `${actualCost}(情报副官:已享8折优惠)` : actualCost;
1971
+ return `✅ ${tech.techname} 升级至 Lv.${nextLevel}
1972
+ 💰 花费金币: ${costHint}
1973
+ 📝 ${levelData.description}
1974
+ 💼 ${levelData.careerBonus}`;
1975
+ }
1976
+ __name(handleTechUpgrade, "handleTechUpgrade");
1977
+ async function handleWeaponUpgrade(handle, target) {
1978
+ const weaponData = weaponConfig[target];
1979
+ const [equipment] = await ctx.database.get("ggcevo_equipment", {
1980
+ handle,
1981
+ weaponId: weaponData.id
1982
+ });
1983
+ if (!equipment) return "❌ 尚未获得该武器";
1984
+ if (equipment.level >= 6) return "❌ 武器已达最高等级";
1985
+ const BASE_COST = [1050, 1450, 1850, 2250, 2650, 3050];
1986
+ const baseCost = BASE_COST[equipment.level];
1987
+ const weaponTechConfig = Spacestationtechnology.find((t) => t.techId === 2);
1988
+ const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
1989
+ const [weaponTech] = await ctx.database.get("ggcevo_tech", { handle, techId: 2 }).catch(() => [{ level: 0 }]);
1990
+ const techLevel = Math.min(Math.max(weaponTech?.level || 0, 0), 5);
1991
+ const isCareerMatch = weaponTechConfig?.careerNames.includes(careerData?.career);
1992
+ const BASE_DISCOUNTS = [5, 10, 15, 20, 25];
1993
+ const CAREER_DISCOUNTS = [10, 20, 30, 40, 50];
1994
+ const baseDiscount = techLevel > 0 ? BASE_DISCOUNTS[techLevel - 1] : 0;
1995
+ const careerDiscount = isCareerMatch && techLevel > 0 ? CAREER_DISCOUNTS[techLevel - 1] : 0;
1996
+ const weaponDiscount = Math.max(baseDiscount, careerDiscount) / 100;
1997
+ let discountedCost = baseCost * (1 - weaponDiscount);
1998
+ const activeWish = await checkFoxBlessing(handle);
1999
+ if (activeWish) {
2000
+ discountedCost *= 0.8;
2001
+ }
2002
+ const actualCost = Math.floor(discountedCost);
2003
+ const [signInfo] = await ctx.database.get("ggcevo_sign", { handle });
2004
+ if (signInfo?.totalRewards < actualCost) {
2005
+ return `❌ 需要 ${actualCost} 金币,当前持有:${signInfo?.totalRewards || 0}`;
2006
+ }
2007
+ await ctx.database.withTransaction(async () => {
2008
+ await ctx.database.set("ggcevo_sign", { handle }, {
2009
+ totalRewards: signInfo.totalRewards - actualCost
2010
+ });
2011
+ await ctx.database.set(
2012
+ "ggcevo_equipment",
2013
+ { handle, weaponId: weaponData.id },
2014
+ {
2015
+ level: equipment.level + 1,
2016
+ modificationSlots: Math.floor((equipment.level + 1) / 3) + 1
2017
+ }
2018
+ );
2019
+ if (activeWish) {
2020
+ await ctx.database.set(
2021
+ "ggcevo_Wish_Record",
2022
+ { id: activeWish.id },
2023
+ { isused: true }
2024
+ );
2025
+ }
2026
+ });
2027
+ const newLevel = equipment.level + 1;
2028
+ const damage = (weaponData.damage * (1 + 0.1 * newLevel)).toFixed(1);
2029
+ let msg = `${target} 升级成功!Lv.${newLevel}`;
2030
+ const priceInfo = actualCost === baseCost ? `
2031
+ 💸 消耗:${actualCost}金币` : `
2032
+ 💸 消耗:${actualCost}金币 (原价${baseCost})`;
2033
+ msg += priceInfo;
2034
+ let discountDetails = [];
2035
+ if (weaponDiscount > 0) {
2036
+ discountDetails.push(`武器系统 Lv${techLevel} 折扣:${Math.max(baseDiscount, careerDiscount)}%`);
2037
+ }
2038
+ if (activeWish) {
2039
+ discountDetails.push("灵狐升运折扣:20%");
2040
+ }
2041
+ if (discountDetails.length > 0) {
2042
+ msg += `
2043
+ 🔧 已应用折扣:${discountDetails.join(" + ")}`;
2044
+ }
2045
+ msg += `
2046
+ 💥 伤害:${damage}`;
2047
+ msg += `
2048
+ 🔩 改装槽:${Math.floor(newLevel / 3) + 1}个`;
2049
+ return msg;
2050
+ }
2051
+ __name(handleWeaponUpgrade, "handleWeaponUpgrade");
2052
+ async function checkFoxBlessing(handle) {
2053
+ return ctx.database.get("ggcevo_Wish_Record", {
2054
+ handle,
2055
+ wishname: "灵狐升运",
2056
+ startTime: { $lte: /* @__PURE__ */ new Date() },
2057
+ endTime: { $gte: /* @__PURE__ */ new Date() },
2058
+ isused: false
2059
+ }).then((records) => records[0]);
2060
+ }
2061
+ __name(checkFoxBlessing, "checkFoxBlessing");
1885
2062
  ctx.command("ggcevo/抽奖").action(async (argv) => {
1886
2063
  const session = argv.session;
1887
2064
  let winCount = 0;
@@ -2109,17 +2286,41 @@ ${itemDetails.join("\n")}`;
2109
2286
  }
2110
2287
  let redCrystal = 0;
2111
2288
  let careerCrystalMessage = "";
2112
- if (meowEffect) {
2113
- tickets *= 2;
2114
- points *= 2;
2115
- effectMessage = "\n🐾 喵喵财源祈愿生效,获得双倍奖励!";
2116
- }
2117
- let careerMessage = "";
2118
2289
  const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
2290
+ let miningBonus = 0;
2291
+ let miningMessage = "";
2292
+ const BASE_BONUS = [5, 10, 15, 20, 25];
2293
+ const CAREER_BONUS = [10, 20, 30, 40, 50];
2294
+ const miningTechConfig = Spacestationtechnology.find((t) => t.techId === 1);
2295
+ if (miningTechConfig) {
2296
+ const [userMiningTech] = await ctx.database.get("ggcevo_tech", {
2297
+ handle,
2298
+ techId: 1
2299
+ }).catch(() => [{ level: 0 }]);
2300
+ const techLevel = Math.min(Math.max(userMiningTech?.level || 0, 0), 5);
2301
+ const baseBonus = techLevel > 0 ? BASE_BONUS[techLevel - 1] : 0;
2302
+ let careerTechBonus = 0;
2303
+ if (careerData?.career && miningTechConfig.careerNames.includes(careerData.career)) {
2304
+ careerTechBonus = techLevel > 0 ? CAREER_BONUS[techLevel - 1] : 0;
2305
+ }
2306
+ miningBonus = Math.max(baseBonus, careerTechBonus);
2307
+ if (miningBonus > 0) {
2308
+ miningMessage = `
2309
+ ⚙️ 采掘系统 Lv${techLevel} 金币加成:+${miningBonus}%`;
2310
+ }
2311
+ }
2312
+ let minerBonus = 0;
2313
+ let minerMessage = "";
2119
2314
  if (careerData?.career === "深空矿工") {
2120
- points = Math.round(points * 1.5);
2121
- careerMessage = "\n⛏️ 深空矿工职业加成:额外获得50%金币!";
2315
+ minerBonus = 50;
2316
+ minerMessage = `
2317
+ ⛏️ 深空矿工职业加成:金币+50%`;
2318
+ }
2319
+ const totalBonus = miningBonus + minerBonus;
2320
+ if (totalBonus > 0) {
2321
+ points = Math.round(points * (1 + totalBonus / 100));
2122
2322
  }
2323
+ const bonusMessage = miningMessage + minerMessage;
2123
2324
  if (careerData?.group === "辛迪加海盗" && careerData.career === "辛迪加财务经理") {
2124
2325
  if (monthlyDays < 7) {
2125
2326
  redCrystal = 1;
@@ -2135,6 +2336,11 @@ ${itemDetails.join("\n")}`;
2135
2336
  careerCrystalMessage = `
2136
2337
  ⚓ 辛迪加财务经理职业加成:获得 ${redCrystal} 红晶`;
2137
2338
  }
2339
+ if (meowEffect) {
2340
+ tickets *= 2;
2341
+ points *= 2;
2342
+ effectMessage = "\n🐾 喵喵财源祈愿生效,获得双倍奖励(金币和咕咕币)!";
2343
+ }
2138
2344
  await ctx.database.withTransaction(async () => {
2139
2345
  await ctx.database.upsert("ggcevo_sign", [{
2140
2346
  handle,
@@ -2156,7 +2362,7 @@ ${itemDetails.join("\n")}`;
2156
2362
  });
2157
2363
  return `签到成功!本月累计签到${monthlyDays}天,获得:
2158
2364
  💰 金币 x ${points}
2159
- 🪙 咕咕币 x ${tickets}` + effectMessage + careerMessage + careerCrystalMessage;
2365
+ 🪙 咕咕币 x ${tickets}` + (effectMessage || "") + bonusMessage + (careerCrystalMessage || "");
2160
2366
  } catch (error) {
2161
2367
  console.error("签到命令时发生错误:", error);
2162
2368
  return "服务器繁忙,请稍后尝试。";
@@ -3542,7 +3748,9 @@ ${achievementList.join("\n")}`;
3542
3748
  day: "2-digit"
3543
3749
  })}`;
3544
3750
  });
3545
- ctx.command("ggcevo/武器库 [type]").usage("输入“武器库”查看类型,或“武器库 类型”查看详细武器信息").action(async (_, type) => {
3751
+ ctx.command("ggcevo/武器库 [type]").usage("输入“武器库”查看类型,或“武器库 类型”查看详细武器信息").action(async ({ session }, type) => {
3752
+ const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
3753
+ if (!profile) return "⚠️ 需要先绑定游戏句柄";
3546
3754
  const typeStats = Object.values(weaponConfig).filter((weapon) => weapon.price !== 0).reduce((stats, weapon) => {
3547
3755
  stats[weapon.type] = (stats[weapon.type] || 0) + 1;
3548
3756
  return stats;
@@ -3561,7 +3769,7 @@ ${achievementList.join("\n")}`;
3561
3769
  return `无效武器类型,可用类型:
3562
3770
  ${validTypes.join("、")}`;
3563
3771
  }
3564
- const items = Object.entries(weaponConfig).filter(([_2, config2]) => config2.type === type && config2.price !== 0).map(([name2, config2]) => {
3772
+ const items = Object.entries(weaponConfig).filter(([_, config2]) => config2.type === type && config2.price !== 0).map(([name2, config2]) => {
3565
3773
  const tagEffectsDesc = config2.tagEffects ? Object.entries(config2.tagEffects).map(([tag, multiplier]) => `▸ 对${tag}目标造成${(multiplier * 100).toFixed(0)}%伤害`).join("\n") : "▸ 无特殊加成效果";
3566
3774
  return [
3567
3775
  `【${name2}】`,
@@ -3581,46 +3789,115 @@ ${validTypes.join("、")}`;
3581
3789
  items.length === 0 ? "⚠️ 该分类下暂无可用武器" : ""
3582
3790
  ].join("\n\n");
3583
3791
  });
3584
- ctx.command("ggcevo/购买 <weapon>").action(async ({ session }, weapon) => {
3792
+ ctx.command("ggcevo/爆破库 [type]").usage("输入“爆破库”查看分类,或“爆破库 类型”查看详细物品").action(async ({ session }, type) => {
3793
+ const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
3794
+ if (!profile) return "⚠️ 需要先绑定游戏句柄";
3795
+ const filteredItems = Object.values(SyndicatedItems).filter(
3796
+ (item) => item.price > 0 && ["爆破物", "手榴弹"].includes(item.type)
3797
+ );
3798
+ const typeStats = filteredItems.reduce((stats, item) => {
3799
+ stats[item.type] = (stats[item.type] || 0) + 1;
3800
+ return stats;
3801
+ }, {});
3802
+ if (!type) {
3803
+ return [
3804
+ "💣 爆破装备库分类 💣",
3805
+ '使用 "爆破库 类型名称" 查看详细列表',
3806
+ "====================",
3807
+ ...Object.entries(typeStats).map(([typeName, count]) => `▸ ${typeName} (${count}种)`),
3808
+ "===================="
3809
+ ].join("\n");
3810
+ }
3811
+ const validTypes = Object.keys(typeStats);
3812
+ if (!validTypes.includes(type)) {
3813
+ return `无效分类,可用类型:
3814
+ ${validTypes.join("、")}`;
3815
+ }
3816
+ const items = filteredItems.filter((item) => item.type === type).map((item) => [
3817
+ `${Object.keys(SyndicatedItems).find((k) => SyndicatedItems[k] === item)}`,
3818
+ // 获取物品名称
3819
+ `类型:${item.type}`,
3820
+ `价格:${item.price}金币`,
3821
+ `效果:${item.effects}`,
3822
+ `描述:${item.description}`
3823
+ ].join("\n"));
3824
+ return [
3825
+ `💣 爆破装备库 - ${type} 💣`,
3826
+ "使用“购买 物品名称”命令进行购买",
3827
+ "====================",
3828
+ ...items,
3829
+ items.length === 0 ? "⚠️ 该分类下暂无可用物品" : ""
3830
+ ].join("\n\n");
3831
+ });
3832
+ ctx.command("ggcevo/购买 <item>").action(async ({ session }, item) => {
3585
3833
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
3586
3834
  if (!profile) return "您暂未绑定句柄。";
3587
3835
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
3588
3836
  const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
3589
- if (existingEntries.length > 0) {
3590
- return `❌ 拒绝访问,您已被列入黑名单。`;
3837
+ if (existingEntries.length > 0) return "❌ 拒绝访问,您已被列入黑名单。";
3838
+ const allItems = { ...weaponConfig, ...SyndicatedItems };
3839
+ if (!item) return "请输入“购买 物品名称”来购买所需物品。";
3840
+ const config2 = allItems[item];
3841
+ if (!config2) return "无效的物品名称,请重新输入。";
3842
+ if (config2.price <= 0) return "❌ 该物品不可直接购买";
3843
+ const isWeapon = ["能量武器", "热能武器", "实弹武器"].includes(config2.type);
3844
+ if (isWeapon) {
3845
+ const existingWeapon = await ctx.database.get("ggcevo_equipment", {
3846
+ handle,
3847
+ weaponId: config2.id
3848
+ });
3849
+ if (existingWeapon.length > 0) return `❌ 您已经拥有${item},无法重复购买`;
3591
3850
  }
3592
3851
  const [signInfo] = await ctx.database.get("ggcevo_sign", { handle });
3593
- if (!weapon) return "请输入“购买 物品名称”来购买所需物品。";
3594
- if (!weaponConfig[weapon]) return "无效的武器名称,请重新输入。";
3595
- const config2 = weaponConfig[weapon];
3596
- const allowedTypes = ["能量武器", "热能武器", "实弹武器"];
3597
- if (!allowedTypes.includes(config2.type)) {
3598
- return `❌ 无法购买该类型武器,仅支持:${allowedTypes.join("、")}`;
3599
- }
3600
- const existingWeapons = await ctx.database.get("ggcevo_equipment", {
3601
- handle,
3602
- weaponId: config2.id
3603
- });
3604
- if (existingWeapons.length > 0) {
3605
- return `你已经拥有${weapon},无法重复购买。`;
3852
+ const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
3853
+ const [weaponTech] = await ctx.database.get("ggcevo_tech", { handle, techId: 2 });
3854
+ let discountDetails = [];
3855
+ let totalDiscount = 0;
3856
+ if (isWeapon) {
3857
+ const techDiscountTable = {
3858
+ 2: [0, 10],
3859
+ 3: [0, 15],
3860
+ 4: [0, 20],
3861
+ 5: [0, 25]
3862
+ };
3863
+ const techLevel = weaponTech?.level || 0;
3864
+ if (techLevel >= 2) {
3865
+ const [baseDisc, careerDisc] = techDiscountTable[Math.min(techLevel, 5)] || [0, 0];
3866
+ const isQualifiedCareer = careerData?.career && Spacestationtechnology.find((t) => t.techId === 2)?.careerNames.includes(careerData.career);
3867
+ const techDiscount = isQualifiedCareer ? Math.max(baseDisc, careerDisc) : baseDisc;
3868
+ if (techDiscount > 0) {
3869
+ totalDiscount += techDiscount;
3870
+ discountDetails.push(
3871
+ `武器系统 Lv${techLevel}${isQualifiedCareer ? "(职业加成)" : ""} ${techDiscount}%折扣`
3872
+ );
3873
+ }
3874
+ }
3606
3875
  }
3607
- const activeWish = await ctx.database.get("ggcevo_Wish_Record", {
3876
+ const activeWish = isWeapon ? await ctx.database.get("ggcevo_Wish_Record", {
3608
3877
  handle,
3609
3878
  wishname: "蚱蜢优购",
3610
3879
  startTime: { $lte: /* @__PURE__ */ new Date() },
3611
3880
  endTime: { $gte: /* @__PURE__ */ new Date() },
3612
3881
  isused: false
3613
- }).then((records) => records[0]);
3614
- let actualPrice = config2.price;
3615
- let discountMessage = "";
3616
- let equippedCount;
3882
+ }).then((records) => records[0]) : null;
3617
3883
  if (activeWish) {
3618
- actualPrice = Math.floor(config2.price * 0.8);
3619
- discountMessage = ` (祈愿优惠价,原价${config2.price})`;
3884
+ const wishDiscount = 20;
3885
+ totalDiscount = 100 - (100 - totalDiscount) * (100 - wishDiscount) / 100;
3886
+ discountDetails.push(`蚱蜢优购祈愿生效 ${wishDiscount}%折扣`);
3887
+ }
3888
+ let actualPrice = config2.price;
3889
+ if (totalDiscount > 0) {
3890
+ actualPrice = Math.floor(config2.price * (100 - totalDiscount) / 100);
3891
+ actualPrice = Math.max(actualPrice, 1);
3620
3892
  }
3621
3893
  if ((signInfo?.totalRewards || 0) < actualPrice) {
3622
- return `金币不足,需要${actualPrice}枚金币${discountMessage}`;
3894
+ let priceInfo = `需要 ${actualPrice} 金币`;
3895
+ if (discountDetails.length > 0) {
3896
+ priceInfo += `(原价 ${config2.price},累计折扣 ${totalDiscount}%)`;
3897
+ }
3898
+ return `❌ 金币不足,${priceInfo}`;
3623
3899
  }
3900
+ let isAutoEquipped = false;
3624
3901
  await ctx.database.withTransaction(async () => {
3625
3902
  await ctx.database.set("ggcevo_sign", { handle }, {
3626
3903
  totalRewards: signInfo.totalRewards - actualPrice
@@ -3630,32 +3907,55 @@ ${validTypes.join("、")}`;
3630
3907
  isused: true
3631
3908
  });
3632
3909
  }
3633
- await ctx.database.upsert("ggcevo_equipment", [{
3634
- handle,
3635
- weaponId: config2.id,
3636
- level: 0,
3637
- modificationSlots: 1,
3638
- equipped: false
3639
- }], ["handle", "weaponId"]);
3640
- equippedCount = await ctx.database.select("ggcevo_equipment").where({ handle, equipped: true }).execute((row) => import_koishi.$.count(row.weaponId));
3641
- if (equippedCount === 0) {
3642
- await ctx.database.set(
3643
- "ggcevo_equipment",
3644
- { handle, weaponId: config2.id },
3645
- { equipped: true }
3646
- );
3910
+ if (isWeapon) {
3911
+ await ctx.database.upsert("ggcevo_equipment", [{
3912
+ handle,
3913
+ weaponId: config2.id,
3914
+ level: 0,
3915
+ modificationSlots: 1,
3916
+ equipped: false
3917
+ }], ["handle", "weaponId"]);
3918
+ const equippedCount = await ctx.database.select("ggcevo_equipment").where({ handle, equipped: true }).execute((row) => import_koishi.$.count(row.weaponId));
3919
+ if (equippedCount === 0) {
3920
+ await ctx.database.set(
3921
+ "ggcevo_equipment",
3922
+ { handle, weaponId: config2.id },
3923
+ { equipped: true }
3924
+ );
3925
+ isAutoEquipped = true;
3926
+ }
3927
+ } else {
3928
+ const [existing] = await ctx.database.get("ggcevo_warehouse", {
3929
+ handle,
3930
+ itemId: config2.id
3931
+ });
3932
+ await ctx.database.upsert("ggcevo_warehouse", [{
3933
+ handle,
3934
+ itemId: config2.id,
3935
+ quantity: (existing?.quantity || 0) + 1
3936
+ }], ["handle", "itemId"]);
3647
3937
  }
3648
3938
  });
3649
- let message = `成功购买 ${weapon}!花费 ${actualPrice}枚金币${discountMessage}。`;
3650
- if (activeWish) {
3651
- message += `
3652
- 🦗 蚱蜢优购祈愿已使用,下次购买将恢复原价。`;
3939
+ let message = `✅ 成功获取 ${isWeapon ? "武器" : "物品"}「${item}
3940
+ `;
3941
+ message += `花费 ${actualPrice} 金币`;
3942
+ if (discountDetails.length > 0) {
3943
+ message += `(原价 ${config2.price} 金币)
3944
+ 折扣明细:
3945
+ ▸ ${discountDetails.join("\n▸ ")}`;
3653
3946
  }
3654
- if (equippedCount === 0) {
3947
+ if (isWeapon) {
3948
+ if (isAutoEquipped) {
3949
+ message += "\n\n【系统已自动装备该武器】";
3950
+ }
3951
+ message += "\n输入「武器仓库」查看详情";
3952
+ } else {
3953
+ const [current] = await ctx.database.get("ggcevo_warehouse", { handle, itemId: config2.id });
3655
3954
  message += `
3656
- 已自动为您装备当前武器!`;
3955
+
3956
+ 当前持有数量:${current?.quantity || 1},输入「仓库」查看物品`;
3657
3957
  }
3658
- return message + "\n输入“武器仓库”查看你拥有的武器。";
3958
+ return message;
3659
3959
  });
3660
3960
  ctx.command("ggcevo/武器仓库").action(async ({ session }) => {
3661
3961
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
@@ -3723,65 +4023,24 @@ ${validTypes.join("、")}`;
3723
4023
  });
3724
4024
  return `您已成功装备武器 ${weapon}!`;
3725
4025
  });
3726
- ctx.command("ggcevo/升级 <weapon>", "升级武器伤害").action(async ({ session }, weapon) => {
4026
+ ctx.command("ggcevo/升级 <target>", "升级武器或科技").action(async ({ session }, target) => {
3727
4027
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
3728
- if (!profile) return "您暂未绑定句柄。";
4028
+ if (!profile) return "❌ 您暂未绑定句柄";
3729
4029
  const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
3730
- const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
3731
- if (existingEntries.length > 0) {
3732
- return `❌ 拒绝访问,您已被列入黑名单。`;
3733
- }
3734
- const [signInfo] = await ctx.database.get("ggcevo_sign", { handle });
3735
- const [equipment] = await ctx.database.get("ggcevo_equipment", {
3736
- handle,
3737
- weaponId: weaponConfig[weapon]?.id
3738
- });
3739
- if (!weapon) return "请输入“升级 武器名称”来升级你想要的武器。";
3740
- if (!equipment) return "尚未获得该武器。";
3741
- if (equipment.level >= 6) return "该武器已达最大升级等级。";
3742
- const activeWish = await ctx.database.get("ggcevo_Wish_Record", {
3743
- handle,
3744
- wishname: "灵狐升运",
3745
- startTime: { $lte: /* @__PURE__ */ new Date() },
3746
- endTime: { $gte: /* @__PURE__ */ new Date() },
3747
- isused: false
3748
- }).then((records) => records[0]);
3749
- let baseCost = [1050, 1450, 1850, 2250, 2650, 3050][equipment.level];
3750
- let actualCost = baseCost;
3751
- let discountMessage = "";
3752
- if (activeWish) {
3753
- actualCost = Math.floor(baseCost * 0.8);
3754
- discountMessage = ` (祈愿优惠价,原价${baseCost})`;
4030
+ if ((await ctx.database.get("ggcevo_blacklist", { handle })).length) {
4031
+ return "❌ 拒绝访问,您已被列入黑名单";
3755
4032
  }
3756
- if ((signInfo?.totalRewards || 0) < actualCost)
3757
- return `需要${actualCost}枚金币${discountMessage},当前持有:${signInfo?.totalRewards || 0}。`;
3758
- await ctx.database.withTransaction(async () => {
3759
- await ctx.database.set("ggcevo_sign", { handle }, {
3760
- totalRewards: signInfo.totalRewards - actualCost
3761
- });
3762
- await ctx.database.set("ggcevo_equipment", {
3763
- handle,
3764
- weaponId: weaponConfig[weapon].id
3765
- }, {
3766
- level: equipment.level + 1,
3767
- modificationSlots: Math.floor((equipment.level + 1) / 3) + 1
3768
- });
3769
- if (activeWish) {
3770
- await ctx.database.set("ggcevo_Wish_Record", { id: activeWish.id }, {
3771
- isused: true
3772
- });
3773
- }
3774
- });
3775
- const newLevel = equipment.level + 1;
3776
- const baseDamage = (weaponConfig[weapon].damage * (1 + 0.1 * newLevel)).toFixed(1);
3777
- const slots = Math.floor(newLevel / 3) + 1;
3778
- let message = `${weapon} 升级成功!花费${actualCost}枚金币${discountMessage}。`;
3779
- if (activeWish) {
3780
- message += `
3781
- 🦊 灵狐升运祈愿已使用,下次升级将恢复原价。`;
4033
+ if (!target) return "⚠️ 请输入要升级的武器或科技名称(升级科技需要加入人类联盟阵营)";
4034
+ const isTech = Spacestationtechnology.some(
4035
+ (t) => t.techname === target || t.techname == target
4036
+ );
4037
+ const isWeapon = Object.keys(weaponConfig).includes(target);
4038
+ if (isTech) {
4039
+ return handleTechUpgrade(handle, target);
4040
+ } else if (isWeapon) {
4041
+ return handleWeaponUpgrade(handle, target);
3782
4042
  }
3783
- return `${message}
3784
- 当前等级:${newLevel},伤害:${baseDamage},拥有改装槽:${slots}个。`;
4043
+ return `❌ 未找到 "${target}" 对应的武器或科技`;
3785
4044
  });
3786
4045
  ctx.command("ggcevo/改装 <weapon> [mod]", "安装武器模块").action(async ({ session }, weapon, mod) => {
3787
4046
  const isValidWeapon = weapon && weaponConfig[weapon]?.id !== void 0;
@@ -4057,7 +4316,7 @@ ${effectMessage.join("\n")}`
4057
4316
  // 修改金币显示行
4058
4317
  `获得金币:${finalReward}${careerMessage}`,
4059
4318
  `目标剩余HP:${Math.max(currentHP, 0)}/${maxHP}`,
4060
- isDefeated ? `🎉 恭喜,您成功击败 ${targetBoss.name}!` : ""
4319
+ isDefeated ? `🎉 恭喜,已成功击败 ${targetBoss.name}!` : ""
4061
4320
  ].filter((line) => line).join("\n");
4062
4321
  await session.send(resultMessage);
4063
4322
  if (broadcastMessage) {
@@ -4066,6 +4325,57 @@ ${effectMessage.join("\n")}`
4066
4325
  await ctx.broadcast(groupId, finalBroadcast);
4067
4326
  }
4068
4327
  });
4328
+ ctx.command("ggcevo/攻击假人").usage("测试当前装备武器的伤害,可添加标签和被动\n用法:攻击假人 [--标签 标签1 标签2] [--被动 被动1 被动2]").option("tags", "-t <tags:string> 添加BOSS标签(逗号分隔)").option("passives", "-p <passives:string> 添加BOSS被动(逗号分隔)").action(async (argv) => {
4329
+ const session = argv.session;
4330
+ const { options } = argv;
4331
+ const parseList = /* @__PURE__ */ __name((str) => str ? str.split(",").map((s) => s.trim()).filter(Boolean) : [], "parseList");
4332
+ const tags = parseList(options.tags);
4333
+ const passives = parseList(options.passives);
4334
+ const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
4335
+ if (!profile) return "您暂未绑定句柄。";
4336
+ const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
4337
+ const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
4338
+ if (existingEntries.length > 0) return "❌ 拒绝访问,您已被列入黑名单。";
4339
+ const [equippedWeapon] = await ctx.database.get("ggcevo_equipment", {
4340
+ handle,
4341
+ equipped: true
4342
+ });
4343
+ if (!equippedWeapon) return '请先输入"装备 武器名称"后再测试。';
4344
+ const dummyBoss = {
4345
+ name: "测试假人",
4346
+ HP: Infinity,
4347
+ type: "主宰",
4348
+ groupId: 0,
4349
+ skills: passives || [],
4350
+ // 从选项获取被动
4351
+ tags: tags || []
4352
+ // 从选项获取标签
4353
+ };
4354
+ const { damage, hasCrit, effectMessage } = await calculateTotalDamage(
4355
+ ctx,
4356
+ session,
4357
+ equippedWeapon,
4358
+ dummyBoss,
4359
+ {
4360
+ isTest: true,
4361
+ // 标记为测试模式
4362
+ customTags: tags,
4363
+ customPassives: passives
4364
+ }
4365
+ );
4366
+ const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
4367
+ const [weaponName] = weaponConfigEntry;
4368
+ return [
4369
+ `🎯 测试攻击 ${dummyBoss.name}`,
4370
+ `💥 使用武器:${weaponName}`,
4371
+ options.tags?.length && `🏷️ 模拟标签:${tags.join(", ")}`,
4372
+ options.passives?.length && `🛡️ 模拟被动:${passives.join(", ")}`,
4373
+ `📊 理论伤害值:${damage}`,
4374
+ hasCrit ? "✨ 触发暴击" : "",
4375
+ ...effectMessage,
4376
+ "⚠️ 注意:假人默认无属性,标签和被动需手动添加"
4377
+ ].filter((line) => line).join("\n");
4378
+ });
4069
4379
  ctx.command("ggcevo/伤害榜 [page]", "查看当前主宰伤害排名").usage("输入 伤害榜 [页码] 查看对应页的排行榜,每页10条").action(async (_, page) => {
4070
4380
  const pageNum = parseInt(page) || 1;
4071
4381
  if (pageNum < 1) return "请输入有效的页码。";
@@ -4151,7 +4461,7 @@ ${effectMessage.join("\n")}`
4151
4461
  name: minion.name,
4152
4462
  type: "子代",
4153
4463
  HP: minion.maxHP,
4154
- tags: bossConfig.main.tags,
4464
+ tags: minion.tags,
4155
4465
  skills: [...minion.passive],
4156
4466
  groupId: groupid,
4157
4467
  isActive: true,
@@ -4488,16 +4798,22 @@ ${effectMessage.join("\n")}`
4488
4798
  `✨ 职业效果:${effectDisplay}`,
4489
4799
  `🗓️ 就职时间:${formattedDate}`
4490
4800
  ];
4491
- if (careerData.group === "辛迪加海盗") {
4492
- infoCard.push(`🔴 持有红晶:${careerData.redcrystal || 0} 个`);
4493
- infoCard.push("💡 提示:红晶可通过主动PK获得(无论胜负)");
4494
- } else {
4495
- infoCard.push("💡 提示:使用「转职」命令可变更职业");
4801
+ if (careerData.group === "人类联盟") {
4802
+ const techEntries = await ctx.database.get("ggcevo_tech", { handle });
4803
+ const activeTechs = techEntries.filter((entry) => entry.level > 0).map((entry) => {
4804
+ const techConfig = Spacestationtechnology.find((t) => t.techId === entry.techId);
4805
+ return techConfig ? `🛠️ ${techConfig.techname} [${entry.level}/${techConfig.maxLevel}]` : null;
4806
+ }).filter(Boolean);
4807
+ if (activeTechs.length > 0) {
4808
+ infoCard.push("", "〓 科技研发 〓", ...activeTechs);
4809
+ }
4496
4810
  }
4811
+ const promptMessage = careerData.group === "辛迪加海盗" ? "💡 提示:红晶可通过主动PK获得(无论胜负)" : "💡 提示:使用「转职」命令可变更职业";
4497
4812
  return [
4498
4813
  "〓 职业档案 〓",
4499
4814
  ...infoCard,
4500
- "〓═════════〓"
4815
+ "〓═════════〓\n" + promptMessage
4816
+ // 提示信息放在分隔线下方
4501
4817
  ].join("\n");
4502
4818
  } catch (error) {
4503
4819
  ctx.logger.error("查询职业信息失败:", error);
@@ -4505,11 +4821,18 @@ ${effectMessage.join("\n")}`
4505
4821
  }
4506
4822
  });
4507
4823
  ctx.command("ggcevo/黑市 [type]", "辛迪加海盗专属黑市").usage("输入“黑市”查看类型,或“黑市 类型”查看详细").action(async ({ session }, type) => {
4824
+ const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
4825
+ if (!profile) return "⚠️ 需要先绑定游戏句柄";
4826
+ const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
4827
+ const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
4828
+ if (!careerData || careerData.group !== "辛迪加海盗") {
4829
+ return "🚫 该功能需要【辛迪加海盗】阵营权限";
4830
+ }
4508
4831
  const typeStats = {};
4509
- Object.values(weaponConfig).forEach((weapon) => {
4832
+ Object.values(weaponConfig).filter((config2) => config2.redCrystalCost > 0).forEach((weapon) => {
4510
4833
  typeStats[weapon.type] = (typeStats[weapon.type] || 0) + 1;
4511
4834
  });
4512
- Object.values(SyndicatedItems).forEach((item) => {
4835
+ Object.values(SyndicatedItems).filter((item) => item.redCrystalCost > 0).forEach((item) => {
4513
4836
  typeStats[item.type] = (typeStats[item.type] || 0) + 1;
4514
4837
  });
4515
4838
  if (!type) {
@@ -4524,12 +4847,15 @@ ${effectMessage.join("\n")}`
4524
4847
  const normalizedType = Object.keys(typeStats).find((t) => t === type);
4525
4848
  if (!normalizedType) return `无效类型,可用:${Object.keys(typeStats).join("、")}`;
4526
4849
  const items = [
4527
- ...Object.entries(weaponConfig).filter(([_, config2]) => config2.type === normalizedType).map(([name2, config2]) => {
4850
+ ...Object.entries(weaponConfig).filter(
4851
+ ([_, config2]) => config2.type === normalizedType && config2.redCrystalCost > 0
4852
+ ).map(([name2, config2]) => {
4528
4853
  const infoBlocks = [
4529
4854
  `【${name2}】`,
4530
4855
  `类型:${config2.type}`,
4531
4856
  ...config2.damage ? [`基础伤害:${config2.damage}`] : [],
4532
4857
  `订购价:${config2.redCrystalCost}红晶`
4858
+ // 只显示红晶价格
4533
4859
  ];
4534
4860
  if (Object.keys(config2.tagEffects).length > 0) {
4535
4861
  const tagEffectsDesc = Object.entries(config2.tagEffects).map(([tag, mul]) => `▸ 对${tag}目标造成${(mul * 100).toFixed(0)}%伤害`).join("\n");
@@ -4541,13 +4867,16 @@ ${effectMessage.join("\n")}`
4541
4867
  );
4542
4868
  return infoBlocks.join("\n");
4543
4869
  }),
4544
- ...Object.entries(SyndicatedItems).filter(([_, item]) => item.type === normalizedType).map(([name2, item]) => {
4870
+ ...Object.entries(SyndicatedItems).filter(
4871
+ ([_, item]) => item.type === normalizedType && item.redCrystalCost > 0
4872
+ ).map(([name2, item]) => {
4545
4873
  const infoBlocks = [
4546
4874
  `【${name2}】`,
4547
4875
  `类型:${item.type}`,
4548
4876
  `订购价:${item.redCrystalCost}红晶`,
4877
+ // 只显示红晶价格
4549
4878
  `效果:${item.effects}`,
4550
- item.description,
4879
+ `描述:${item.description}`,
4551
4880
  "──────────────"
4552
4881
  ];
4553
4882
  return infoBlocks.join("\n");
@@ -4666,7 +4995,7 @@ ${effectMessage.join("\n")}`
4666
4995
  ) && item.quantity > 0
4667
4996
  );
4668
4997
  if (!validItems.length) {
4669
- message.push("你的特殊物品仓库空空如也。");
4998
+ message.push("你的物品仓库空空如也。");
4670
4999
  } else {
4671
5000
  message.push(
4672
5001
  validItems.map((warehouseItem) => {
@@ -4688,7 +5017,7 @@ ${effectMessage.join("\n")}`
4688
5017
  }
4689
5018
  return message.join("\n");
4690
5019
  });
4691
- ctx.command("ggcevo/使用 [itemName]").action(async (argv, itemName) => {
5020
+ ctx.command("ggcevo/使用 [itemName] [target]").action(async (argv, itemName, target) => {
4692
5021
  const session = argv.session;
4693
5022
  const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
4694
5023
  if (!profile) return "🔒 需要先绑定游戏句柄";
@@ -4710,24 +5039,18 @@ ${effectMessage.join("\n")}`
4710
5039
  ([_, item]) => item.id === targetItem.itemId
4711
5040
  );
4712
5041
  const [itemNameConfirmed, itemConfig2] = itemEntry;
4713
- if (itemConfig2.id === 1) {
4714
- const activeSentry = await ctx.database.get("ggcevo_boss", {
4715
- name: "空间站哨枪塔",
4716
- isActive: true
4717
- });
4718
- if (!activeSentry.length) return "⚠️ 目标「空间站哨枪塔」未激活";
4719
- }
5042
+ const effectResult = await applyItemEffect(session, handle, itemConfig2, target);
5043
+ if (!effectResult.success) return effectResult.message;
4720
5044
  const newQuantity = targetItem.quantity - 1;
4721
5045
  await ctx.database.set(
4722
5046
  "ggcevo_warehouse",
4723
5047
  { handle, itemId: targetItem.itemId },
4724
5048
  { quantity: newQuantity }
4725
5049
  );
4726
- const effectResult = await applyItemEffect(session, handle, itemConfig2);
4727
5050
  return [
4728
5051
  `✅ 成功使用 ${itemNameConfirmed}`,
4729
5052
  `├ 剩余数量:${newQuantity}`,
4730
- `└ 效果触发:${effectResult}`,
5053
+ `└ 效果触发:${effectResult.message}`,
4731
5054
  "─".repeat(25)
4732
5055
  ].join("\n");
4733
5056
  } catch (error) {
@@ -4735,6 +5058,139 @@ ${effectMessage.join("\n")}`
4735
5058
  return "⚠️ 物品使用失败,请联系管理员";
4736
5059
  }
4737
5060
  });
5061
+ ctx.command("ggcevo/科技 [techName]", "查看空间站科技信息").usage("输入“科技”查看列表,或“科技 科技名称”查看详细信息").action(async ({ session }, techName) => {
5062
+ const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
5063
+ if (!profile) return "🔒 需要先绑定游戏句柄";
5064
+ const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
5065
+ const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
5066
+ if (!careerData || careerData.group !== "人类联盟") {
5067
+ return "🚫 该功能需要【人类联盟】阵营权限";
5068
+ }
5069
+ const romanNumerals = { 1: "I", 2: "II", 3: "III", 4: "IV", 5: "V" };
5070
+ if (!techName) {
5071
+ const techList = Spacestationtechnology.map(
5072
+ (tech2) => `▸ ${tech2.techname} (最大等级 ${romanNumerals[tech2.maxLevel]})`
5073
+ );
5074
+ return [
5075
+ "🛰️ 空间站科技系统 🛰️",
5076
+ '使用 "科技 科技名称" 查看详细信息',
5077
+ "====================",
5078
+ ...techList,
5079
+ "===================="
5080
+ ].join("\n");
5081
+ }
5082
+ const tech = Spacestationtechnology.find(
5083
+ (t) => t.techname === techName
5084
+ );
5085
+ if (!tech) return `❌ 无效科技名称,可用科技:
5086
+ ${Spacestationtechnology.map((t) => t.techname).join("、")}`;
5087
+ const techDetails = tech.levels.map((level) => {
5088
+ return [
5089
+ `✦ 等级 ${romanNumerals[level.level]}`,
5090
+ `▸ 升级花费:${level.cost}金币`,
5091
+ `▸ 基础效果:${level.description}`,
5092
+ `💼 ${level.careerBonus}`,
5093
+ "------------------"
5094
+ ].join("\n");
5095
+ });
5096
+ return [
5097
+ `🛠️ ${tech.techname} 科技详情 🛠️`,
5098
+ `最大可升级等级:${romanNumerals[tech.maxLevel]}`,
5099
+ '使用 "升级 科技名称" 进行升级',
5100
+ "====================",
5101
+ ...techDetails,
5102
+ "===================="
5103
+ ].join("\n");
5104
+ });
5105
+ ctx.command("ggcevo/挖矿").action(async ({ session }) => {
5106
+ const convertUTCtoChinaTime2 = /* @__PURE__ */ __name((utcDate) => {
5107
+ const chinaOffset = 8 * 60 * 60 * 1e3;
5108
+ return new Date(utcDate.getTime() + chinaOffset);
5109
+ }, "convertUTCtoChinaTime");
5110
+ const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
5111
+ if (!profile) return "🔒 需要先绑定游戏句柄";
5112
+ const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
5113
+ if (await ctx.database.get("ggcevo_blacklist", { handle }).then((r) => r.length)) {
5114
+ return "⛔ 您已被列入黑名单";
5115
+ }
5116
+ const [career] = await ctx.database.get("ggcevo_careers", { handle });
5117
+ if (!["深空矿工", "情报副官"].includes(career?.career)) {
5118
+ return "🚫 需要职业为深空矿工或情报副官";
5119
+ }
5120
+ const [tech] = await ctx.database.get("ggcevo_tech", { handle, techId: 1 });
5121
+ if (!tech || tech.level < 2) return "🚫 需要采掘系统等级≥2";
5122
+ const [record] = await ctx.database.get("ggcevo_Mining", { handle });
5123
+ const [sign] = await ctx.database.get("ggcevo_sign", { handle });
5124
+ if (!record) {
5125
+ await ctx.database.create("ggcevo_Mining", {
5126
+ handle,
5127
+ startTime: /* @__PURE__ */ new Date()
5128
+ // 记录当前时间为开始时间
5129
+ });
5130
+ return "⛏️ 挖矿作业已开始,至少1小时后可收获";
5131
+ }
5132
+ const chinaStart = convertUTCtoChinaTime2(record.startTime);
5133
+ const chinaNow = convertUTCtoChinaTime2(/* @__PURE__ */ new Date());
5134
+ const duration = Math.floor(
5135
+ (chinaNow.getTime() - chinaStart.getTime()) / 1e3 / 60
5136
+ );
5137
+ if (duration < 60) {
5138
+ const remaining = 60 - duration;
5139
+ return [
5140
+ "⛏️ 挖矿进行中",
5141
+ `🕒 开始时间:${chinaStart.toLocaleString("zh-CN", { hour12: false })}`,
5142
+ `⏱️ 当前时间:${chinaNow.toLocaleString("zh-CN", { hour12: false })}`,
5143
+ `⏳ 还需等待:${remaining}分钟`,
5144
+ `💡 提示:达到1小时可随时收获并自动开始下一轮`
5145
+ ].join("\n");
5146
+ }
5147
+ const halfHours = Math.floor(duration / 30);
5148
+ let base = halfHours * 6.25;
5149
+ base = Math.round(base);
5150
+ base = Math.min(base, 300);
5151
+ let multiplier = 0;
5152
+ switch (tech.level) {
5153
+ case 3:
5154
+ multiplier = 0.1;
5155
+ break;
5156
+ // +10%
5157
+ case 4:
5158
+ multiplier = 0.3;
5159
+ break;
5160
+ // +30%
5161
+ case 5:
5162
+ multiplier = 0.5;
5163
+ break;
5164
+ }
5165
+ const total = Math.round(base * (1 + multiplier));
5166
+ await ctx.database.withTransaction(async () => {
5167
+ await ctx.database.upsert("ggcevo_sign", [{
5168
+ handle,
5169
+ totalRewards: (sign?.totalRewards || 0) + total
5170
+ }], ["handle"]);
5171
+ await ctx.database.set("ggcevo_Mining", { handle }, {
5172
+ startTime: /* @__PURE__ */ new Date()
5173
+ // 重置为当前时间
5174
+ });
5175
+ });
5176
+ const formatTime = /* @__PURE__ */ __name((mins) => {
5177
+ const hours = Math.floor(mins / 60);
5178
+ const minutes = mins % 60;
5179
+ return `${hours}小时${minutes}分钟`;
5180
+ }, "formatTime");
5181
+ return [
5182
+ "⛏️ 挖矿报告",
5183
+ `🕒 开始时间:${chinaStart.toLocaleString("zh-CN", { hour12: false })}`,
5184
+ `⏱️ 结束时间:${chinaNow.toLocaleString("zh-CN", { hour12: false })}`,
5185
+ `⏳ 持续时间:${formatTime(duration)}`,
5186
+ ...tech.level >= 3 ? (
5187
+ // 仅当科技等级≥3时显示加成信息
5188
+ [`🔧 科技加成(Lv.${tech.level}):+${multiplier * 100}%`]
5189
+ ) : [],
5190
+ `💰 实际获得:${total}金币`,
5191
+ "💡 已自动开始下一轮挖矿"
5192
+ ].join("\n");
5193
+ });
4738
5194
  }
4739
5195
  __name(apply, "apply");
4740
5196
  function simpleDraw() {
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.2.72",
4
+ "version": "1.3.0",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [