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 +2 -0
- package/lib/damage.d.ts +3 -1
- package/lib/data/skillFn.d.ts +9 -1
- package/lib/index.js +447 -14
- package/lib/map.d.ts +1 -1
- package/lib/mapHtml.d.ts +6 -0
- package/lib/test.d.ts +1 -8
- package/package.json +1 -1
package/lib/battle.d.ts
CHANGED
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
|
}
|
package/lib/data/skillFn.d.ts
CHANGED
|
@@ -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}:${
|
|
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}
|
|
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
|
-
|
|
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
|
|
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
package/lib/mapHtml.d.ts
ADDED
package/lib/test.d.ts
CHANGED