koishi-plugin-smmcat-gensokyo 0.0.27 → 0.0.29

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/battle.d.ts CHANGED
@@ -104,6 +104,8 @@ export type BuffGain = {
104
104
  dizziness?: boolean;
105
105
  /** 是否混乱 */
106
106
  chaos?: boolean;
107
+ /** 伤害减免 */
108
+ reduction?: number;
107
109
  };
108
110
  /** 最后战斗状态 */
109
111
  type LastPlay = {
package/lib/damage.d.ts CHANGED
@@ -28,6 +28,8 @@ export type DamageConfig = {
28
28
  isCsp: boolean;
29
29
  /** 是否未破防 */
30
30
  isBadDef: boolean;
31
+ /** 减免伤害 */
32
+ reductionVal: number;
31
33
  };
32
34
  declare class Damage {
33
35
  config: DamageConfig;
@@ -45,7 +47,7 @@ declare class Damage {
45
47
  csp(fn: (config: DamageConfig) => void): this;
46
48
  /** 防御结算 */
47
49
  beforDef(fn: (config: DamageConfig) => void): this;
48
- /** 最终结算 */
50
+ /** 最终结算 伤害减免 */
49
51
  beforEnd(fn: (config: DamageConfig) => void): this;
50
52
  result(fn?: DamageCallback): DamageConfig;
51
53
  }
@@ -4,6 +4,7 @@ export declare enum SkillType {
4
4
  释放失败 = "\u91CA\u653E\u5931\u8D25",
5
5
  伤害技 = "\u4F24\u5BB3\u6280",
6
6
  增益技 = "\u589E\u76CA\u6280",
7
+ 减益技 = "\u51CF\u76CA\u6280",
7
8
  治疗技 = "\u6CBB\u7597\u6280",
8
9
  奥义 = "\u5965\u4E49"
9
10
  }
@@ -37,6 +38,13 @@ interface BuffSkillParams {
37
38
  /** 错误提示 */
38
39
  err?: string;
39
40
  }
41
+ interface DeBuffSkillParams {
42
+ type: SkillType.减益技;
43
+ /** 是否衔接普攻 */
44
+ isNext: boolean;
45
+ /** 错误提示 */
46
+ err?: string;
47
+ }
40
48
  interface UltimateSkillParams {
41
49
  type: SkillType.奥义;
42
50
  /** 是否衔接普攻 */
@@ -49,7 +57,7 @@ interface ErrSkillParams {
49
57
  /** 错误提示 */
50
58
  err?: string;
51
59
  }
52
- type SkillParams = DamageSkillParams | BuffSkillParams | HealSkillParams | UltimateSkillParams | ErrSkillParams;
60
+ type SkillParams = DamageSkillParams | BuffSkillParams | HealSkillParams | UltimateSkillParams | ErrSkillParams | DeBuffSkillParams;
53
61
  interface SkillConfig<T extends SkillType = SkillType> {
54
62
  /** 技能名 */
55
63
  name: string;
package/lib/index.js CHANGED
@@ -55,13 +55,15 @@ var GensokyoMap = {
55
55
  areaName: "地下墓穴",
56
56
  type: "BOSS区" /* BOSS区 */,
57
57
  needLv: 1,
58
- down: "蜘蛛洞穴"
58
+ down: "蜘蛛洞穴",
59
+ monster: [{ name: "古明地觉", lv: 15 }]
59
60
  },
60
61
  "蜘蛛洞穴": {
61
62
  floor: 1,
62
63
  areaName: "蜘蛛洞穴",
63
64
  type: "冒险区" /* 冒险区 */,
64
65
  needLv: 1,
66
+ top: "地下墓穴",
65
67
  down: "蜘蛛森林一"
66
68
  },
67
69
  "蜘蛛森林一": {
@@ -700,6 +702,30 @@ var monsterData = {
700
702
  { name: "初级复活卷轴", val: 1, radomVal: 50 }
701
703
  ],
702
704
  fn: [{ name: "毒之牙", prob: 1 }]
705
+ },
706
+ "古明地觉": {
707
+ name: "古明地觉",
708
+ type: "BOSS" /* BOSS */,
709
+ info: "位于旧地狱中心地带的管理者,拥有读心的控制技能。",
710
+ pic: "http://smmcat.cn/run/gensokyo/古明地觉.png",
711
+ hp: 95,
712
+ maxHp: 95,
713
+ mp: 140,
714
+ maxMp: 140,
715
+ atk: 24,
716
+ def: 2,
717
+ chr: 150,
718
+ csr: 0,
719
+ evasion: 150,
720
+ hit: 30,
721
+ ghd: 1.6,
722
+ speed: 8,
723
+ giveExp: 20,
724
+ giveMonetary: 8,
725
+ giveProps: [
726
+ { name: "初级复活卷轴", val: 1, radomVal: 50 }
727
+ ],
728
+ fn: [{ name: "恐怖催眠术", prob: 1 }, { name: "恐怖的回忆", prob: 2 }]
703
729
  }
704
730
  };
705
731
 
@@ -833,7 +859,8 @@ var Damage = class {
833
859
  isRealHarm: realHarm,
834
860
  isEvasion: false,
835
861
  isCsp: false,
836
- isBadDef: false
862
+ isBadDef: false,
863
+ reductionVal: 0
837
864
  };
838
865
  }
839
866
  /** 伤害判定前 */
@@ -895,8 +922,15 @@ var Damage = class {
895
922
  }
896
923
  return this;
897
924
  }
898
- /** 最终结算 */
925
+ /** 最终结算 伤害减免 */
899
926
  beforEnd(fn) {
927
+ if (!this.config.isRealHarm) {
928
+ this.config.reductionVal = Math.floor(this.config.agent.goal.gain.reduction * this.config.harm);
929
+ this.config.harm -= this.config.reductionVal;
930
+ if (this.config.harm < 0) {
931
+ this.config.harm = 0;
932
+ }
933
+ }
900
934
  fn && fn(this.config);
901
935
  return this;
902
936
  }
@@ -1048,6 +1082,19 @@ var BuffFn = {
1048
1082
  }
1049
1083
  });
