koishi-plugin-xxck-1 0.3.4 → 0.3.6

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
@@ -11,6 +11,7 @@ export interface PluginConfig {
11
11
  eventExchangePrice7: number;
12
12
  collectionPart1Pattern: string;
13
13
  collectionPart2Pattern: string;
14
+ disturbExchangePrice: number;
14
15
  normalStar7Threshold: number;
15
16
  normalStar6Threshold: number;
16
17
  normalStar6Prob: number;
@@ -27,6 +28,7 @@ export declare const Config: Schema<Schemastery.ObjectS<{
27
28
  eventExchangePrice7: Schema<number, number>;
28
29
  collectionPart1Pattern: Schema<string, string>;
29
30
  collectionPart2Pattern: Schema<string, string>;
31
+ disturbExchangePrice: Schema<number, number>;
30
32
  normalStar7Threshold: Schema<number, number>;
31
33
  normalStar6Threshold: Schema<number, number>;
32
34
  normalStar6Prob: Schema<number, number>;
@@ -42,6 +44,7 @@ export declare const Config: Schema<Schemastery.ObjectS<{
42
44
  eventExchangePrice7: Schema<number, number>;
43
45
  collectionPart1Pattern: Schema<string, string>;
44
46
  collectionPart2Pattern: Schema<string, string>;
47
+ disturbExchangePrice: Schema<number, number>;
45
48
  normalStar7Threshold: Schema<number, number>;
46
49
  normalStar6Threshold: Schema<number, number>;
47
50
  normalStar6Prob: Schema<number, number>;
@@ -144,6 +147,10 @@ declare module 'koishi' {
144
147
  got6: boolean;
145
148
  got7: boolean;
146
149
  };
150
+ gacha_user_disturb_draw: {
151
+ qq: string;
152
+ draw_count: number;
153
+ };
147
154
  gacha_battle_user: {
148
155
  qq: string;
149
156
  win: number;
package/lib/index.js CHANGED
@@ -40,14 +40,16 @@ var zh_CN_default = {
40
40
  "command.wwc.help.sign": "签到:每日领取抽数 | 指令:WWC签到 | 说明:每日1次,获得40抽",
41
41
  "command.wwc.help.draw": "抽卡:普通抽卡 | 指令:WWC抽卡 [次数] | 说明:1-20连,消耗普通抽数,默认1连",
42
42
  "command.wwc.help.warehouse": "仓库:查看已拥有卡片 | 指令:WWC仓库 | 说明:显示等级/星级/限定标记,按星级排序",
43
- "command.wwc.help.shop": "店铺:查看今日可升格卡片 | 指令:WWC店铺 | 说明:每日随机刷新3个7星卡,全服限购",
43
+ "command.wwc.help.shop": "店铺:查看今日可升格卡片 | 指令:WWC店铺 | 说明:每日随机刷新4个7星、6个6星、10个5星(均来自普通卡池),全服限购5次",
44
44
  "command.wwc.help.upgrade": "升格:兑换店铺卡片 | 指令:WWC升格 [卡片编号...] | 说明:消耗热带扰动,重复卡片自动升级",
45
45
  "command.wwc.help.exchange": "兑换:水汽换普通抽数 | 指令:WWC兑换 [次数] | 说明:100水汽=1抽,每日上限80抽,单次1-40",
46
46
  "command.wwc.help.collection": "收藏:查看卡片收藏进度 | 指令:WWC收藏(全部分类);WWC收藏1 / WWC收藏2 / WWC收藏3 为拆分版(分类正则可在插件配置项 collectionPart1Pattern / collectionPart2Pattern 中定义,收藏3 = 两者都不匹配的类别)| 说明:含普通+限定卡",
47
- "command.wwc.help.ranking": "排名:查看全服收藏排行 | 指令:WWC排名1/WWC排行1 | 说明:显示前20名+自身排名,按收藏数排序",
47
+ "command.wwc.help.ranking": "排名:查看全服排行 | 指令:WWC排名1(按收藏数);WWC排名2(按7/6星战力分:7星0级20分每级+15,普通6星0级5分每级+3,限时6星0级8分每级+6)| 说明:显示前20名+自身排名",
48
48
  "command.wwc.help.eventStatus": "限时状态:查看开放的限时卡池 | 指令:WWC限时状态 | 说明:显示期数/名称/星级/开放时间",
49
49
  "command.wwc.help.eventDraw": "限时抽卡:参与限时卡池 | 指令:WWC限时抽卡 [期数] [次数] | 说明:1-20连,消耗限时抽数,无期限数匹配唯一开放池",
50
50
  "command.wwc.help.eventExchange": "限时兑换:水汽换限时抽数 | 指令:WWC限时兑换 [期数] [次数] | 说明:6星300水汽/抽,7星450水汽/抽,单次1-40",
51
+ "command.wwc.help.disturbDraw": "扰动抽卡:使用扰动抽数抽卡 | 指令:WWC扰动抽卡 [次数] | 说明:普通卡池5/6/7星,7星10%、6星36%、5星54%,单次1-20连",
52
+ "command.wwc.help.disturbExchange": "扰动兑换:热带扰动换扰动抽数 | 指令:WWC扰动兑换 [次数] | 说明:每抽消耗扰动由配置项决定(默认100),单次1-40",
51
53
  "command.wwc.help.tip": "💡 提示:所有指令前缀为「WWC」,区分大小写;抽卡/兑换次数超出限制会自动兜底为1次",
52
54
  // ==============================================
53
55
  // 2. 功能操作成功提示
@@ -64,6 +66,8 @@ var zh_CN_default = {
64
66
  "tip.switch.groupClose": "❌ 本群WWC抽卡功能已关闭!群成员无法使用任何指令",
65
67
  "tip.eventAdd.success": "✅ 限时卡池创建成功:{code} | 请检查时间戳是否正确",
66
68
  "tip.eventExchange.success": "✅ 限时兑换成功\n卡池:{code} | 数量:{count}抽 | 消耗:{cost}水汽",
69
+ "tip.disturbExchange.success": "✅ 扰动兑换成功\n数量:{count}抽 | 消耗:{cost}热带扰动 | 当前扰动抽数:{left}抽",
70
+ "tip.disturbDraw.title": "🎲 [{name}] 扰动抽卡完成(剩余扰动抽数:{left}抽)!获得以下卡片:",
67
71
  "tip.eventStatus.info": "📅 限时卡池【{code}】\n卡片:{cardName}({star}星)\n类型:{type}\n开放时间:{start} ~ {end}",
68
72
  "tip.upgrade.success": "✅ 升格成功!恭喜您获得了以下卡片:\n",
69
73
  "tip.upgrade.cost": "💸 消耗扰动:-{total_cost}",
@@ -111,6 +115,8 @@ var zh_CN_default = {
111
115
  "error.eventDraw.count.notEnough": "❌ {star}星限时抽数不足:\n当前{have}抽/需要{need}抽\n可使用WWC限时兑换获取",
112
116
  "error.eventDraw.param.invalid": "❌ 抽卡参数无效,请传入期数和次数",
113
117
  "error.eventExchange.pool.none": "❌ 该期数限时卡池未开放或不存在!\n请使用WWC限时状态查看",
118
+ "error.disturbExchange.disturb.notEnough": "❌ 热带扰动不足!\n本次兑换需要:{need}扰动 | 当前拥有:{have}扰动",
119
+ "error.disturbDraw.count.notEnough": "❌ 扰动抽数不足!\n当前剩余:{have} 次 | 需要:{need} 次(可使用 WWC扰动兑换 兑换)",
114
120
  "error.switch.private": "❌ 私信场景无需设置群开关!该指令仅可在群聊中使用",
115
121
  "error.switch.fail": "❌ 开关操作失败!{msg}",
116
122
  "error.shop.no7starCard": "❌ 店铺生成失败!普通卡池中无7星卡片,请联系主人录入",
@@ -154,6 +160,9 @@ var zh_CN_default = {
154
160
  "image.ranking.header.player": "玩家",
155
161
  "image.ranking.header.count": "收藏数量",
156
162
  "image.ranking.mine": "你的排名:第{rank}名 | 收藏卡片:{count}张",
163
+ "image.ranking2.title": "WWC全服7/6星战力排行榜(前20名)",
164
+ "image.ranking2.header.score": "综合得分",
165
+ "image.ranking2.mine": "你的排名:第{rank}名 | 综合得分:{score}分",
157
166
  // ==============================================
158
167
  // 6. 系统日志/通知(主人私信)
159
168
  // ==============================================
@@ -177,6 +186,7 @@ var Config = import_koishi.Schema.object({
177
186
  eventExchangePrice7: import_koishi.Schema.number().description("限时卡池7星兑换每抽消耗的水汽量(默认450)").default(450).min(1).max(1e4),
178
187
  collectionPart1Pattern: import_koishi.Schema.string().description('WWC收藏1的分类正则:类别名匹配此正则的归入收藏图1(默认匹配"纯数字且≥2000")').default("^([2-9]\\d{3}|\\d{5,})$").role("textarea"),
179
188
  collectionPart2Pattern: import_koishi.Schema.string().description('WWC收藏2的分类正则:类别名匹配此正则的归入收藏图2(默认匹配"纯数字且<2000");两个正则都不匹配的类别归入WWC收藏3').default("^(\\d{1,3}|1\\d{3})$").role("textarea"),
189
+ disturbExchangePrice: import_koishi.Schema.number().description("扰动兑换:每抽扰动抽数消耗的热带扰动量(默认100)").default(100).min(1).max(1e5),
180
190
  normalStar7Threshold: import_koishi.Schema.number().description("普通卡池7星保底抽数(默认1500)").default(1500).min(1).max(1e4),
181
191
  normalStar6Threshold: import_koishi.Schema.number().description("普通卡池6星保底抽数(默认300)").default(300).min(1).max(1e4),
182
192
  normalStar6Prob: import_koishi.Schema.number().description("普通卡池6星保底抽出6星概率百分比(减去为抽出7星概率)").default(90).min(0).max(100),
@@ -339,8 +349,12 @@ async function _shop_draw_image(ctx, session, userName, date, disturbance, vapor
339
349
  const BASE_X = 40;
340
350
  const BASE_Y = 30;
341
351
  const CANVAS_WIDTH = 900;
342
- const CANVAS_HEIGHT = 1100;
343
352
  const CARD_ITEM_HEIGHT = 85;
353
+ const FIRST_CARD_Y = BASE_Y + 235;
354
+ const CANVAS_HEIGHT = Math.max(
355
+ 1100,
356
+ FIRST_CARD_Y + Math.max(0, (shopCards?.length ?? 0) - 1) * CARD_ITEM_HEIGHT + 70
357
+ );
344
358
  const FONT_FAMILY = "Microsoft YaHei, SimHei, 黑体, 宋体, sans-serif";
345
359
  const canvas = ctx.canvas.createCanvas(CANVAS_WIDTH, CANVAS_HEIGHT);
346
360
  const ctx2d = canvas.getContext("2d");
@@ -1284,20 +1298,24 @@ async function _do_shop(ctx, session, signResetHour, signResetMinute) {
1284
1298
  const today = `${todayDate.getFullYear()}${String(todayDate.getMonth() + 1).padStart(2, "0")}${String(todayDate.getDate()).padStart(2, "0")}`;
1285
1299
  let todayShop = await ctx.database.get("gacha_shop_daily", { shop_date: today });
1286
1300
  if (todayShop.length === 0) {
1287
- const [sevenStarCards, sixStarCards] = await Promise.all([
1301
+ const [sevenStarCards, sixStarCards, fiveStarCards] = await Promise.all([
1288
1302
  ctx.database.get("gacha_card_pool", { card_star: 7 }),
1289
- ctx.database.get("gacha_card_pool", { card_star: 6 })
1303
+ ctx.database.get("gacha_card_pool", { card_star: 6 }),
1304
+ ctx.database.get("gacha_card_pool", { card_star: 5 })
1290
1305
  ]);
1291
- if (sevenStarCards.length < 4 || sixStarCards.length < 6) {
1306
+ if (sevenStarCards.length < 4 || sixStarCards.length < 6 || fiveStarCards.length < 10) {
1292
1307
  return await session.send(import_koishi.h.text(session.text("error.shop.cardNotEnough")));
1293
1308
  }
1294
1309
  const selected7 = sevenStarCards.sort(() => Math.random() - 0.5).slice(0, 4);
1295
1310
  const selected6 = sixStarCards.sort(() => Math.random() - 0.5).slice(0, 6);
1296
- const allCards = [...selected7, ...selected6];
1311
+ const selected5 = fiveStarCards.sort(() => Math.random() - 0.5).slice(0, 10);
1312
+ const allCards = [...selected7, ...selected6, ...selected5];
1313
+ const SHOP_PRICE_BASE = { 7: 800, 6: 200, 5: 20 };
1314
+ const SHOP_PRICE_RANGE = { 7: 80, 6: 30, 5: 0 };
1297
1315
  for (const card of allCards) {
1298
- const basePrice = card.card_star === 7 ? 800 : 200;
1299
- const range = card.card_star === 7 ? 80 : 30;
1300
- const randomPrice = basePrice + Math.floor(Math.random() * (range * 2 + 1)) - range;
1316
+ const basePrice = SHOP_PRICE_BASE[card.card_star] ?? 10;
1317
+ const range = SHOP_PRICE_RANGE[card.card_star] ?? 0;
1318
+ const randomPrice = range > 0 ? basePrice + Math.floor(Math.random() * (range * 2 + 1)) - range : basePrice;
1301
1319
  const nextId = await getNextId(ctx, "gacha_shop_daily");
1302
1320
  await ctx.database.create("gacha_shop_daily", {
1303
1321
  id: nextId,
@@ -1339,6 +1357,7 @@ async function _do_shop(ctx, session, signResetHour, signResetMinute) {
1339
1357
  leftLimit: limitMap.get(item.card_id)
1340
1358
  };
1341
1359
  });
1360
+ shopCardList.sort((a, b) => b.star - a.star || String(a.id).localeCompare(String(b.id)));
1342
1361
  const userAsset = await ctx.database.get("gacha_user_draw_count", { qq });
1343
1362
  const dist = userAsset[0]?.tropical_disturbance ?? 0;
1344
1363
  const vapor = userAsset[0]?.water_vapor ?? 0;
@@ -1429,6 +1448,97 @@ async function _do_ranking(ctx, session) {
1429
1448
  }
1430
1449
  }
1431
1450
  __name(_do_ranking, "_do_ranking");
1451
+ async function _do_ranking2(ctx, session) {
1452
+ ctx.logger.info("WWC排名2 开始执行");
1453
+ try {
1454
+ const qq = await getUnifiedQQ(ctx, session);
1455
+ const user = await ctx.database.get("gacha_user", { qq });
1456
+ if (!user.length) {
1457
+ await session.send(build_msg(session, session.text("error.common.notRegister")));
1458
+ return;
1459
+ }
1460
+ const show_name = user[0].status === 1 ? user[0].nickname : qq;
1461
+ const [normalPoolCards, eventPoolCards] = await Promise.all([
1462
+ ctx.database.get("gacha_card_pool", {}, { fields: ["card_id", "card_star"] }),
1463
+ ctx.database.get("gacha_event_pool", {}, { fields: ["card_id", "card_star"] })
1464
+ ]);
1465
+ const poolInfo = /* @__PURE__ */ new Map();
1466
+ normalPoolCards.forEach((c) => {
1467
+ if (!poolInfo.has(c.card_id)) poolInfo.set(c.card_id, { star: c.card_star, isLimit: false });
1468
+ });
1469
+ eventPoolCards.forEach((c) => {
1470
+ if (!poolInfo.has(c.card_id)) poolInfo.set(c.card_id, { star: c.card_star, isLimit: true });
1471
+ });
1472
+ const all_users = await ctx.database.get("gacha_user", {});
1473
+ const ranking_data = [];
1474
+ for (const u of all_users) {
1475
+ try {
1476
+ const cards = await ctx.database.get("gacha_user_card", { qq: u.qq }, { fields: ["card_id", "card_level"] });
1477
+ const levelMap = /* @__PURE__ */ new Map();
1478
+ cards.forEach((c) => {
1479
+ const lv = c.card_level || 0;
1480
+ const prev = levelMap.get(c.card_id);
1481
+ if (prev === void 0 || lv > prev) levelMap.set(c.card_id, lv);
1482
+ });
1483
+ let totalScore = 0;
1484
+ levelMap.forEach((lv, cid) => {
1485
+ const info = poolInfo.get(cid);
1486
+ if (!info) return;
1487
+ if (info.star >= 7) totalScore += 20 + 15 * lv;
1488
+ else if (info.star === 6) totalScore += info.isLimit ? 8 + 6 * lv : 5 + 3 * lv;
1489
+ });
1490
+ ranking_data.push({
1491
+ qq: u.qq,
1492
+ show_name: u.status === 1 ? u.nickname : u.qq,
1493
+ total_score: totalScore
1494
+ });
1495
+ } catch (e) {
1496
+ continue;
1497
+ }
1498
+ }
1499
+ ranking_data.sort((a, b) => b.total_score - a.total_score);
1500
+ const ranking_list = [];
1501
+ let user_rank = 0;
1502
+ let user_score = 0;
1503
+ ranking_data.forEach((item, idx) => {
1504
+ const rank = idx + 1;
1505
+ if (item.qq === qq) {
1506
+ user_rank = rank;
1507
+ user_score = item.total_score;
1508
+ }
1509
+ if (rank <= 20) {
1510
+ ranking_list.push([rank, item.show_name, item.total_score]);
1511
+ }
1512
+ });
1513
+ const titleText = session.text("image.ranking2.title");
1514
+ const headerRankText = session.text("image.ranking.header.rank");
1515
+ const headerPlayerText = session.text("image.ranking.header.player");
1516
+ const headerCountText = session.text("image.ranking2.header.score");
1517
+ const mineText = session.text("image.ranking2.mine", { rank: user_rank, score: user_score });
1518
+ const img_base64 = await _ranking_draw_image(
1519
+ ctx,
1520
+ ranking_list,
1521
+ user_rank,
1522
+ user_score,
1523
+ show_name,
1524
+ titleText,
1525
+ headerRankText,
1526
+ headerPlayerText,
1527
+ headerCountText,
1528
+ mineText
1529
+ );
1530
+ if (img_base64) {
1531
+ await session.send(img_base64);
1532
+ ctx.logger.info("WWC排名2 图片发送成功");
1533
+ } else {
1534
+ await session.send(build_msg(session, session.text("error.common.imageGenerate")));
1535
+ }
1536
+ } catch (e) {
1537
+ ctx.logger.error("WWC排名2 报错:", e);
1538
+ await session.send(build_msg(session, session.text("error.ranking.fail")));
1539
+ }
1540
+ }
1541
+ __name(_do_ranking2, "_do_ranking2");
1432
1542
  async function _do_switch(ctx, session, type, action, masterQQ) {
1433
1543
  const userQQ = await getUnifiedQQ(ctx, session);
1434
1544
  if (userQQ !== masterQQ) {
@@ -1800,6 +1910,128 @@ async function _do_event_draw(ctx, session, data, event6Threshold, event7Thresho
1800
1910
  }
1801
1911
  }
1802
1912
  __name(_do_event_draw, "_do_event_draw");
1913
+ async function _do_disturb_exchange(ctx, session, cnt, price) {
1914
+ const qq = await getUnifiedQQ(ctx, session);
1915
+ const realCnt = Math.min(Math.max(cnt | 0, 1), 40);
1916
+ const user = await ctx.database.get("gacha_user", { qq });
1917
+ if (!user.length) return await session.send(build_msg(session, session.text("error.common.notRegister")));
1918
+ const total = price * realCnt;
1919
+ const asset = await ctx.database.get("gacha_user_draw_count", { qq });
1920
+ const disturb = asset[0]?.tropical_disturbance ?? 0;
1921
+ if (disturb < total) {
1922
+ ctx.logger.warn(`[扰动兑换] 玩家${qq}兑换失败:热带扰动不足(拥有${disturb},需${total})`);
1923
+ return await session.send(build_msg(session, session.text("error.disturbExchange.disturb.notEnough", { need: total, have: disturb })));
1924
+ }
1925
+ await ctx.database.upsert("gacha_user_draw_count", [{ qq, tropical_disturbance: disturb - total }]);
1926
+ const ud = await ctx.database.get("gacha_user_disturb_draw", { qq });
1927
+ const have = ud[0]?.draw_count ?? 0;
1928
+ await ctx.database.upsert("gacha_user_disturb_draw", [{ qq, draw_count: have + realCnt }]);
1929
+ ctx.logger.info(`[扰动兑换] 玩家${qq}兑换成功:获得${realCnt}抽,消耗扰动${total},扰动抽数${have}→${have + realCnt}`);
1930
+ await session.send(build_msg(
1931
+ session,
1932
+ session.text("tip.disturbExchange.success", { count: realCnt, cost: total, left: have + realCnt })
1933
+ ));
1934
+ }
1935
+ __name(_do_disturb_exchange, "_do_disturb_exchange");
1936
+ async function _do_disturb_draw(ctx, session, count) {
1937
+ ctx.logger.info("执行扰动抽卡,次数:", count);
1938
+ const qq = await getUnifiedQQ(ctx, session);
1939
+ const user = await ctx.database.get("gacha_user", { qq });
1940
+ if (!user.length) return await session.send(build_msg(session, session.text("error.common.notRegister")));
1941
+ const showName = user[0].status === 1 ? user[0].nickname : qq;
1942
+ if (!Number.isInteger(count) || count < 1 || count > 20) {
1943
+ return await session.send(build_msg(session, session.text("error.draw.count.invalid")));
1944
+ }
1945
+ const ud = await ctx.database.get("gacha_user_disturb_draw", { qq });
1946
+ const have = ud[0]?.draw_count ?? 0;
1947
+ if (have < count) {
1948
+ return await session.send(build_msg(session, session.text("error.disturbDraw.count.notEnough", {
1949
+ need: count,
1950
+ have
1951
+ })));
1952
+ }
1953
+ const allCards = await ctx.database.get("gacha_card_pool", {});
1954
+ const starCardMap = { 5: [], 6: [], 7: [] };
1955
+ allCards.forEach((card) => {
1956
+ if (starCardMap[card.card_star]) starCardMap[card.card_star].push(card);
1957
+ });
1958
+ const DISTURB_STAR_PROB = { 7: 10, 6: 36, 5: 54 };
1959
+ const weightedPool = [];
1960
+ for (const [star, prob] of Object.entries(DISTURB_STAR_PROB)) {
1961
+ if (!starCardMap[+star]?.length) continue;
1962
+ for (let i = 0; i < prob; i++) weightedPool.push(+star);
1963
+ }
1964
+ if (!weightedPool.length) {
1965
+ return await session.send(build_msg(session, session.text("error.draw.poolEmpty")));
1966
+ }
1967
+ const STAR_TO_DISTURBANCE = { 0: 0, 1: 0, 2: 0, 3: 1, 4: 5, 5: 20, 6: 100, 7: 500 };
1968
+ const INIT_WATER_VAPOR = { 0: 50, 1: 100, 2: 150, 3: 200, 4: 500, 5: 1e3, 6: 2e3, 7: 5e3 };
1969
+ const UPGRADE_WATER_VAPOR = { 0: 25, 1: 50, 2: 75, 3: 100, 4: 200, 5: 500, 6: 1e3, 7: 2e3 };
1970
+ const drawResult = [];
1971
+ let disturbanceTotal = 0;
1972
+ let waterVaporTotal = 0;
1973
+ let isUpgrade = false;
1974
+ for (let i = 0; i < count; i++) {
1975
+ const selectedStar = weightedPool[Math.floor(Math.random() * weightedPool.length)];
1976
+ const cardList = starCardMap[selectedStar];
1977
+ const card = cardList[Math.floor(Math.random() * cardList.length)];
1978
+ drawResult.push({ star: selectedStar, cid: card.card_id, name: card.card_name });
1979
+ const userCard = await ctx.database.get("gacha_user_card", { qq, card_id: card.card_id });
1980
+ if (!userCard.length) {
1981
+ await ctx.database.upsert("gacha_user_card", [{
1982
+ qq,
1983
+ card_id: card.card_id,
1984
+ card_level: 0,
1985
+ obtain_at: Date.now()
1986
+ }]);
1987
+ waterVaporTotal += INIT_WATER_VAPOR[selectedStar];
1988
+ ctx.logger.info(`[扰动抽卡] 新增卡片:${card.card_id} ${card.card_name},等级0`);
1989
+ } else {
1990
+ const currentLevel = userCard[0].card_level;
1991
+ if (currentLevel < CARD_LEVEL_MAX) {
1992
+ await ctx.database.upsert("gacha_user_card", [{
1993
+ id: userCard[0].id,
1994
+ qq,
1995
+ card_id: card.card_id,
1996
+ card_level: currentLevel + 1,
1997
+ obtain_at: Date.now()
1998
+ }]);
1999
+ isUpgrade = true;
2000
+ waterVaporTotal += UPGRADE_WATER_VAPOR[selectedStar];
2001
+ ctx.logger.info(`[扰动抽卡] 卡片升级:${card.card_id},等级${currentLevel}→${currentLevel + 1}`);
2002
+ } else {
2003
+ const d = STAR_TO_DISTURBANCE[selectedStar];
2004
+ if (d > 0) {
2005
+ disturbanceTotal += d;
2006
+ ctx.logger.info(`[扰动抽卡] 卡片满级:${card.card_id},转化为${d}热带扰动`);
2007
+ }
2008
+ }
2009
+ }
2010
+ }
2011
+ await ctx.database.upsert("gacha_user_disturb_draw", [{ qq, draw_count: have - count }]);
2012
+ const asset = await ctx.database.get("gacha_user_draw_count", { qq });
2013
+ await ctx.database.upsert("gacha_user_draw_count", [{
2014
+ qq,
2015
+ draw_count: asset[0]?.draw_count ?? 0,
2016
+ tropical_disturbance: (asset[0]?.tropical_disturbance ?? 0) + disturbanceTotal,
2017
+ water_vapor: (asset[0]?.water_vapor ?? 0) + waterVaporTotal,
2018
+ no_6star_draws: asset[0]?.no_6star_draws ?? 0,
2019
+ no_7star_draws: asset[0]?.no_7star_draws ?? 0
2020
+ }]);
2021
+ ctx.logger.info(`[扰动抽卡] ${showName}(${qq}) 消耗${count}抽,剩余${have - count},水汽+${waterVaporTotal},热带扰动+${disturbanceTotal}`);
2022
+ let msg = session.text("tip.disturbDraw.title", { name: showName, left: have - count }) + "\n";
2023
+ drawResult.forEach((item) => {
2024
+ msg += `${get_star_symbol(item.star)} ${item.cid} ${item.name}
2025
+ `;
2026
+ });
2027
+ let info = "";
2028
+ if (isUpgrade) info += session.text("tip.draw.upgrade");
2029
+ info += session.text("tip.draw.vapor", { vapor: waterVaporTotal });
2030
+ info += session.text("tip.draw.disturb", { disturbanceTotal });
2031
+ if (info) msg += "\n" + info.replace(/;$/, "");
2032
+ await session.send(build_msg(session, msg));
2033
+ }
2034
+ __name(_do_disturb_draw, "_do_disturb_draw");
1803
2035
  async function _do_broadcast(ctx, session, msg, masterQQ) {
1804
2036
  const userQQ = await getUnifiedQQ(ctx, session);
1805
2037
  if (userQQ !== masterQQ) return;
@@ -1851,7 +2083,7 @@ async function _do_reject(ctx, session, rejectQQ, masterQQ) {
1851
2083
  }
1852
2084
  __name(_do_reject, "_do_reject");
1853
2085
  async function _do_help(ctx, session) {
1854
- const helpMsg = session.text("command.wwc.help.title") + "\n" + session.text("command.wwc.help.register") + "\n" + session.text("command.wwc.help.sign") + "\n" + session.text("command.wwc.help.draw") + "\n" + session.text("command.wwc.help.warehouse") + "\n" + session.text("command.wwc.help.shop") + "\n" + session.text("command.wwc.help.upgrade") + "\n" + session.text("command.wwc.help.exchange") + "\n" + session.text("command.wwc.help.collection") + "\n" + session.text("command.wwc.help.ranking") + "\n" + session.text("command.wwc.help.eventStatus") + "\n" + session.text("command.wwc.help.eventDraw") + "\n" + session.text("command.wwc.help.eventExchange") + "\n" + session.text("command.wwc.help.tip");
2086
+ const helpMsg = session.text("command.wwc.help.title") + "\n" + session.text("command.wwc.help.register") + "\n" + session.text("command.wwc.help.sign") + "\n" + session.text("command.wwc.help.draw") + "\n" + session.text("command.wwc.help.warehouse") + "\n" + session.text("command.wwc.help.shop") + "\n" + session.text("command.wwc.help.upgrade") + "\n" + session.text("command.wwc.help.exchange") + "\n" + session.text("command.wwc.help.collection") + "\n" + session.text("command.wwc.help.ranking") + "\n" + session.text("command.wwc.help.eventStatus") + "\n" + session.text("command.wwc.help.eventDraw") + "\n" + session.text("command.wwc.help.eventExchange") + "\n" + session.text("command.wwc.help.disturbDraw") + "\n" + session.text("command.wwc.help.disturbExchange") + "\n" + session.text("command.wwc.help.tip");
1855
2087
  await session.send(build_msg(session, helpMsg));
1856
2088
  }
1857
2089
  __name(_do_help, "_do_help");
@@ -1951,6 +2183,10 @@ async function apply(ctx, config) {
1951
2183
  got6: { type: "boolean" },
1952
2184
  got7: { type: "boolean" }
1953
2185
  }, { primary: ["qq", "event_code"] });
2186
+ ctx.model.extend("gacha_user_disturb_draw", {
2187
+ qq: { type: "string" },
2188
+ draw_count: { type: "integer" }
2189
+ }, { primary: ["qq"] });
1954
2190
  ctx.model.extend("gacha_group_member", {
1955
2191
  group_id: { type: "string" },
1956
2192
  qq: { type: "string" },
@@ -2090,6 +2326,11 @@ async function apply(ctx, config) {
2090
2326
  const session = argv.session;
2091
2327
  await _do_ranking(ctx, session);
2092
2328
  });
2329
+ ctx.command("WWC排名2", "查看全服7/6星战力评分排行(7星0级20分每级+15,普通6星0级5分每级+3,限时6星0级8分每级+6),显示前20名+自身排名").alias("wwc排名2").alias("WWC排行2").action(async (argv) => {
2330
+ if (!argv.session) return;
2331
+ const session = argv.session;
2332
+ await _do_ranking2(ctx, session);
2333
+ });
2093
2334
  ctx.command("WWC开启", "开启本群WWC功能,仅主人可用").alias("wwc开启").action(async (argv) => {
2094
2335
  if (!argv.session) return;
2095
2336
  const session = argv.session;
@@ -2131,6 +2372,20 @@ async function apply(ctx, config) {
2131
2372
  const cnt = Number.isInteger(num) && num >= 1 && num <= 40 ? num : 1;
2132
2373
  await _do_event_exchange(ctx, session, { code, cnt }, config.eventExchangePrice6, config.eventExchangePrice7);
2133
2374
  });
2375
+ ctx.command("WWC扰动抽卡 [次数]", "使用扰动抽数抽卡(普通卡池:7星10%、6星36%、5星54%),支持1-20连").alias("wwc扰动抽卡").alias("WWC扰动抽").action(async (argv, count) => {
2376
+ if (!argv.session) return;
2377
+ const session = argv.session;
2378
+ const num = Number(count);
2379
+ const times = Number.isInteger(num) && num >= 1 && num <= 20 ? num : 1;
2380
+ await _do_disturb_draw(ctx, session, times);
2381
+ });
2382
+ ctx.command("WWC扰动兑换 <次数>", "热带扰动兑换扰动抽数,每抽消耗由配置项决定(默认100),单次1-40").alias("wwc扰动兑换").alias("WWC扰动换抽").action(async (argv, count) => {
2383
+ if (!argv.session) return;
2384
+ const session = argv.session;
2385
+ const num = Number(count);
2386
+ const cnt = Number.isInteger(num) && num >= 1 && num <= 40 ? num : 1;
2387
+ await _do_disturb_exchange(ctx, session, cnt, config.disturbExchangePrice);
2388
+ });
2134
2389
  ctx.command("WWC限时录入 <参数...>", "录入限时卡池信息,仅主人可用(格式:期数 ID 名称 星级 类别 开始戳 结束戳)").alias("wwc限时录入").action(async (argv, ...params) => {
2135
2390
  if (!argv.session) return;
2136
2391
  const session = argv.session;
@@ -12,6 +12,8 @@ declare const _default: {
12
12
  "command.wwc.help.eventStatus": string;
13
13
  "command.wwc.help.eventDraw": string;
14
14
  "command.wwc.help.eventExchange": string;
15
+ "command.wwc.help.disturbDraw": string;
16
+ "command.wwc.help.disturbExchange": string;
15
17
  "command.wwc.help.tip": string;
16
18
  "tip.register.success": string;
17
19
  "tip.register.modify": string;
@@ -25,6 +27,8 @@ declare const _default: {
25
27
  "tip.switch.groupClose": string;
26
28
  "tip.eventAdd.success": string;
27
29
  "tip.eventExchange.success": string;
30
+ "tip.disturbExchange.success": string;
31
+ "tip.disturbDraw.title": string;
28
32
  "tip.eventStatus.info": string;
29
33
  "tip.upgrade.success": string;
30
34
  "tip.upgrade.cost": string;
@@ -69,6 +73,8 @@ declare const _default: {
69
73
  "error.eventDraw.count.notEnough": string;
70
74
  "error.eventDraw.param.invalid": string;
71
75
  "error.eventExchange.pool.none": string;
76
+ "error.disturbExchange.disturb.notEnough": string;
77
+ "error.disturbDraw.count.notEnough": string;
72
78
  "error.switch.private": string;
73
79
  "error.switch.fail": string;
74
80
  "error.shop.no7starCard": string;
@@ -105,6 +111,9 @@ declare const _default: {
105
111
  "image.ranking.header.player": string;
106
112
  "image.ranking.header.count": string;
107
113
  "image.ranking.mine": string;
114
+ "image.ranking2.title": string;
115
+ "image.ranking2.header.score": string;
116
+ "image.ranking2.mine": string;
108
117
  "sys.notify.register": string;
109
118
  "sys.notify.sign": string;
110
119
  "sys.notify.draw": string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-xxck-1",
3
3
  "description": "抽卡系统|完整指令说明见readme|建议使用skia-canvas",
4
- "version": "0.3.4",
4
+ "version": "0.3.6",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [