koishi-plugin-ggcevo-game 1.4.45 → 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.
- package/lib/database.d.ts +14 -0
- package/lib/index.js +232 -32
- package/lib/utils.d.ts +3 -0
- package/package.json +1 -1
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
|
@@ -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 = {};
|
|
@@ -5069,6 +5084,16 @@ function apply(ctx, config) {
|
|
|
5069
5084
|
}, {
|
|
5070
5085
|
primary: "handle"
|
|
5071
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
|
+
});
|
|
5072
5097
|
ctx.setInterval(async () => {
|
|
5073
5098
|
const totalBosses = await ctx.database.select("ggcevo_boss").execute((row) => import_koishi.$.count(row.name));
|
|
5074
5099
|
const groupId = [...config.groupId];
|
|
@@ -5243,6 +5268,15 @@ function apply(ctx, config) {
|
|
|
5243
5268
|
ctx.logger.error("监控失败:", error);
|
|
5244
5269
|
}
|
|
5245
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);
|
|
5246
5280
|
ctx.command("ggcevo/抽奖").action(async (argv) => {
|
|
5247
5281
|
const session = argv.session;
|
|
5248
5282
|
let winCount = 0;
|
|
@@ -6433,6 +6467,38 @@ ${items.join("、")}
|
|
|
6433
6467
|
if (!targetCareer?.group || !validGroups.has(targetCareer.group)) {
|
|
6434
6468
|
return "❌ 对方尚未加入人类联盟或辛迪加海盗,不能参与PK";
|
|
6435
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
|
+
}
|
|
6436
6502
|
if (targetCareer.group === "人类联盟") {
|
|
6437
6503
|
let joinDate;
|
|
6438
6504
|
if (typeof targetCareer.date === "string") {
|
|
@@ -6452,9 +6518,9 @@ ${items.join("、")}
|
|
|
6452
6518
|
handle: targetHandle
|
|
6453
6519
|
});
|
|
6454
6520
|
const isNewPlayer = !targetPKRecord;
|
|
6455
|
-
const
|
|
6521
|
+
const hasProtection2 = diffInDays < 30;
|
|
6456
6522
|
const isPKDisabled = targetPKRecord && !targetPKRecord.enable;
|
|
6457
|
-
if ((isNewPlayer || isPKDisabled) &&
|
|
6523
|
+
if ((isNewPlayer || isPKDisabled) && hasProtection2) {
|
|
6458
6524
|
return `🛡️ 该玩家是人类联盟成员,当前处于30天保护期内(剩余${30 - diffInDays}天),无法PK`;
|
|
6459
6525
|
}
|
|
6460
6526
|
}
|
|
@@ -7815,6 +7881,56 @@ ${validTypes.join("、")}`;
|
|
|
7815
7881
|
return "加入阵营时发生错误,请稍后再试";
|
|
7816
7882
|
}
|
|
7817
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
|
+
});
|
|
7818
7934
|
ctx.command("ggcevo/转职 [profession]", "转职系统").action(async ({ session }, profession) => {
|
|
7819
7935
|
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
7820
7936
|
if (!profile) return "🔒 需要先绑定游戏句柄。";
|
|
@@ -7903,39 +8019,62 @@ ${validTypes.join("、")}`;
|
|
|
7903
8019
|
});
|
|
7904
8020
|
if (!profile) return "🔒 需要先绑定游戏句柄。";
|
|
7905
8021
|
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
7906
|
-
|
|
7907
|
-
if (!careerData)
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
const
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
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}`);
|
|
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
|
+
}
|
|
7931
8063
|
}
|
|
8064
|
+
} else {
|
|
8065
|
+
infoCard.push(
|
|
8066
|
+
"🎯 当前阵营:无",
|
|
8067
|
+
"👔 当前职业:无",
|
|
8068
|
+
"",
|
|
8069
|
+
'💡 使用"加入阵营"指令选择你的阵营'
|
|
8070
|
+
);
|
|
7932
8071
|
}
|
|
7933
|
-
const
|
|
8072
|
+
const divider = "〓═════════〓";
|
|
8073
|
+
const promptMessage = careerData.group === "辛迪加海盗" ? "💡 提示:红晶可通过主动发起PK获得(无论胜负)" : careerData.group ? "💡 提示:使用「转职」指令可变更职业" : "";
|
|
7934
8074
|
return [
|
|
7935
8075
|
`〓 职业档案 〓`,
|
|
7936
8076
|
...infoCard,
|
|
7937
|
-
|
|
7938
|
-
// 提示信息放在分隔线下方
|
|
8077
|
+
...promptMessage ? [divider, promptMessage] : []
|
|
7939
8078
|
].join("\n");
|
|
7940
8079
|
} catch (error) {
|
|
7941
8080
|
ctx.logger.error("查询职业信息失败:", error);
|
|
@@ -8415,7 +8554,7 @@ ${Spacestationtechnology.map((t) => t.techname).join("、")}`;
|
|
|
8415
8554
|
// 新增累加
|
|
8416
8555
|
});
|
|
8417
8556
|
});
|
|
8418
|
-
const
|
|
8557
|
+
const formatTime2 = /* @__PURE__ */ __name((mins) => {
|
|
8419
8558
|
const hours = Math.floor(mins / 60);
|
|
8420
8559
|
const minutes = mins % 60;
|
|
8421
8560
|
return `${hours}小时${minutes}分钟`;
|
|
@@ -8424,7 +8563,7 @@ ${Spacestationtechnology.map((t) => t.techname).join("、")}`;
|
|
|
8424
8563
|
"⛏️ 挖矿报告",
|
|
8425
8564
|
`🕒 开始时间:${record.startTime.toLocaleString("zh-CN", { hour12: false })}`,
|
|
8426
8565
|
`⏱️ 结束时间:${nowtime.toLocaleString("zh-CN", { hour12: false })}`,
|
|
8427
|
-
`⏳ 持续时间:${
|
|
8566
|
+
`⏳ 持续时间:${formatTime2(duration)}`
|
|
8428
8567
|
];
|
|
8429
8568
|
const maxHours = tech.level === 5 ? 48 : 24;
|
|
8430
8569
|
if (duration > maxHours * 60) {
|
|
@@ -8576,6 +8715,67 @@ ${Spacestationtechnology.map((t) => t.techname).join("、")}`;
|
|
|
8576
8715
|
return "处理任务时发生错误,请稍后重试。";
|
|
8577
8716
|
}
|
|
8578
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
|
+
});
|
|
8579
8779
|
}
|
|
8580
8780
|
__name(apply, "apply");
|
|
8581
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;
|