1050
1084
  }, "fn")
1085
+ },
1086
+ "破绽": {
1087
+ name: "破绽",
1088
+ type: "减益" /* 减益 */,
1089
+ info: "增加受到的 30% 伤害",
1090
+ fn: /* @__PURE__ */ __name(function(agent, fn) {
1091
+ fn && fn({
1092
+ type: "减益" /* 减益 */,
1093
+ down: {
1094
+ reduction: 0.3
1095
+ }
1096
+ });
1097
+ }, "fn")
1051
1098
  }
1052
1099
  };
1053
1100
  function giveBuff(agent, buff) {
@@ -1072,6 +1119,7 @@ function settlementBuff(agent) {
1072
1119
  agent.gain.maxMp = 0;
1073
1120
  agent.gain.maxMp = 0;
1074
1121
  agent.gain.speed = 0;
1122
+ agent.gain.reduction = 0;
1075
1123
  agent.gain.dizziness = false;
1076
1124
  agent.gain.chaos = false;
1077
1125
  const msgList = [];
@@ -1084,7 +1132,8 @@ function settlementBuff(agent) {
1084
1132
  ghd: "暴击伤害",
1085
1133
  evasion: "闪避值",
1086
1134
  hit: "命中值",
1087
- speed: "速度"
1135
+ speed: "速度",
1136
+ reduction: "伤害减免"
1088
1137
  };
1089
1138
  Object.keys(agent.buff).forEach((item) => {
1090
1139
  const buffInfo = BuffFn[item] || null;
@@ -1106,7 +1155,7 @@ function settlementBuff(agent) {
1106
1155
  const upMsg = [];
1107
1156
  buffInfo.fn(agent, (val) => {
1108
1157
  Object.keys(val.up).forEach((buffName) => {
1109
- if (agent.gain[buffName]) {
1158
+ if (agent.gain[buffName] !== void 0) {
1110
1159
  upMsg.push(
1111
1160
  val.up[buffName] > 0 ? gainDict[buffName] + "↑" + val.up[buffName] : gainDict[buffName] + "↓" + Math.abs(val.up[buffName])
1112
1161
  );
@@ -1120,14 +1169,14 @@ function settlementBuff(agent) {
1120
1169
  const downMsg = [];
1121
1170
  buffInfo.fn(agent, (val) => {
1122
1171
  Object.keys(val.down).forEach((buffName) => {
1123
- if (agent.gain[buffName]) {
1172
+ if (agent.gain[buffName] !== void 0) {
1124
1173
  downMsg.push(
1125
1174
  val.down[buffName] > 0 ? gainDict[buffName] + "↓" + val.down[buffName] : gainDict[buffName] + "↑" + Math.abs(val.down[buffName])
1126
1175
  );
1127
1176
  agent.gain[buffName] -= val.down[buffName];
1128
1177
  }
1129
1178
  });
1130
- msgList.push(`${buffInfo.name}:${upMsg.join("、")}`);
1179
+ msgList.push(`${buffInfo.name}:${downMsg.join("、")}`);
1131
1180
  });
1132
1181
  break;
1133
1182
  case "控制" /* 控制 */:
@@ -1144,7 +1193,7 @@ function settlementBuff(agent) {
1144
1193
  --agent.buff[item].timer;
1145
1194
  if (agent.buff[item].timer == 0) delete agent.buff[item];
1146
1195
  });
1147
- return msgList.length ? msgList.map((item) => `» ${getLineupName(agent)}:${item})`).join("\n") : null;
1196
+ return msgList.length ? msgList.map((item) => `» ${getLineupName(agent)}:${item}`).join("\n") : null;
1148
1197
  }
1149
1198
  __name(settlementBuff, "settlementBuff");
1150
1199
 
@@ -1337,6 +1386,49 @@ var skillFn = {
1337
1386
  });
1338
1387
  return msgList.join("\n");
1339
1388
  }, "fn")
1389
+ },
1390
+ "恐怖催眠术": {
1391
+ name: "恐怖催眠术",
1392
+ type: "伤害技" /* 伤害技 */,
1393
+ info: "对单个目标造成(攻击1.5倍+自身命中值10%)伤害,造成伤害有60%概率使其晕眩2回合。",
1394
+ lv: 1,
1395
+ mp: 40,
1396
+ fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
1397
+ let useBuff = false;
1398
+ const damageData = new Damage(agent).result({
1399
+ before: /* @__PURE__ */ __name((val) => {
1400
+ val.default_harm += Math.floor(val.default_harm * 0.2) + Math.floor((val.agent.self.hit + val.agent.self.gain.hit) * 0.1);
1401
+ }, "before"),
1402
+ beforEnd: /* @__PURE__ */ __name((val) => {
1403
+ if (val.harm && random(0, 10) < 6) {
1404
+ useBuff = true;
1405
+ giveBuff(agent.goal, { name: "晕眩", timer: 3 });
1406
+ }
1407
+ }, "beforEnd")
1408
+ });
1409
+ fn({
1410
+ type: "伤害技" /* 伤害技 */,
1411
+ damage: damageData,
1412
+ isNext: false,
1413
+ target: [agent.goal]
1414
+ });
1415
+ return `${getLineupName(agent.self)} 发动恐怖催眠术!对 ${getLineupName(agent.goal)} 造成 ${damageData.harm} 伤害。${useBuff ? "(晕眩)" : ""}` + moreDamageInfo(damageData);
1416
+ }, "fn")
1417
+ },
1418
+ "恐怖的回忆": {
1419
+ name: "恐怖的回忆",
1420
+ type: "减益技" /* 减益技 */,
1421
+ info: "对单个目标附加破绽状态(额外受到30%伤害),持续2回合",
1422
+ lv: 1,
1423
+ mp: 30,
1424
+ fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
1425
+ giveBuff(agent.goal, { name: "破绽", timer: 2 });
1426
+ fn({
1427
+ type: "减益技" /* 减益技 */,
1428
+ isNext: false
1429
+ });
1430
+ return `${getLineupName(agent.self)} 发动恐怖的回忆!对 ${getLineupName(agent.goal)} 附加了2回合破绽状态。`;
1431
+ }, "fn")
1340
1432
  }
1341
1433
  };
1342
1434
 
@@ -1641,7 +1733,7 @@ MP:${item.mp}/${item.maxMp + item.gain.maxMp}`);
1641
1733
  return;
1642
1734
  }
1643
1735
  const currentBattle = BattleData.lastPlay[session.userId];
1644
- const allAgentList = [...currentBattle.goal, ...currentBattle.self].sort((a, b) => b.speed - a.speed);
1736
+ const allAgentList = [...currentBattle.goal, ...currentBattle.self].sort((a, b) => b.speed + b.gain.speed - (a.speed + a.gain.speed));
1645
1737
  const msgList = [];
1646
1738
  for (const agent of allAgentList) {
1647
1739
  const buffMsg = settlementBuff(agent);
@@ -1813,7 +1905,9 @@ MP:${item.mp}/${item.maxMp + item.gain.maxMp}`);
1813
1905
  });
