koishi-plugin-ggcevo-game 1.1.6 → 1.2.1
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 +28 -2
- package/lib/index.js +724 -60
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -34,6 +34,9 @@ declare module 'koishi' {
|
|
|
34
34
|
ggcevo_achievements: Achievement;
|
|
35
35
|
ggcevo_pk: PKRecord;
|
|
36
36
|
ggcevo_pk_logs: PKLog;
|
|
37
|
+
ggcevo_equipment: equipment;
|
|
38
|
+
ggcevo_boss: Boss;
|
|
39
|
+
ggcevo_boss_damage: BossDamageRecord;
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
42
|
export interface backpack {
|
|
@@ -121,11 +124,34 @@ export interface PKRecord {
|
|
|
121
124
|
enable: boolean;
|
|
122
125
|
lastToggle: Date;
|
|
123
126
|
}
|
|
124
|
-
interface PKLog {
|
|
127
|
+
export interface PKLog {
|
|
125
128
|
id: number;
|
|
126
129
|
initiator_handle: string;
|
|
127
130
|
target_handle: string;
|
|
128
131
|
date: Date;
|
|
129
132
|
}
|
|
133
|
+
export interface equipment {
|
|
134
|
+
handle: string;
|
|
135
|
+
weaponId: number;
|
|
136
|
+
level: number;
|
|
137
|
+
modificationSlots: number;
|
|
138
|
+
installedMods: string[];
|
|
139
|
+
equipped: boolean;
|
|
140
|
+
}
|
|
141
|
+
export interface Boss {
|
|
142
|
+
name: string;
|
|
143
|
+
type: string;
|
|
144
|
+
HP: number;
|
|
145
|
+
groupId: number;
|
|
146
|
+
isActive: boolean;
|
|
147
|
+
respawnTime: Date;
|
|
148
|
+
}
|
|
149
|
+
export interface BossDamageRecord {
|
|
150
|
+
handle: string;
|
|
151
|
+
playerName: string;
|
|
152
|
+
totalDamage: number;
|
|
153
|
+
attackCount: number;
|
|
154
|
+
bossGroupId: number;
|
|
155
|
+
lastattackDate: Date;
|
|
156
|
+
}
|
|
130
157
|
export declare function apply(ctx: Context, config: Config): void;
|
|
131
|
-
export {};
|
package/lib/index.js
CHANGED
|
@@ -214,6 +214,97 @@ function apply(ctx, config) {
|
|
|
214
214
|
primary: "id",
|
|
215
215
|
autoInc: true
|
|
216
216
|
});
|
|
217
|
+
ctx.model.extend("ggcevo_equipment", {
|
|
218
|
+
handle: "string",
|
|
219
|
+
weaponId: "unsigned",
|
|
220
|
+
level: "unsigned",
|
|
221
|
+
modificationSlots: "unsigned",
|
|
222
|
+
installedMods: "list",
|
|
223
|
+
equipped: "boolean"
|
|
224
|
+
}, {
|
|
225
|
+
primary: ["handle", "weaponId"]
|
|
226
|
+
});
|
|
227
|
+
ctx.model.extend("ggcevo_boss", {
|
|
228
|
+
name: "string",
|
|
229
|
+
type: "string",
|
|
230
|
+
HP: "unsigned",
|
|
231
|
+
groupId: "unsigned",
|
|
232
|
+
isActive: "boolean",
|
|
233
|
+
respawnTime: "timestamp"
|
|
234
|
+
}, {
|
|
235
|
+
primary: "name"
|
|
236
|
+
});
|
|
237
|
+
ctx.model.extend("ggcevo_boss_damage", {
|
|
238
|
+
handle: "string",
|
|
239
|
+
playerName: "string",
|
|
240
|
+
totalDamage: "unsigned",
|
|
241
|
+
attackCount: "unsigned",
|
|
242
|
+
bossGroupId: "unsigned",
|
|
243
|
+
lastattackDate: "timestamp"
|
|
244
|
+
}, {
|
|
245
|
+
primary: "handle"
|
|
246
|
+
});
|
|
247
|
+
const weaponConfig = {
|
|
248
|
+
// 武器配置
|
|
249
|
+
"高斯步枪": {
|
|
250
|
+
id: 1,
|
|
251
|
+
type: "实弹武器",
|
|
252
|
+
damage: 10,
|
|
253
|
+
description: "标准配置武器,中距离作战利器",
|
|
254
|
+
price: 100,
|
|
255
|
+
tagEffects: {
|
|
256
|
+
"轻甲": 1.5,
|
|
257
|
+
// 对轻甲目标造成150%伤害
|
|
258
|
+
"重甲": 0.7
|
|
259
|
+
// 对重甲目标造成70%伤害
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
"激光步枪": {
|
|
263
|
+
id: 2,
|
|
264
|
+
type: "能量武器",
|
|
265
|
+
damage: 23,
|
|
266
|
+
description: "先进激光武器,远距离精准打击",
|
|
267
|
+
price: 300,
|
|
268
|
+
tagEffects: {
|
|
269
|
+
"重甲": 1.5,
|
|
270
|
+
// 对重甲目标造成150%伤害
|
|
271
|
+
"护盾": 0.5
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
const modConfig = {
|
|
276
|
+
"动能增幅": {
|
|
277
|
+
cost: 1250,
|
|
278
|
+
effect: "伤害+20%",
|
|
279
|
+
description: "动能增幅(伤害+20%)"
|
|
280
|
+
// 新增描述字段
|
|
281
|
+
},
|
|
282
|
+
"棱镜水晶": {
|
|
283
|
+
cost: 1750,
|
|
284
|
+
effect: "20%暴击率",
|
|
285
|
+
description: "棱镜水晶(20%暴击率)"
|
|
286
|
+
// 新增描述字段
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
const bossPool = [
|
|
290
|
+
{
|
|
291
|
+
main: {
|
|
292
|
+
id: 1,
|
|
293
|
+
name: "异齿猛兽-首领",
|
|
294
|
+
type: "主宰",
|
|
295
|
+
maxHP: 1e4,
|
|
296
|
+
tags: ["重甲", "生物"]
|
|
297
|
+
},
|
|
298
|
+
minions: [
|
|
299
|
+
{
|
|
300
|
+
name: "异齿猛兽",
|
|
301
|
+
type: "子代",
|
|
302
|
+
maxHP: 2e3,
|
|
303
|
+
tags: ["重甲", "生物"]
|
|
304
|
+
}
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
];
|
|
217
308
|
const initDefaultItems = {
|
|
218
309
|
"咕咕币": { id: 1, type: "抽奖道具", description: "用于进行抽奖" },
|
|
219
310
|
"兑换券": { id: 2, type: "兑换货币", description: "用于兑换赞助物品" },
|
|
@@ -228,6 +319,29 @@ function apply(ctx, config) {
|
|
|
228
319
|
"🏅先行者赛季前十勋章": { id: 104, type: "勋章", description: "先行者赛季胜点榜第四名到第十名奖励" },
|
|
229
320
|
"🎖先行者赛季前二十勋章": { id: 105, type: "勋章", description: "先行者赛季胜点榜第十一名到第二十名奖励" }
|
|
230
321
|
};
|
|
322
|
+
const itemConfig = {
|
|
323
|
+
"拾荒者": { quality: "t3", type: "皮肤", cost: 3, isLimited: false },
|
|
324
|
+
"劳工": { quality: "t3", type: "皮肤", cost: 3, isLimited: false },
|
|
325
|
+
"老兵": { quality: "t2", type: "皮肤", cost: 4, isLimited: false },
|
|
326
|
+
"合成人": { quality: "t2", type: "皮肤", cost: 4, isLimited: false },
|
|
327
|
+
"阿斯塔特": { quality: "t1", type: "皮肤", cost: 5, isLimited: false },
|
|
328
|
+
"皇家指挥官": { quality: "t1", type: "皮肤", cost: 5, isLimited: false },
|
|
329
|
+
"个性开场白": { quality: "t1", type: "入场特效", cost: 5, quantity: 5, isLimited: false },
|
|
330
|
+
"史蒂夫": { quality: "t0", type: "皮肤", cost: 6, quantity: 1, isLimited: true },
|
|
331
|
+
"ep4": { quality: "t0", type: "物品", cost: 6, quantity: 3, isLimited: false },
|
|
332
|
+
"小狗": { quality: "t3", type: "宠物", cost: 3, quantity: 5, isLimited: false },
|
|
333
|
+
"小猫": { quality: "t3", type: "宠物", cost: 3, quantity: 5, isLimited: false },
|
|
334
|
+
"小黄鸭": { quality: "t3", type: "宠物", cost: 3, quantity: 5, isLimited: false },
|
|
335
|
+
"萌萌熊": { quality: "t2", type: "宠物", cost: 4, quantity: 3, isLimited: false },
|
|
336
|
+
"荆棘蜥蜴": { quality: "t2", type: "宠物", cost: 4, quantity: 3, isLimited: false },
|
|
337
|
+
"萌宠小狗": { quality: "t1", type: "宠物", cost: 5, quantity: 2, isLimited: false },
|
|
338
|
+
"熔岩虫": { quality: "t1", type: "宠物", cost: 5, quantity: 2, isLimited: false },
|
|
339
|
+
"尸甲虫": { quality: "t1", type: "宠物", cost: 5, quantity: 2, isLimited: false },
|
|
340
|
+
"绿毛虫": { quality: "t0", type: "宠物", cost: 6, quantity: 1, isLimited: false },
|
|
341
|
+
"妙蛙种子": { quality: "t0", type: "宠物", cost: 6, quantity: 1, isLimited: false },
|
|
342
|
+
"皮卡丘": { quality: "t0", type: "宠物", cost: 6, quantity: 1, isLimited: false },
|
|
343
|
+
"哆啦A梦": { quality: "t0", type: "宠物", cost: 6, quantity: 1, isLimited: false }
|
|
344
|
+
};
|
|
231
345
|
async function gachaWithPity(handle) {
|
|
232
346
|
const [record] = await ctx.database.get("ggcevo_records", { handle });
|
|
233
347
|
const currentPity = record?.pityCounter ?? 0;
|
|
@@ -303,6 +417,67 @@ function apply(ctx, config) {
|
|
|
303
417
|
}
|
|
304
418
|
}
|
|
305
419
|
__name(checkSensitiveWord, "checkSensitiveWord");
|
|
420
|
+
async function initializeBoss() {
|
|
421
|
+
const activeBoss = await ctx.database.get("ggcevo_boss", { isActive: true });
|
|
422
|
+
if (!activeBoss.length) {
|
|
423
|
+
await activateNextBossGroup();
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
__name(initializeBoss, "initializeBoss");
|
|
427
|
+
async function activateNextBossGroup(currentBossId = null) {
|
|
428
|
+
let nextIndex = 0;
|
|
429
|
+
if (currentBossId !== null) {
|
|
430
|
+
const currentIndex = bossPool.findIndex((b) => b.main.id === currentBossId);
|
|
431
|
+
if (currentIndex !== -1) {
|
|
432
|
+
nextIndex = (currentIndex + 1) % bossPool.length;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
const nextBossGroup = bossPool[nextIndex];
|
|
436
|
+
const mainBoss = await ctx.database.create("ggcevo_boss", {
|
|
437
|
+
name: nextBossGroup.main.name,
|
|
438
|
+
type: nextBossGroup.main.type,
|
|
439
|
+
HP: nextBossGroup.main.maxHP,
|
|
440
|
+
groupId: nextBossGroup.main.id,
|
|
441
|
+
isActive: true,
|
|
442
|
+
respawnTime: /* @__PURE__ */ new Date()
|
|
443
|
+
});
|
|
444
|
+
for (const minion of nextBossGroup.minions) {
|
|
445
|
+
await ctx.database.create("ggcevo_boss", {
|
|
446
|
+
name: minion.name,
|
|
447
|
+
type: minion.type,
|
|
448
|
+
HP: minion.maxHP,
|
|
449
|
+
groupId: mainBoss.groupId,
|
|
450
|
+
isActive: true,
|
|
451
|
+
respawnTime: /* @__PURE__ */ new Date()
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
return mainBoss;
|
|
455
|
+
}
|
|
456
|
+
__name(activateNextBossGroup, "activateNextBossGroup");
|
|
457
|
+
function createHpBar(current, max) {
|
|
458
|
+
const ratio = current / max;
|
|
459
|
+
const filled = Math.floor(ratio * 20);
|
|
460
|
+
return "▰".repeat(filled) + "▱".repeat(20 - filled);
|
|
461
|
+
}
|
|
462
|
+
__name(createHpBar, "createHpBar");
|
|
463
|
+
ctx.setInterval(async () => {
|
|
464
|
+
const now = /* @__PURE__ */ new Date();
|
|
465
|
+
const expiredGroups = await ctx.database.select("ggcevo_boss").where({
|
|
466
|
+
type: "主宰",
|
|
467
|
+
respawnTime: { $lte: now },
|
|
468
|
+
isActive: false
|
|
469
|
+
}).execute();
|
|
470
|
+
for (const group of expiredGroups) {
|
|
471
|
+
await ctx.database.remove("ggcevo_boss", {
|
|
472
|
+
groupId: group.groupId
|
|
473
|
+
});
|
|
474
|
+
await activateNextBossGroup(group.groupId);
|
|
475
|
+
ctx.broadcast(
|
|
476
|
+
config.groupId,
|
|
477
|
+
`🔄 BOSS已刷新!新的BOSS组已出现,快去挑战吧!`
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
}, 60 * 1e3);
|
|
306
481
|
ctx.command("ggcevo/抽奖").action(async (argv) => {
|
|
307
482
|
const session = argv.session;
|
|
308
483
|
let winCount = 0;
|
|
@@ -1092,29 +1267,6 @@ ID:${activity.id}
|
|
|
1092
1267
|
pageNum < totalPages ? `输入 违规记录 -p ${pageNum + 1} 查看下一条` : "已是最后一页"
|
|
1093
1268
|
].join("\n");
|
|
1094
1269
|
});
|
|
1095
|
-
const itemConfig = {
|
|
1096
|
-
"拾荒者": { quality: "t3", type: "皮肤", cost: 3, isLimited: false },
|
|
1097
|
-
"劳工": { quality: "t3", type: "皮肤", cost: 3, isLimited: false },
|
|
1098
|
-
"老兵": { quality: "t2", type: "皮肤", cost: 4, isLimited: false },
|
|
1099
|
-
"合成人": { quality: "t2", type: "皮肤", cost: 4, isLimited: false },
|
|
1100
|
-
"阿斯塔特": { quality: "t1", type: "皮肤", cost: 5, isLimited: false },
|
|
1101
|
-
"皇家指挥官": { quality: "t1", type: "皮肤", cost: 5, isLimited: false },
|
|
1102
|
-
"个性开场白": { quality: "t1", type: "入场特效", cost: 5, quantity: 5, isLimited: false },
|
|
1103
|
-
"史蒂夫": { quality: "t0", type: "皮肤", cost: 6, quantity: 1, isLimited: true },
|
|
1104
|
-
"ep4": { quality: "t0", type: "物品", cost: 6, quantity: 3, isLimited: false },
|
|
1105
|
-
"小狗": { quality: "t3", type: "宠物", cost: 3, quantity: 5, isLimited: false },
|
|
1106
|
-
"小猫": { quality: "t3", type: "宠物", cost: 3, quantity: 5, isLimited: false },
|
|
1107
|
-
"小黄鸭": { quality: "t3", type: "宠物", cost: 3, quantity: 5, isLimited: false },
|
|
1108
|
-
"萌萌熊": { quality: "t2", type: "宠物", cost: 4, quantity: 3, isLimited: false },
|
|
1109
|
-
"荆棘蜥蜴": { quality: "t2", type: "宠物", cost: 4, quantity: 3, isLimited: false },
|
|
1110
|
-
"萌宠小狗": { quality: "t1", type: "宠物", cost: 5, quantity: 2, isLimited: false },
|
|
1111
|
-
"熔岩虫": { quality: "t1", type: "宠物", cost: 5, quantity: 2, isLimited: false },
|
|
1112
|
-
"尸甲虫": { quality: "t1", type: "宠物", cost: 5, quantity: 2, isLimited: false },
|
|
1113
|
-
"绿毛虫": { quality: "t0", type: "宠物", cost: 6, quantity: 1, isLimited: false },
|
|
1114
|
-
"妙蛙种子": { quality: "t0", type: "宠物", cost: 6, quantity: 1, isLimited: false },
|
|
1115
|
-
"皮卡丘": { quality: "t0", type: "宠物", cost: 6, quantity: 1, isLimited: false },
|
|
1116
|
-
"哆啦A梦": { quality: "t0", type: "宠物", cost: 6, quantity: 1, isLimited: false }
|
|
1117
|
-
};
|
|
1118
1270
|
ctx.command("ggcevo/兑换", "兑换物品").action(async ({ session }) => {
|
|
1119
1271
|
try {
|
|
1120
1272
|
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
@@ -1476,52 +1628,67 @@ ${achievementList.join("\n")}`;
|
|
|
1476
1628
|
const processedLobbies = /* @__PURE__ */ new Set();
|
|
1477
1629
|
ctx.setInterval(async () => {
|
|
1478
1630
|
try {
|
|
1479
|
-
const response = await ctx.http("get", "
|
|
1631
|
+
const response = await ctx.http("get", "API_URL");
|
|
1480
1632
|
const data = response.data;
|
|
1481
1633
|
const openLobbies = data.results.filter(
|
|
1482
1634
|
(lobby) => lobby.status === "open" && !processedLobbies.has(lobby.id)
|
|
1483
1635
|
);
|
|
1484
|
-
const
|
|
1485
|
-
(lobby) => lobby.slots.filter((slot) => slot.kind === "human" && slot.profile).map((slot) => {
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1636
|
+
const allPlayers = openLobbies.flatMap(
|
|
1637
|
+
(lobby) => lobby.slots.filter((slot) => slot.kind === "human" && slot.profile).map((slot) => ({
|
|
1638
|
+
regionId: slot.profile.regionId,
|
|
1639
|
+
realmId: slot.profile.realmId,
|
|
1640
|
+
profileId: slot.profile.profileId,
|
|
1641
|
+
handle: `${slot.profile.regionId}-S2-${slot.profile.realmId}-${slot.profile.profileId}`,
|
|
1642
|
+
name: slot.name
|
|
1643
|
+
// 保留名称用于后续展示
|
|
1644
|
+
}))
|
|
1489
1645
|
);
|
|
1490
|
-
const
|
|
1646
|
+
const punishmentRecords = await ctx.database.select("ggcevo_Punishment").where({
|
|
1491
1647
|
$and: [
|
|
1492
|
-
{ handle: { $in:
|
|
1648
|
+
{ handle: { $in: allPlayers.map((p) => p.handle) } },
|
|
1493
1649
|
{ id: { $gte: 1889 } },
|
|
1494
1650
|
{ level: { $in: ["B", "B+", "A"] } }
|
|
1495
1651
|
]
|
|
1496
|
-
}).execute()
|
|
1497
|
-
|
|
1498
|
-
level: r.level
|
|
1499
|
-
})));
|
|
1500
|
-
const punishmentMap = new Map(records.map((r) => [r.handle, r]));
|
|
1652
|
+
}).execute();
|
|
1653
|
+
const punishedHandles = new Set(punishmentRecords.map((r) => r.handle));
|
|
1501
1654
|
for (const lobby of openLobbies) {
|
|
1502
|
-
const
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1655
|
+
const lobbyPlayers = lobby.slots.filter((slot) => slot.kind === "human" && slot.profile).map((slot) => ({
|
|
1656
|
+
regionId: slot.profile.regionId,
|
|
1657
|
+
realmId: slot.profile.realmId,
|
|
1658
|
+
profileId: slot.profile.profileId,
|
|
1659
|
+
handle: `${slot.profile.regionId}-S2-${slot.profile.realmId}-${slot.profile.profileId}`,
|
|
1660
|
+
name: slot.name
|
|
1661
|
+
}));
|
|
1662
|
+
const violators = lobbyPlayers.filter((p) => punishedHandles.has(p.handle));
|
|
1663
|
+
if (violators.length > 0) {
|
|
1664
|
+
const unpunishedPlayersData = lobbyPlayers.filter(
|
|
1665
|
+
(p) => !punishedHandles.has(p.handle)
|
|
1666
|
+
);
|
|
1667
|
+
const queryConditions = unpunishedPlayersData.map((p) => ({
|
|
1668
|
+
regionId: p.regionId,
|
|
1669
|
+
realmId: p.realmId,
|
|
1670
|
+
profileId: p.profileId
|
|
1671
|
+
}));
|
|
1672
|
+
const safePlayers = await ctx.database.select("sc2arcade_player").where({ $or: queryConditions }).execute().then((res) => res.map((r) => r.userId));
|
|
1673
|
+
const atElements = safePlayers.map((userId) => `<at id="${userId}"/>`).join(" ");
|
|
1508
1674
|
const message = [
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
...
|
|
1514
|
-
(
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1675
|
+
`📺 监测到违规大厅 ID: ${lobby.id}`,
|
|
1676
|
+
`创建时间: ${new Date(lobby.createdAt).toLocaleString("zh-CN")}`,
|
|
1677
|
+
`🏆 安全玩家:${atElements || "无"}`,
|
|
1678
|
+
`🚨 违规玩家(${violators.length} 人):`,
|
|
1679
|
+
...violators.map((v) => {
|
|
1680
|
+
const record = punishmentRecords.find((r) => r.handle === v.handle);
|
|
1681
|
+
return `· ${v.name}(${record?.level}级处罚)`;
|
|
1682
|
+
}),
|
|
1683
|
+
`房主: ${lobby.hostName}`,
|
|
1684
|
+
`玩家数: ${lobby.slotsHumansTaken}/${lobby.slotsHumansTotal}`
|
|
1518
1685
|
].join("\n");
|
|
1519
1686
|
await ctx.broadcast(config.groupId, message);
|
|
1520
1687
|
processedLobbies.add(lobby.id);
|
|
1521
1688
|
}
|
|
1522
1689
|
}
|
|
1523
1690
|
} catch (error) {
|
|
1524
|
-
ctx.logger.error("
|
|
1691
|
+
ctx.logger.error("监控失败:", error);
|
|
1525
1692
|
}
|
|
1526
1693
|
}, config.checkInterval * 1e3);
|
|
1527
1694
|
ctx.command("ggcevo/pk [user]", "发起玩家对战").alias("挑战").action(async (argv, user) => {
|
|
@@ -1608,13 +1775,6 @@ ${achievementList.join("\n")}`;
|
|
|
1608
1775
|
return `该玩家今日已被挑战太多次(最多${config.maxDailyBeChallenged}次)`;
|
|
1609
1776
|
}
|
|
1610
1777
|
}
|
|
1611
|
-
const [finalInitiator, finalTarget] = await Promise.all([
|
|
1612
|
-
ctx.database.get("ggcevo_pk", initiatorHandle),
|
|
1613
|
-
ctx.database.get("ggcevo_pk", targetHandle)
|
|
1614
|
-
]);
|
|
1615
|
-
if (!finalInitiator[0]?.enable || !finalTarget[0]?.enable) {
|
|
1616
|
-
return "对战状态已发生变化,请重新发起挑战。";
|
|
1617
|
-
}
|
|
1618
1778
|
const [initiatorData, targetData] = await Promise.all([
|
|
1619
1779
|
ctx.database.get("ggcevo_rank", initiatorHandle),
|
|
1620
1780
|
ctx.database.get("ggcevo_rank", targetHandle)
|
|
@@ -1689,7 +1849,7 @@ ${achievementList.join("\n")}`;
|
|
|
1689
1849
|
`⚔️【对战结果】${isWin ? "胜利" : "失败"}`,
|
|
1690
1850
|
`🏅 挑战者:${initiatorRankname}(积分 ${initiatorRank})`,
|
|
1691
1851
|
`🛡️ 应战者:${targetRankname}(积分 ${targetRank})`,
|
|
1692
|
-
`📊
|
|
1852
|
+
`📊 胜率预测:${winRate.toFixed(1)}%`,
|
|
1693
1853
|
`🎰 金币变动:${stealPercentage}%`
|
|
1694
1854
|
];
|
|
1695
1855
|
isWin ? result.push(`💰您获得 ${goldTransfer}`, `💸 对方损失 ${goldTransfer}`) : result.push(`💸您损失 ${goldTransfer}`, `💰 对方获得 ${goldTransfer}`);
|
|
@@ -1750,6 +1910,510 @@ ${achievementList.join("\n")}`;
|
|
|
1750
1910
|
day: "2-digit"
|
|
1751
1911
|
})}`;
|
|
1752
1912
|
});
|
|
1913
|
+
ctx.command("ggcevo/商城").action(async ({ session }) => {
|
|
1914
|
+
const items = Object.entries(weaponConfig).map(([name2, config2]) => {
|
|
1915
|
+
const tagEffectsDesc = config2.tagEffects ? Object.entries(config2.tagEffects).map(([tag, multiplier]) => `▸ 对${tag}目标造成${(multiplier * 100).toFixed(0)}%伤害`).join("\n") : "▸ 无特殊加成效果";
|
|
1916
|
+
return [
|
|
1917
|
+
`【${name2}】`,
|
|
1918
|
+
`类型:${config2.type}`,
|
|
1919
|
+
`基础伤害:${config2.damage}`,
|
|
1920
|
+
`价格:${config2.price}金币`,
|
|
1921
|
+
"特性:",
|
|
1922
|
+
tagEffectsDesc,
|
|
1923
|
+
config2.description
|
|
1924
|
+
].join("\n");
|
|
1925
|
+
});
|
|
1926
|
+
return [
|
|
1927
|
+
"🏪 咕咕军火商店 🏪",
|
|
1928
|
+
"使用“购买 武器名称”命令进行购买",
|
|
1929
|
+
"====================",
|
|
1930
|
+
...items
|
|
1931
|
+
].join("\n\n");
|
|
1932
|
+
});
|
|
1933
|
+
ctx.command("ggcevo/购买 <weapon>").action(async ({ session }, weapon) => {
|
|
1934
|
+
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
1935
|
+
if (!profile) return "未绑定句柄";
|
|
1936
|
+
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
1937
|
+
const [signInfo] = await ctx.database.get("ggcevo_sign", { handle });
|
|
1938
|
+
if (!weaponConfig[weapon]) return "无效的武器名称";
|
|
1939
|
+
const config2 = weaponConfig[weapon];
|
|
1940
|
+
if ((signInfo?.totalRewards || 0) < config2.price)
|
|
1941
|
+
return `金币不足,需要${config2.price}金币`;
|
|
1942
|
+
await ctx.database.withTransaction(async () => {
|
|
1943
|
+
await ctx.database.set("ggcevo_sign", { handle }, {
|
|
1944
|
+
totalRewards: signInfo.totalRewards - config2.price
|
|
1945
|
+
});
|
|
1946
|
+
await ctx.database.upsert("ggcevo_equipment", [{
|
|
1947
|
+
handle,
|
|
1948
|
+
weaponId: config2.id,
|
|
1949
|
+
level: 0,
|
|
1950
|
+
// 初始等级为0
|
|
1951
|
+
modificationSlots: 1,
|
|
1952
|
+
// 初始改装槽为1
|
|
1953
|
+
equipped: false
|
|
1954
|
+
}], ["handle", "weaponId"]);
|
|
1955
|
+
});
|
|
1956
|
+
return `成功购买 ${weapon}!输入“装备列表”查看你的武器库`;
|
|
1957
|
+
});
|
|
1958
|
+
ctx.command("ggcevo/装备列表").action(async ({ session }) => {
|
|
1959
|
+
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
1960
|
+
if (!profile) return "未绑定句柄";
|
|
1961
|
+
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
1962
|
+
const weapons = await ctx.database.get("ggcevo_equipment", {
|
|
1963
|
+
handle
|
|
1964
|
+
});
|
|
1965
|
+
const weaponDetails = await Promise.all(weapons.map(async (w) => {
|
|
1966
|
+
const weaponName = Object.entries(weaponConfig).find(([_, c]) => c.id === w.weaponId)[0];
|
|
1967
|
+
const config2 = weaponConfig[weaponName];
|
|
1968
|
+
const statusIcon = w.equipped ? "⚡" : "・";
|
|
1969
|
+
const statusText = w.equipped ? "[已装备]" : "";
|
|
1970
|
+
const currentDamage = config2.damage * (1 + 0.1 * w.level);
|
|
1971
|
+
const mods = w.installedMods.map((m) => modConfig[m].description).join(" | ") || "无";
|
|
1972
|
+
return [
|
|
1973
|
+
`${statusIcon} ${weaponName} ${statusText}`,
|
|
1974
|
+
`等级:Lv.${w.level} | 改装槽:${w.modificationSlots}`,
|
|
1975
|
+
`伤害:${config2.damage} → ${currentDamage.toFixed(1)}`,
|
|
1976
|
+
`改装:${mods}`
|
|
1977
|
+
].join("\n");
|
|
1978
|
+
}));
|
|
1979
|
+
return [
|
|
1980
|
+
"🛡️ 当前装备库",
|
|
1981
|
+
'使用"装备 武器名称"切换装备',
|
|
1982
|
+
"⚡表示当前装备武器",
|
|
1983
|
+
"────────────────",
|
|
1984
|
+
...weaponDetails.length ? weaponDetails : ["空空如也,快去商城看看吧!"],
|
|
1985
|
+
"────────────────",
|
|
1986
|
+
"💡 装备效果说明:",
|
|
1987
|
+
"⚡ 已装备武器会在战斗中生效",
|
|
1988
|
+
"🔧 改装效果仅在战斗时计算"
|
|
1989
|
+
].join("\n");
|
|
1990
|
+
});
|
|
1991
|
+
ctx.command("ggcevo/装备 <weapon>").action(async ({ session }, weapon) => {
|
|
1992
|
+
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
1993
|
+
if (!profile) return "未绑定句柄";
|
|
1994
|
+
if (!weaponConfig[weapon]) return "无效的武器名称";
|
|
1995
|
+
const config2 = weaponConfig[weapon];
|
|
1996
|
+
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
1997
|
+
const [owned] = await ctx.database.get("ggcevo_equipment", {
|
|
1998
|
+
handle,
|
|
1999
|
+
weaponId: config2.id
|
|
2000
|
+
});
|
|
2001
|
+
if (!owned) return "尚未获得该武器";
|
|
2002
|
+
await ctx.database.withTransaction(async () => {
|
|
2003
|
+
await ctx.database.set(
|
|
2004
|
+
"ggcevo_equipment",
|
|
2005
|
+
{
|
|
2006
|
+
handle,
|
|
2007
|
+
weaponId: { $ne: config2.id }
|
|
2008
|
+
// 排除当前武器
|
|
2009
|
+
},
|
|
2010
|
+
{ equipped: false }
|
|
2011
|
+
);
|
|
2012
|
+
await ctx.database.upsert("ggcevo_equipment", [{
|
|
2013
|
+
handle,
|
|
2014
|
+
weaponId: config2.id,
|
|
2015
|
+
equipped: true
|
|
2016
|
+
}], ["handle", "weaponId"]);
|
|
2017
|
+
});
|
|
2018
|
+
return `已装备 ${weapon}!`;
|
|
2019
|
+
});
|
|
2020
|
+
ctx.command("ggcevo/升级 <weapon>", "升级武器伤害").action(async ({ session }, weapon) => {
|
|
2021
|
+
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
2022
|
+
if (!profile) return "未绑定句柄";
|
|
2023
|
+
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
2024
|
+
const [signInfo] = await ctx.database.get("ggcevo_sign", { handle });
|
|
2025
|
+
const [equipment] = await ctx.database.get("ggcevo_equipment", {
|
|
2026
|
+
handle,
|
|
2027
|
+
weaponId: weaponConfig[weapon]?.id
|
|
2028
|
+
});
|
|
2029
|
+
if (!equipment) return "尚未获得该武器";
|
|
2030
|
+
if (equipment.level >= 6) return "该武器已达最大升级等级";
|
|
2031
|
+
const upgradeCost = [1050, 1450, 1850, 2250, 2650, 3050][equipment.level];
|
|
2032
|
+
if ((signInfo?.totalRewards || 0) < upgradeCost)
|
|
2033
|
+
return `需要${upgradeCost}金币,当前持有:${signInfo?.totalRewards || 0}`;
|
|
2034
|
+
await ctx.database.set("ggcevo_equipment", {
|
|
2035
|
+
handle,
|
|
2036
|
+
weaponId: weaponConfig[weapon].id
|
|
2037
|
+
}, {
|
|
2038
|
+
level: equipment.level + 1,
|
|
2039
|
+
modificationSlots: Math.floor((equipment.level + 1) / 3) + 1
|
|
2040
|
+
});
|
|
2041
|
+
await ctx.database.set("ggcevo_sign", { handle }, {
|
|
2042
|
+
totalRewards: signInfo.totalRewards - upgradeCost
|
|
2043
|
+
});
|
|
2044
|
+
const baseDamage = weaponConfig[weapon].damage * (1 + 0.1 * (equipment.level + 1));
|
|
2045
|
+
return `${weapon} 升级成功!当前等级:${equipment.level + 1},伤害:${baseDamage}`;
|
|
2046
|
+
});
|
|
2047
|
+
ctx.command("ggcevo/改装 <weapon> <mod>", "安装武器改装件").action(async ({ session }, weapon, mod) => {
|
|
2048
|
+
if (!modConfig[mod]) return "可用改装:动能增幅(1250)、棱镜水晶(1750)";
|
|
2049
|
+
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
2050
|
+
if (!profile) return "未绑定游戏账号";
|
|
2051
|
+
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
2052
|
+
const [signInfo] = await ctx.database.get("ggcevo_sign", { handle });
|
|
2053
|
+
const [equipment] = await ctx.database.get("ggcevo_equipment", {
|
|
2054
|
+
handle,
|
|
2055
|
+
weaponId: weaponConfig[weapon]?.id
|
|
2056
|
+
});
|
|
2057
|
+
if (!equipment) return "尚未获得该武器";
|
|
2058
|
+
if (equipment.installedMods.length >= equipment.modificationSlots)
|
|
2059
|
+
return "改装槽已满,请先升级武器";
|
|
2060
|
+
if (equipment.installedMods.includes(mod))
|
|
2061
|
+
return "已安装相同改装件";
|
|
2062
|
+
if ((signInfo?.totalRewards || 0) < modConfig[mod].cost)
|
|
2063
|
+
return `需要${modConfig[mod].cost}金币,当前持有:${signInfo?.totalRewards || 0}`;
|
|
2064
|
+
await ctx.database.set("ggcevo_equipment", {
|
|
2065
|
+
handle,
|
|
2066
|
+
weaponId: weaponConfig[weapon].id
|
|
2067
|
+
}, {
|
|
2068
|
+
installedMods: [...equipment.installedMods, mod]
|
|
2069
|
+
});
|
|
2070
|
+
await ctx.database.set("ggcevo_sign", { handle }, {
|
|
2071
|
+
totalRewards: signInfo.totalRewards - modConfig[mod].cost
|
|
2072
|
+
});
|
|
2073
|
+
const installedModsWithDesc = [...equipment.installedMods, mod].map(
|
|
2074
|
+
(m) => modConfig[m].description
|
|
2075
|
+
);
|
|
2076
|
+
return `${weapon} 成功安装 ${modConfig[mod].description}!当前改装:${installedModsWithDesc.join(" | ")}`;
|
|
2077
|
+
});
|
|
2078
|
+
ctx.command("ggcevo/攻击 <targetType>").usage("使用 攻击 主宰/zz 或 攻击 子代/zd 来选择攻击目标").action(async (argv, targetType) => {
|
|
2079
|
+
const session = argv.session;
|
|
2080
|
+
const targetAliases = {
|
|
2081
|
+
"主宰": ["主宰", "zz"],
|
|
2082
|
+
"子代": ["子代", "zd"]
|
|
2083
|
+
};
|
|
2084
|
+
let normalizedTarget;
|
|
2085
|
+
for (const [key, aliases] of Object.entries(targetAliases)) {
|
|
2086
|
+
if (aliases.includes(targetType)) {
|
|
2087
|
+
normalizedTarget = key;
|
|
2088
|
+
break;
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
if (!normalizedTarget) return "请指定正确的攻击目标:主宰/zz 或 子代/zd";
|
|
2092
|
+
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
2093
|
+
if (!profile) return "您的 QQ 未绑定句柄。";
|
|
2094
|
+
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
2095
|
+
const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
|
|
2096
|
+
if (existingEntries.length > 0) return "❌拒绝访问,您已被列入活动黑名单。";
|
|
2097
|
+
const lastAttack = await ctx.database.get("ggcevo_boss_damage", { handle });
|
|
2098
|
+
if (lastAttack.length > 0) {
|
|
2099
|
+
const lastDate = convertUTCtoChinaTime(new Date(lastAttack[0].lastattackDate));
|
|
2100
|
+
const today = convertUTCtoChinaTime(/* @__PURE__ */ new Date());
|
|
2101
|
+
if (isSameDate(lastDate, today)) {
|
|
2102
|
+
return "今天已经攻击过BOSS了,请明天再来挑战!";
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
const [equippedWeapon] = await ctx.database.get("ggcevo_equipment", {
|
|
2106
|
+
handle,
|
|
2107
|
+
equipped: true
|
|
2108
|
+
});
|
|
2109
|
+
if (!equippedWeapon) return "请先装备武器再挑战主宰";
|
|
2110
|
+
const activeBosses = await ctx.database.get("ggcevo_boss", { isActive: true });
|
|
2111
|
+
if (!activeBosses.length) return "当前没有激活的主宰";
|
|
2112
|
+
const targetBoss = normalizedTarget === "主宰" ? activeBosses.find((b) => b.type === "主宰") : activeBosses.find((b) => b.type === "子代");
|
|
2113
|
+
if (!targetBoss) return `当前没有可攻击的${normalizedTarget === "主宰" ? "主宰" : "子代"}`;
|
|
2114
|
+
const bossGroup = bossPool.find((group) => group.main.id === targetBoss.groupId);
|
|
2115
|
+
if (!bossGroup) return "无法获取BOSS组信息,请联系管理员";
|
|
2116
|
+
const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
|
|
2117
|
+
const [weaponName, weaponData] = weaponConfigEntry;
|
|
2118
|
+
let damage = weaponData.damage * (1 + 0.1 * equippedWeapon.level);
|
|
2119
|
+
equippedWeapon.installedMods.forEach((mod) => {
|
|
2120
|
+
if (mod === "动能增幅") damage *= 1.2;
|
|
2121
|
+
if (mod === "棱镜水晶" && Math.random() < 0.2) damage *= 2;
|
|
2122
|
+
});
|
|
2123
|
+
let tagMultiplier;
|
|
2124
|
+
const targetBossConfig = targetBoss.type === "主宰" ? bossGroup.main : bossGroup.minions[0];
|
|
2125
|
+
if (targetBossConfig.tags && targetBossConfig.tags.length > 0) {
|
|
2126
|
+
const armorTags = targetBossConfig.tags.filter((tag) => ["重甲", "轻甲", "护盾"].includes(tag));
|
|
2127
|
+
const voidTags = targetBossConfig.tags.filter((tag) => ["水货"].includes(tag));
|
|
2128
|
+
const typeTags = targetBossConfig.tags.filter((tag) => ["生物", "机械"].includes(tag));
|
|
2129
|
+
let armorMultiplier = 1;
|
|
2130
|
+
let voidMultiplier = 1;
|
|
2131
|
+
let typeMultiplier = 1;
|
|
2132
|
+
armorTags.forEach((tag) => {
|
|
2133
|
+
const effectValue = weaponData.tagEffects && weaponData.tagEffects[tag] !== void 0 ? weaponData.tagEffects[tag] : 1;
|
|
2134
|
+
armorMultiplier *= effectValue;
|
|
2135
|
+
});
|
|
2136
|
+
voidTags.forEach((tag) => {
|
|
2137
|
+
const effectValue = weaponData.tagEffects && weaponData.tagEffects[tag] !== void 0 ? weaponData.tagEffects[tag] : 1;
|
|
2138
|
+
voidMultiplier *= effectValue;
|
|
2139
|
+
});
|
|
2140
|
+
typeTags.forEach((tag) => {
|
|
2141
|
+
const effectValue = weaponData.tagEffects && weaponData.tagEffects[tag] !== void 0 ? weaponData.tagEffects[tag] : 1;
|
|
2142
|
+
typeMultiplier *= effectValue;
|
|
2143
|
+
});
|
|
2144
|
+
tagMultiplier = armorMultiplier * voidMultiplier * typeMultiplier;
|
|
2145
|
+
damage *= tagMultiplier;
|
|
2146
|
+
}
|
|
2147
|
+
const [rankRecord] = await ctx.database.get("ggcevo_rank", { handle });
|
|
2148
|
+
if (rankRecord?.rank > 0) {
|
|
2149
|
+
const rankBonus = Math.floor(rankRecord.rank / 400) * 0.01;
|
|
2150
|
+
damage *= 1 + rankBonus;
|
|
2151
|
+
}
|
|
2152
|
+
if (targetBoss.type === "主宰") {
|
|
2153
|
+
const activeMinions = await ctx.database.get("ggcevo_boss", {
|
|
2154
|
+
groupId: targetBoss.groupId,
|
|
2155
|
+
type: "子代",
|
|
2156
|
+
isActive: true
|
|
2157
|
+
});
|
|
2158
|
+
if (activeMinions.length === 0) {
|
|
2159
|
+
damage *= 1.2;
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
damage = Math.round(damage);
|
|
2163
|
+
const updatedHP = targetBoss.HP - damage;
|
|
2164
|
+
const isDefeated = updatedHP <= 0;
|
|
2165
|
+
const [existingRecord] = await ctx.database.get("ggcevo_boss_damage", {
|
|
2166
|
+
handle,
|
|
2167
|
+
bossGroupId: targetBoss.groupId
|
|
2168
|
+
});
|
|
2169
|
+
if (existingRecord) {
|
|
2170
|
+
await ctx.database.set("ggcevo_boss_damage", {
|
|
2171
|
+
handle,
|
|
2172
|
+
bossGroupId: targetBoss.groupId
|
|
2173
|
+
}, {
|
|
2174
|
+
totalDamage: existingRecord.totalDamage + damage,
|
|
2175
|
+
attackCount: existingRecord.attackCount + 1,
|
|
2176
|
+
lastattackDate: /* @__PURE__ */ new Date()
|
|
2177
|
+
});
|
|
2178
|
+
} else {
|
|
2179
|
+
await ctx.database.create("ggcevo_boss_damage", {
|
|
2180
|
+
handle,
|
|
2181
|
+
playerName: session.username,
|
|
2182
|
+
bossGroupId: targetBoss.groupId,
|
|
2183
|
+
totalDamage: damage,
|
|
2184
|
+
attackCount: 1,
|
|
2185
|
+
lastattackDate: /* @__PURE__ */ new Date()
|
|
2186
|
+
});
|
|
2187
|
+
}
|
|
2188
|
+
if (isDefeated) {
|
|
2189
|
+
if (targetBoss.type === "主宰") {
|
|
2190
|
+
await ctx.database.set(
|
|
2191
|
+
"ggcevo_boss",
|
|
2192
|
+
{ groupId: targetBoss.groupId },
|
|
2193
|
+
{
|
|
2194
|
+
isActive: false,
|
|
2195
|
+
HP: 0
|
|
2196
|
+
}
|
|
2197
|
+
);
|
|
2198
|
+
const respawnTime = /* @__PURE__ */ new Date();
|
|
2199
|
+
respawnTime.setSeconds(respawnTime.getSeconds() + 3600);
|
|
2200
|
+
await ctx.database.set(
|
|
2201
|
+
"ggcevo_boss",
|
|
2202
|
+
{ name: targetBoss.name },
|
|
2203
|
+
{ respawnTime }
|
|
2204
|
+
);
|
|
2205
|
+
const damageRecords = await ctx.database.select("ggcevo_boss_damage").where({ bossGroupId: targetBoss.groupId }).orderBy("totalDamage", "desc").execute();
|
|
2206
|
+
const rewardMessages = [];
|
|
2207
|
+
const updatePromises = [];
|
|
2208
|
+
const rewardMap = /* @__PURE__ */ new Map();
|
|
2209
|
+
if (damageRecords.length > 0) {
|
|
2210
|
+
const top20 = damageRecords.slice(0, 20);
|
|
2211
|
+
top20.forEach((record, index) => {
|
|
2212
|
+
const rank = index + 1;
|
|
2213
|
+
let guguCoins, gold;
|
|
2214
|
+
if (rank === 1) {
|
|
2215
|
+
guguCoins = 10;
|
|
2216
|
+
gold = 150;
|
|
2217
|
+
} else if (rank === 2) {
|
|
2218
|
+
guguCoins = 9;
|
|
2219
|
+
gold = 120;
|
|
2220
|
+
} else if (rank === 3) {
|
|
2221
|
+
guguCoins = 8;
|
|
2222
|
+
gold = 100;
|
|
2223
|
+
} else if (rank <= 10) {
|
|
2224
|
+
guguCoins = 5;
|
|
2225
|
+
gold = 70;
|
|
2226
|
+
} else {
|
|
2227
|
+
guguCoins = 3;
|
|
2228
|
+
gold = 50;
|
|
2229
|
+
}
|
|
2230
|
+
const key = record.handle;
|
|
2231
|
+
rewardMap.set(key, {
|
|
2232
|
+
guguCoins: (rewardMap.get(key)?.guguCoins || 0) + guguCoins,
|
|
2233
|
+
gold: (rewardMap.get(key)?.gold || 0) + gold,
|
|
2234
|
+
playerName: record.playerName
|
|
2235
|
+
});
|
|
2236
|
+
rewardMessages.push(
|
|
2237
|
+
`${rank}. ${record.playerName}`,
|
|
2238
|
+
` 获得奖励: ${guguCoins} 咕咕币 + ${gold} 金币`
|
|
2239
|
+
);
|
|
2240
|
+
});
|
|
2241
|
+
const others = damageRecords.slice(20);
|
|
2242
|
+
if (others.length > 0) {
|
|
2243
|
+
others.forEach((record) => {
|
|
2244
|
+
const key = record.handle;
|
|
2245
|
+
rewardMap.set(key, {
|
|
2246
|
+
guguCoins: (rewardMap.get(key)?.guguCoins || 0) + 3,
|
|
2247
|
+
gold: (rewardMap.get(key)?.gold || 0) + 50,
|
|
2248
|
+
playerName: record.playerName
|
|
2249
|
+
});
|
|
2250
|
+
});
|
|
2251
|
+
rewardMessages.push(`其他参与者各获得: 3 咕咕币 + 50 金币`);
|
|
2252
|
+
}
|
|
2253
|
+
for (const [handle2, reward] of rewardMap) {
|
|
2254
|
+
const signPromise = (async () => {
|
|
2255
|
+
const [existingSign2] = await ctx.database.get("ggcevo_sign", { handle: handle2 });
|
|
2256
|
+
if (existingSign2) {
|
|
2257
|
+
await ctx.database.set("ggcevo_sign", { handle: handle2 }, {
|
|
2258
|
+
totalRewards: existingSign2.totalRewards + reward.gold
|
|
2259
|
+
});
|
|
2260
|
+
} else {
|
|
2261
|
+
await ctx.database.create("ggcevo_sign", {
|
|
2262
|
+
handle: handle2,
|
|
2263
|
+
totalRewards: reward.gold
|
|
2264
|
+
});
|
|
2265
|
+
}
|
|
2266
|
+
})();
|
|
2267
|
+
updatePromises.push(signPromise);
|
|
2268
|
+
const backpackPromise = (async () => {
|
|
2269
|
+
const [existingItem] = await ctx.database.get("ggcevo_backpack", {
|
|
2270
|
+
handle: handle2,
|
|
2271
|
+
itemId: 1
|
|
2272
|
+
// 假设1是咕咕币的ID
|
|
2273
|
+
});
|
|
2274
|
+
if (existingItem) {
|
|
2275
|
+
await ctx.database.set("ggcevo_backpack", {
|
|
2276
|
+
handle: handle2,
|
|
2277
|
+
itemId: 1
|
|
2278
|
+
}, {
|
|
2279
|
+
quantity: existingItem.quantity + reward.guguCoins
|
|
2280
|
+
});
|
|
2281
|
+
} else {
|
|
2282
|
+
await ctx.database.create("ggcevo_backpack", {
|
|
2283
|
+
handle: handle2,
|
|
2284
|
+
itemId: 1,
|
|
2285
|
+
quantity: reward.guguCoins
|
|
2286
|
+
});
|
|
2287
|
+
}
|
|
2288
|
+
})();
|
|
2289
|
+
updatePromises.push(backpackPromise);
|
|
2290
|
+
}
|
|
2291
|
+
await Promise.all(updatePromises);
|
|
2292
|
+
}
|
|
2293
|
+
await ctx.database.remove("ggcevo_boss_damage", {
|
|
2294
|
+
bossGroupId: targetBoss.groupId
|
|
2295
|
+
});
|
|
2296
|
+
ctx.broadcast(config.groupId, [
|
|
2297
|
+
`🎯 主宰 ${targetBoss.name} 已被击败!`,
|
|
2298
|
+
`所有子代已消失,下一个主宰将在1小时后出现`,
|
|
2299
|
+
"",
|
|
2300
|
+
"🎁 奖励发放结果:",
|
|
2301
|
+
...rewardMessages
|
|
2302
|
+
].join("\n"));
|
|
2303
|
+
} else {
|
|
2304
|
+
await ctx.database.set(
|
|
2305
|
+
"ggcevo_boss",
|
|
2306
|
+
{ name: targetBoss.name },
|
|
2307
|
+
{
|
|
2308
|
+
isActive: false,
|
|
2309
|
+
HP: 0
|
|
2310
|
+
}
|
|
2311
|
+
);
|
|
2312
|
+
ctx.broadcast(
|
|
2313
|
+
config.groupId,
|
|
2314
|
+
`🎯 子代 ${targetBoss.name} 已被击败!
|
|
2315
|
+
主宰仍然存在,但是将额外遭受20%的易伤,继续战斗!`
|
|
2316
|
+
);
|
|
2317
|
+
}
|
|
2318
|
+
} else {
|
|
2319
|
+
await ctx.database.set(
|
|
2320
|
+
"ggcevo_boss",
|
|
2321
|
+
{ name: targetBoss.name },
|
|
2322
|
+
{ HP: updatedHP }
|
|
2323
|
+
);
|
|
2324
|
+
}
|
|
2325
|
+
const [existingSign] = await ctx.database.get("ggcevo_sign", { handle });
|
|
2326
|
+
if (existingSign) {
|
|
2327
|
+
await ctx.database.set("ggcevo_sign", { handle }, {
|
|
2328
|
+
totalRewards: existingSign.totalRewards + damage
|
|
2329
|
+
});
|
|
2330
|
+
} else {
|
|
2331
|
+
await ctx.database.create("ggcevo_sign", {
|
|
2332
|
+
handle,
|
|
2333
|
+
totalRewards: damage
|
|
2334
|
+
});
|
|
2335
|
+
}
|
|
2336
|
+
return [
|
|
2337
|
+
`🔥 对 ${targetBoss.name} 发起攻击!`,
|
|
2338
|
+
`造成伤害:${damage}`,
|
|
2339
|
+
`目标剩余HP:${isDefeated ? 0 : updatedHP}/${targetBoss.type === "主宰" ? bossGroup.main.maxHP : bossGroup.minions[0].maxHP}`,
|
|
2340
|
+
isDefeated ? `🎉 成功击败 ${targetBoss.name}!` : ""
|
|
2341
|
+
].join("\n");
|
|
2342
|
+
});
|
|
2343
|
+
ctx.command("ggcevo/初始化主宰", "初始化或重置主宰系统", { authority: 3 }).action(async () => {
|
|
2344
|
+
try {
|
|
2345
|
+
await ctx.database.remove("ggcevo_boss", {});
|
|
2346
|
+
await initializeBoss();
|
|
2347
|
+
const activeBosses = await ctx.database.get("ggcevo_boss", { isActive: true });
|
|
2348
|
+
const mainBoss = activeBosses.find((b) => b.type === "主宰");
|
|
2349
|
+
if (!mainBoss) {
|
|
2350
|
+
return "主宰初始化失败,请联系开发者检查系统";
|
|
2351
|
+
}
|
|
2352
|
+
return `✅ 主宰系统已成功初始化!当前主宰: ${mainBoss.name}`;
|
|
2353
|
+
} catch (error) {
|
|
2354
|
+
console.error("主宰初始化失败:", error);
|
|
2355
|
+
return "❌ 主宰初始化失败,请稍后重试";
|
|
2356
|
+
}
|
|
2357
|
+
});
|
|
2358
|
+
ctx.command("ggcevo/伤害榜 [page]", "查看当前主宰伤害排名").usage("输入 伤害榜 [页码] 查看对应页的排行榜,每页10条").action(async (_, page) => {
|
|
2359
|
+
const pageNum = parseInt(page) || 1;
|
|
2360
|
+
if (pageNum < 1) return "请输入有效的页码。";
|
|
2361
|
+
const activeBosses = await ctx.database.get("ggcevo_boss", { isActive: true });
|
|
2362
|
+
if (!activeBosses.length) return "当前没有激活的BOSS";
|
|
2363
|
+
const mainBoss = activeBosses.find((b) => b.type === "主宰");
|
|
2364
|
+
if (!mainBoss) return "当前BOSS数据异常";
|
|
2365
|
+
const offset = (pageNum - 1) * 10;
|
|
2366
|
+
const [records, total] = await Promise.all([
|
|
2367
|
+
// 获取当前页记录
|
|
2368
|
+
ctx.database.select("ggcevo_boss_damage").where({ bossGroupId: mainBoss.groupId }).orderBy("totalDamage", "desc").limit(10).offset(offset).execute(),
|
|
2369
|
+
// 获取总记录数
|
|
2370
|
+
ctx.database.select("ggcevo_boss_damage").where({ bossGroupId: mainBoss.groupId }).execute((row) => import_koishi.$.count(row.handle))
|
|
2371
|
+
]);
|
|
2372
|
+
const totalPages = Math.ceil(total / 10);
|
|
2373
|
+
if (pageNum > totalPages) return `最多有 ${totalPages} 页`;
|
|
2374
|
+
if (!records.length) return "暂无伤害记录";
|
|
2375
|
+
const rankingText = records.map(
|
|
2376
|
+
(record, index) => `${offset + index + 1}. ${record.playerName || "未知玩家"} | 总伤害: ${record.totalDamage} | 攻击次数: ${record.attackCount}`
|
|
2377
|
+
).join("\n");
|
|
2378
|
+
return [
|
|
2379
|
+
`🏆 当前主宰伤害榜 (${mainBoss.name})`,
|
|
2380
|
+
"────────────────",
|
|
2381
|
+
rankingText,
|
|
2382
|
+
"────────────────",
|
|
2383
|
+
`第 ${pageNum} 页 / 共 ${totalPages} 页`,
|
|
2384
|
+
pageNum < totalPages ? `输入 伤害榜 ${pageNum + 1} 查看下一页` : "已是最后一页"
|
|
2385
|
+
].join("\n");
|
|
2386
|
+
});
|
|
2387
|
+
ctx.command("ggcevo/主宰状态", "查看当前主宰信息").alias("zz状态").action(async () => {
|
|
2388
|
+
const activeBosses = await ctx.database.get("ggcevo_boss", { isActive: true });
|
|
2389
|
+
if (!activeBosses.length) return "当前没有激活的BOSS";
|
|
2390
|
+
const mainBoss = activeBosses.find((b) => b.type === "主宰");
|
|
2391
|
+
const minions = activeBosses.filter((b) => b.type === "子代");
|
|
2392
|
+
if (!mainBoss) return "当前BOSS数据异常,请联系管理员";
|
|
2393
|
+
const bossGroup = bossPool.find((group) => group.main.name === mainBoss.name);
|
|
2394
|
+
if (!bossGroup) return "BOSS配置数据异常,请联系管理员";
|
|
2395
|
+
const mainBossHpBar = createHpBar(mainBoss.HP, bossGroup.main.maxHP);
|
|
2396
|
+
const result = [
|
|
2397
|
+
`🔴 主宰:${mainBoss.name}`,
|
|
2398
|
+
`${mainBossHpBar} (${mainBoss.HP}/${bossGroup.main.maxHP})`,
|
|
2399
|
+
`标签:${bossGroup.main.tags.join("、")}`
|
|
2400
|
+
];
|
|
2401
|
+
if (minions.length > 0) {
|
|
2402
|
+
result.push("", "🟠 子代信息:");
|
|
2403
|
+
minions.forEach((minion) => {
|
|
2404
|
+
const minionConfig = bossGroup.minions.find((m) => m.name === minion.name);
|
|
2405
|
+
if (minionConfig) {
|
|
2406
|
+
const minionHpBar = createHpBar(minion.HP, minionConfig.maxHP);
|
|
2407
|
+
result.push(
|
|
2408
|
+
`${minion.name}`,
|
|
2409
|
+
`${minionHpBar} (${minion.HP}/${minionConfig.maxHP})`,
|
|
2410
|
+
`标签:${minionConfig.tags.join("、")}`
|
|
2411
|
+
);
|
|
2412
|
+
}
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2415
|
+
return result.join("\n");
|
|
2416
|
+
});
|
|
1753
2417
|
}
|
|
1754
2418
|
__name(apply, "apply");
|
|
1755
2419
|
function simpleDraw() {
|