1814
1906
  }
1815
1907
  });
1816
- await session.send(`小队获得${val}EXP、${monetary}货币!`);
1908
+ if (overInfo.win == "self") {
1909
+ await session.send(`小队获得${val}EXP、${monetary}货币!`);
1910
+ }
1817
1911
  for (const agent of selfList) {
1818
1912
  aynchronize(agent);
1819
1913
  if (overInfo.win == "self") {
@@ -1885,7 +1979,8 @@ function initBattleAttribute(data) {
1885
1979
  hit: 0,
1886
1980
  speed: 0,
1887
1981
  chaos: false,
1888
- dizziness: false
1982
+ dizziness: false,
1983
+ reduction: 0
1889
1984
  },
1890
1985
  buff: {},
1891
1986
  fn: [],
@@ -1923,7 +2018,8 @@ function initBattleAttribute(data) {
1923
2018
  hit: 0,
1924
2019
  speed: 0,
1925
2020
  chaos: false,
1926
- dizziness: false
2021
+ dizziness: false,
2022
+ reduction: 0
1927
2023
  },
1928
2024
  buff: {},
1929
2025
  fn: monsterData2.fn ? JSON.parse(JSON.stringify(monsterData2.fn)) : [],
@@ -2275,7 +2371,7 @@ var User = {
2275
2371
  await session.send("请不要设置怪物的名字!");
2276
2372
  return;
2277
2373
  }
2278
- if (playname.trim().length < 6 || playname.trim().length > 1) {
2374
+ if (playname.trim().length > 6 || playname.trim().length < 1) {
2279
2375
  await session.send("名字长度有问题,要求小于 6个字,大于 1个字");
2280
2376
  return;
2281
2377
  }
@@ -2583,10 +2679,319 @@ ${Object.keys(UserOccDict).map((i) => `【${i}】:${UserOccDict[i].info}`).join(
2583
2679
  }
2584
2680
  };
2585
2681
 
2682
+ // src/mapHtml.ts
2683
+ function generateMapHTML(mapData, currentAreaName) {
2684
+ const centerKey = Object.keys(mapData).find((key) => mapData[key].type === "传送门");
2685
+ if (!centerKey) {
2686
+ return "<div>未找到传送门区域</div>";
2687
+ }
2688
+ const visited = /* @__PURE__ */ new Set();
2689
+ const grid = {};
2690
+ let minRow = 0, maxRow = 0, minCol = 0, maxCol = 0;
2691
+ function placeArea(key, row, col) {
2692
+ if (visited.has(key)) return;
2693
+ visited.add(key);
2694
+ const area = mapData[key];
2695
+ if (!area) return;
2696
+ const connections = {
2697
+ top: false,
2698
+ left: false,
2699
+ right: false,
2700
+ down: false
2701
+ };
2702
+ if (!grid[row]) grid[row] = {};
2703
+ grid[row][col] = { area, key, row, col, connections };
2704
+ minRow = Math.min(minRow, row);
2705
+ maxRow = Math.max(maxRow, row);
2706
+ minCol = Math.min(minCol, col);
2707
+ maxCol = Math.max(maxCol, col);
2708
+ if (area.top) {
2709
+ placeArea(area.top, row - 1, col);
2710
+ connections.top = true;
2711
+ if (grid[row - 1]?.[col]) {
2712
+ grid[row - 1][col].connections.down = true;
2713
+ }
2714
+ }
2715
+ if (area.left) {
2716
+ placeArea(area.left, row, col - 1);
2717
+ connections.left = true;
2718
+ if (grid[row]?.[col - 1]) {
2719
+ grid[row][col - 1].connections.right = true;
2720
+ }
2721
+ }
2722
+ if (area.right) {
2723
+ placeArea(area.right, row, col + 1);
2724
+ connections.right = true;
2725
+ if (grid[row]?.[col + 1]) {
2726
+ grid[row][col + 1].connections.left = true;
2727
+ }
2728
+ }
2729
+ if (area.down) {
2730
+ placeArea(area.down, row + 1, col);
2731
+ connections.down = true;
2732
+ if (grid[row + 1]?.[col]) {
2733
+ grid[row + 1][col].connections.top = true;
2734
+ }
2735
+ }
2736
+ }
2737
+ __name(placeArea, "placeArea");
2738
+ placeArea(centerKey, 0, 0);
2739
+ const cellWidth = 160;
2740
+ const cellHeight = 120;
2741
+ const svgWidth = (maxCol - minCol + 1) * cellWidth;
2742
+ const svgHeight = (maxRow - minRow + 1) * cellHeight;
2743
+ let html = `
2744
+ <style>
2745
+ .map-container {
2746
+ display: inline-block;
2747
+ position: relative;
2748
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
2749
+ font-size: 12px;
2750
+ background-color: transparent;
2751
+ padding: 20px;
2752
+ border-radius: 12px;
2753
+ min-width: 100vw;
2754
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
2755
+ }
2756
+ .map-table {
2757
+ border-collapse: separate;
2758
+ border-spacing: 0;
2759
+ position: relative;
2760
+ z-index: 2;
2761
+ }
2762
+ .map-cell {
2763
+ width: ${cellWidth}px;
2764
+ height: ${cellHeight}px;
2765
+ border: none;
2766
+ padding: 12px;
2767
+ vertical-align: top;
2768
+ text-align: center;
2769
+ background: rgba(255, 255, 255, 0.95);
2770
+ border-radius: 8px;
2771
+ transition: all 0.3s ease;
2772
+ position: relative;
2773
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
2774
+ backdrop-filter: blur(10px);
2775
+ }
2776
+ .map-cell:hover {
2777
+ transform: translateY(-2px);
2778
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
2779
+ }
2780
+ .empty-cell {
2781
+ background: transparent !important;
2782
+ box-shadow: none !important;
2783
+ border: none !important;
2784
+ }
2785
+ .area-name {
2786
+ font-weight: 700;
2787
+ margin-bottom: 6px;
2788
+ color: #2d3748;
2789
+ font-size: 14px;
2790
+ letter-spacing: 0.5px;
2791
+ }
2792
+ .area-type {
2793
+ font-size: 11px;
2794
+ color: #718096;
2795
+ margin-bottom: 6px;
2796
+ padding: 2px 8px;
2797
+ background: rgba(237, 242, 247, 0.8);
2798
+ border-radius: 12px;
2799
+ display: inline-block;
2800
+ }
2801
+ .area-info {
2802
+ font-size: 10px;
2803
+ color: #4a5568;
2804
+ margin-bottom: 6px;
2805
+ font-style: italic;
2806
+ }
2807
+ .monster-list, .npc-list {
2808
+ font-size: 10px;
2809
+ color: #2d3748;
2810
+ text-align: left;
2811
+ margin-top: 6px;
2812
+ padding-left: 8px;
2813
+ }
2814
+ .monster-list {
2815
+ border-left: 2px solid #e53e3e;
2816
+ }
2817
+ .npc-list {
2818
+ border-left: 2px solid #38a169;
2819
+ }
2820
+ .safe {
2821
+ background: linear-gradient(135deg, rgba(224, 247, 250, 0.95), rgba(129, 230, 217, 0.95));
2822
+ border: 2px solid #38b2ac;
2823
+ }
2824
+ .boss {
2825
+ background: linear-gradient(135deg, rgba(255, 235, 238, 0.95), rgba(254, 178, 178, 0.95));
2826
+ border: 2px solid #e53e3e;
2827
+ }
2828
+ .adventure {
2829
+ background: linear-gradient(135deg, rgba(241, 248, 233, 0.95), rgba(154, 230, 180, 0.95));
2830
+ border: 2px solid #38a169;
2831
+ }
2832
+ .portal {
2833
+ background: linear-gradient(135deg, rgba(255, 243, 224, 0.95), rgba(251, 211, 141, 0.95));
2834
+ border: 2px solid #ed8936;
2835
+ }
2836
+ .current {
2837
+ background: linear-gradient(135deg, rgba(255, 249, 196, 0.95), rgba(254, 240, 138, 0.95)) !important;
2838
+ border: 3px solid #d69e2e !important;
2839
+ box-shadow: 0 0 20px rgba(214, 158, 46, 0.4), 0 8px 16px rgba(0, 0, 0, 0.2);
2840
+ transform: scale(1.08);
2841
+ z-index: 10;
2842
+ animation: glow 2s ease-in-out infinite alternate;
2843
+ }
2844
+ @keyframes glow {
2845
+ from {
2846
+ box-shadow: 0 0 20px rgba(214, 158, 46, 0.4), 0 8px 16px rgba(0, 0, 0, 0.2);
2847
+ }
2848
+ to {
2849
+ box-shadow: 0 0 30px rgba(214, 158, 46, 0.6), 0 10px 20px rgba(0, 0, 0, 0.3);
2850
+ }
2851
+ }
2852
+ .current .area-name {
2853
+ color: #744210;
2854
+ font-weight: 900;
2855
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
2856
+ }
2857
+ .current-marker {
2858
+ display: inline-block;
2859
+ width: 10px;
2860
+ height: 10px;
2861
+ background: linear-gradient(135deg, #d69e2e, #744210);
2862
+ border-radius: 50%;
2863
+ margin-right: 6px;
2864
+ animation: pulse 1.5s ease-in-out infinite;
2865
+ box-shadow: 0 0 8px rgba(214, 158, 46, 0.8);
2866
+ }
2867
+ @keyframes pulse {
2868
+ 0% { transform: scale(1); opacity: 1; }
2869
+ 50% { transform: scale(1.4); opacity: 0.8; }
2870
+ 100% { transform: scale(1); opacity: 1; }
2871
+ }
2872
+ .connection-lines {
2873
+ position: absolute;
2874
+ top: 0;
2875
+ left: 0;
2876
+ width: 100%;
2877
+ height: 100%;
2878
+ z-index: 1;
2879
+ pointer-events: none;
2880
+ }
2881
+ .connection-line {
2882
+ stroke: rgba(255, 255, 255, 0.7);
2883
+ stroke-width: 3;
2884
+ stroke-linecap: round;
2885
+ filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
2886
+ }
2887
+ .connection-line-dotted {
2888
+ stroke-dasharray: 5, 5;
2889
+ }
2890
+ .connection-line-solid {
2891
+ stroke-dasharray: none;
2892
+ }
2893
+ .connection-dot {
2894
+ fill: rgba(255, 255, 255, 0.9);
2895
+ stroke: #4a5568;
2896
+ stroke-width: 1;
2897
+ filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.2));
2898
+ }
2899
+ </style>
2900
+ <div class="map-container">
2901
+ <svg class="connection-lines" width="${svgWidth}" height="${svgHeight}">
2902
+ `;
2903
+ for (let r = minRow; r <= maxRow; r++) {
2904
+ for (let c = minCol; c <= maxCol; c++) {
2905
+ const cell = grid[r]?.[c];
2906
+ if (cell) {
2907
+ const { connections } = cell;
2908
+ const x = (c - minCol) * cellWidth + cellWidth / 2;
2909
+ const y = (r - minRow) * cellHeight + cellHeight / 2;
2910
+ html += `<circle class="connection-dot" cx="${x}" cy="${y}" r="4" />`;
2911
+ if (connections.top) {
2912
+ const targetX = x;
2913
+ const targetY = y - cellHeight;
2914
+ html += `<line class="connection-line connection-line-dotted"
2915
+ x1="${x}" y1="${y}"
2916
+ x2="${targetX}" y2="${targetY}" />`;
2917
+ }
2918
+ if (connections.down) {
2919
+ const targetX = x;
2920
+ const targetY = y + cellHeight;
2921
+ html += `<line class="connection-line connection-line-dotted"
2922
+ x1="${x}" y1="${y}"
2923
+ x2="${targetX}" y2="${targetY}" />`;
2924
+ }
2925
+ if (connections.left) {
2926
+ const targetX = x - cellWidth;
2927
+ const targetY = y;
2928
+ html += `<line class="connection-line connection-line-dotted"
2929
+ x1="${x}" y1="${y}"
2930
+ x2="${targetX}" y2="${targetY}" />`;
2931
+ }
2932
+ if (connections.right) {
2933
+ const targetX = x + cellWidth;
2934
+ const targetY = y;
2935
+ html += `<line class="connection-line connection-line-dotted"
2936
+ x1="${x}" y1="${y}"
2937
+ x2="${targetX}" y2="${targetY}" />`;
2938
+ }
2939
+ }
2940
+ }
2941
+ }
2942
+ html += `</svg><table class="map-table">`;
2943
+ for (let r = minRow; r <= maxRow; r++) {
2944
+ html += "<tr>";
2945
+ for (let c = minCol; c <= maxCol; c++) {
2946
+ const cell = grid[r]?.[c];
2947
+ if (cell) {
2948
+ const { area, key } = cell;
2949
+ const isCurrent = currentAreaName === area.areaName;
2950
+ const typeClass = area.type === "安全区" ? "safe" : area.type === "BOSS区" ? "boss" : area.type === "冒险区" ? "adventure" : area.type === "传送门" ? "portal" : "";
2951
+ const currentClass = isCurrent ? "current" : "";
2952
+ html += `<td class="map-cell ${typeClass} ${currentClass}">`;
2953
+ html += `<div class="area-name">`;
2954
+ if (isCurrent) {
2955
+ html += `<span class="current-marker"></span>`;
2956
+ }
2957
+ html += `${area.areaName}`;
2958
+ if (isCurrent) {
2959
+ html += ` <span style="color:#744210;font-size:11px;font-weight:600;">(当前位置)</span>`;
2960
+ }
2961
+ html += `</div>`;
2962
+ html += `<div class="area-type">${area.type} (Lv.${area.needLv}+)</div>`;
2963
+ if (area.info) {
2964
+ html += `<div class="area-info">${area.info}</div>`;
2965
+ }
2966
+ if (area.npc && area.npc.length > 0) {
2967
+ html += `<div class="npc-list">NPC: ${area.npc.join(", ")}</div>`;
2968
+ }
2969
+ if (area.monster && area.monster.length > 0) {
2970
+ html += `<div class="monster-list">`;
2971
+ area.monster.forEach((m) => {
2972
+ html += `<div style="margin: 2px 0;">${m.name} <span style="color:#e53e3e">Lv.${m.lv}</span></div>`;
2973
+ });
2974
+ html += `</div>`;
2975
+ }
2976
+ html += `</td>`;
2977
+ } else {
2978
+ html += `<td class="map-cell empty-cell"></td>`;
2979
+ }
2980
+ }
2981
+ html += "</tr>";
2982
+ }
2983
+ html += `
2984
+ </table>
2985
+ </div>
2986
+ `;
2987
+ return html;
2988
+ }
2989
+ __name(generateMapHTML, "generateMapHTML");
2990
+
2586
2991
  // src/index.ts
2587
2992
  var name = "smmcat-gensokyo";
2588
2993
  var inject = {
2589
- required: ["monetary", "database"]
2994
+ required: ["monetary", "database", "puppeteer"]
2590
2995
  };
2591
2996
  var Config = import_koishi2.Schema.object({});
2592
2997
  function apply(ctx, config) {
@@ -2885,18 +3290,27 @@ function apply(ctx, config) {
2885
3290
  });
2886
3291
  ctx.command("幻想乡/队伍操作");
2887
3292
  ctx.command("队伍操作/队伍创建").action(async ({ session }) => {
3293
+ const userData = await User.getUserAttribute(session);
3294
+ if (!userData) return;
3295
+ GensokyoMap.initUserPoistion(session, userData);
2888
3296
  if (BattleData.isBattle(session)) {
2889
3297
  return `战斗中无法进行队伍创建操作!`;
2890
3298
  }
2891
3299
  await BattleData.creatTeam(session);
2892
3300
  });
2893
3301
  ctx.command("队伍操作/队伍信息").action(async ({ session }) => {
3302
+ const userData = await User.getUserAttribute(session);
3303
+ if (!userData) return;
3304
+ GensokyoMap.initUserPoistion(session, userData);
2894
3305
  const team = BattleData.teamListByUser(session.userId);
2895
3306
  if (!team.length) return `你还没有队伍...`;
2896
3307
  return `当前队伍信息如下:
2897
3308
  ` + team.map((item) => `lv.${item.lv} ${item.playName} [${BattleData.teamTemp[item.userId].identity}]`).join("\n");
2898
3309
  });
2899
3310
  ctx.command("队伍操作/队伍邀请 <playName>").action(async ({ session }, playName) => {
3311
+ const userData = await User.getUserAttribute(session);
3312
+ if (!userData) return;
3313
+ GensokyoMap.initUserPoistion(session, userData);
2900
3314
  if (BattleData.isBattle(session)) {
2901
3315
  return `战斗中无法进行队伍邀请操作!`;
2902
3316
  }
@@ -2906,23 +3320,42 @@ function apply(ctx, config) {
2906
3320
  await BattleData.invitationTeam(session, playName);
2907
3321
  });
2908
3322
  ctx.command("队伍操作/队伍加入").action(async ({ session }) => {
3323
+ const userData = await User.getUserAttribute(session);
3324
+ if (!userData) return;
3325
+ GensokyoMap.initUserPoistion(session, userData);
2909
3326
  if (BattleData.isBattle(session)) {
2910
3327
  return `战斗中无法进行队伍创建操作!`;
2911
3328
  }
2912
3329
  await BattleData.joinTeam(session);
2913
3330
  });
2914
3331
  ctx.command("队伍操作/队伍退出").action(async ({ session }) => {
3332
+ const userData = await User.getUserAttribute(session);
3333
+ if (!userData) return;
3334
+ GensokyoMap.initUserPoistion(session, userData);
2915
3335
  if (BattleData.isBattle(session)) {
2916
3336
  return `战斗中无法进行队伍退出操作!`;
2917
3337
  }
2918
3338
  await BattleData.exitTeam(session);
2919
3339
  });
2920
3340
  ctx.command("队伍操作/队伍解散").action(async ({ session }) => {
3341
+ const userData = await User.getUserAttribute(session);
3342
+ if (!userData) return;
3343
+ GensokyoMap.initUserPoistion(session, userData);
2921
3344
  if (BattleData.isBattle(session)) {
2922
3345
  return `战斗中无法进行队伍解散操作!`;
2923
3346
  }
2924
3347
  await BattleData.dissolveTeam(session);
2925
3348
  });
3349
+ ctx.command("幻想乡/地图").action(async ({ session }) => {
3350
+ const userData = await User.getUserAttribute(session);
3351
+ if (!userData) return;
3352
+ GensokyoMap.initUserPoistion(session, userData);
3353
+ const { areaName, floor } = GensokyoMap.userCurrentLoal[session.userId];
3354
+ const mapLocal = GensokyoMap.mapLocalData[floor];
3355
+ const html = generateMapHTML(mapLocal, areaName);
3356
+ console.log(html);
3357
+ await session.send(await ctx.puppeteer.render(html));
3358
+ });
2926
3359
  }
2927
3360
  __name(apply, "apply");
2928
3361
  // Annotate the CommonJS export names for ESM import in node:
package/lib/map.d.ts CHANGED
@@ -17,7 +17,7 @@ declare module 'koishi' {
17
17
  }
18
18
  }
19
19
  /** 区域信息 */
20
- type AreaItem = {
20
+ export type AreaItem = {
21
21
  /** 层级 */
22
22
  floor: number;
23
23
  /** 区域名 */
@@ -0,0 +1,6 @@
1
+ import { AreaItem } from "./map";
2
+ interface MapData {
3
+ [key: string]: AreaItem;
4
+ }
5
+ export declare function generateMapHTML(mapData: MapData, currentAreaName?: string): string;
6
+ export {};
package/lib/test.d.ts CHANGED
@@ -1,8 +1 @@
1
- declare const fn: {
2
- name: string;
3
- prob: number;
4
- }[];
5
- declare function useAtkFn(fnList: {
6
- name: string;
7
- prob: number;
8
- }[]): string;
1
+ declare let a: number;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-smmcat-gensokyo",
3
3
  "description": "名为《幻想乡》的文字冒险游戏",
4
- "version": "0.0.27",
4
+ "version": "0.0.29",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [