koishi-plugin-smmcat-gensokyo 0.0.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/battle.d.ts +125 -0
- package/lib/damage.d.ts +51 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.js +1224 -0
- package/lib/map.d.ts +104 -0
- package/lib/monster.d.ts +63 -0
- package/lib/users.d.ts +95 -0
- package/lib/utlis.d.ts +3 -0
- package/package.json +20 -0
- package/readme.md +5 -0
package/lib/index.js
ADDED
|
@@ -0,0 +1,1224 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name2 in all)
|
|
8
|
+
__defProp(target, name2, { get: all[name2], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
Config: () => Config,
|
|
24
|
+
apply: () => apply,
|
|
25
|
+
inject: () => inject,
|
|
26
|
+
name: () => name
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(src_exports);
|
|
29
|
+
var import_koishi = require("koishi");
|
|
30
|
+
|
|
31
|
+
// src/map.ts
|
|
32
|
+
var delay = /* @__PURE__ */ __name((ms) => new Promise((resolve) => setTimeout(resolve, ms)), "delay");
|
|
33
|
+
var GensokyoMap = {
|
|
34
|
+
config: {},
|
|
35
|
+
ctx: {},
|
|
36
|
+
mapLocalData: {},
|
|
37
|
+
userCurrentLoal: {},
|
|
38
|
+
async init(config, ctx) {
|
|
39
|
+
GensokyoMap.config = config;
|
|
40
|
+
GensokyoMap.ctx = ctx;
|
|
41
|
+
ctx.database.extend("smm_gensokyo_map_position", {
|
|
42
|
+
userId: "string",
|
|
43
|
+
floor: "integer",
|
|
44
|
+
areaName: "string",
|
|
45
|
+
moveing: "boolean",
|
|
46
|
+
playName: "string"
|
|
47
|
+
}, {
|
|
48
|
+
primary: "userId",
|
|
49
|
+
autoInc: false
|
|
50
|
+
});
|
|
51
|
+
GensokyoMap.mapLocalData = {
|
|
52
|
+
1: {
|
|
53
|
+
"地下墓穴": {
|
|
54
|
+
floor: 1,
|
|
55
|
+
areaName: "地下墓穴",
|
|
56
|
+
type: "BOSS区" /* BOSS区 */,
|
|
57
|
+
needLv: 1,
|
|
58
|
+
down: "蜘蛛洞穴"
|
|
59
|
+
},
|
|
60
|
+
"蜘蛛洞穴": {
|
|
61
|
+
floor: 1,
|
|
62
|
+
areaName: "蜘蛛洞穴",
|
|
63
|
+
type: "冒险区" /* 冒险区 */,
|
|
64
|
+
needLv: 1,
|
|
65
|
+
down: "蜘蛛森林一"
|
|
66
|
+
},
|
|
67
|
+
"蜘蛛森林一": {
|
|
68
|
+
floor: 1,
|
|
69
|
+
areaName: "蜘蛛森林一",
|
|
70
|
+
type: "冒险区" /* 冒险区 */,
|
|
71
|
+
needLv: 1,
|
|
72
|
+
monster: [{ name: "小蜘蛛", lv: 2 }],
|
|
73
|
+
top: "蜘蛛洞穴",
|
|
74
|
+
left: "蜘蛛森林二",
|
|
75
|
+
right: "蜘蛛森林三",
|
|
76
|
+
down: "蜘蛛森林通道"
|
|
77
|
+
},
|
|
78
|
+
"蜘蛛森林二": {
|
|
79
|
+
floor: 1,
|
|
80
|
+
areaName: "蜘蛛森林二",
|
|
81
|
+
type: "冒险区" /* 冒险区 */,
|
|
82
|
+
needLv: 1,
|
|
83
|
+
right: "蜘蛛森林一"
|
|
84
|
+
},
|
|
85
|
+
"蜘蛛森林三": {
|
|
86
|
+
floor: 1,
|
|
87
|
+
areaName: "蜘蛛森林三",
|
|
88
|
+
type: "冒险区" /* 冒险区 */,
|
|
89
|
+
needLv: 1,
|
|
90
|
+
left: "蜘蛛森林一"
|
|
91
|
+
},
|
|
92
|
+
"蜘蛛森林通道": {
|
|
93
|
+
floor: 1,
|
|
94
|
+
areaName: "蜘蛛森林通道",
|
|
95
|
+
type: "冒险区" /* 冒险区 */,
|
|
96
|
+
needLv: 1,
|
|
97
|
+
top: "蜘蛛森林一",
|
|
98
|
+
down: "中央广场"
|
|
99
|
+
},
|
|
100
|
+
"中央广场": {
|
|
101
|
+
floor: 1,
|
|
102
|
+
areaName: "中央广场",
|
|
103
|
+
info: "一层的中心位置,梦开始的地方",
|
|
104
|
+
npc: ["aipo"],
|
|
105
|
+
type: "安全区" /* 安全区 */,
|
|
106
|
+
needLv: 1,
|
|
107
|
+
top: "蜘蛛森林通道",
|
|
108
|
+
down: "新手村",
|
|
109
|
+
left: "酒馆",
|
|
110
|
+
right: "银行"
|
|
111
|
+
},
|
|
112
|
+
"酒馆": {
|
|
113
|
+
floor: 1,
|
|
114
|
+
areaName: "酒馆",
|
|
115
|
+
type: "安全区" /* 安全区 */,
|
|
116
|
+
needLv: 1,
|
|
117
|
+
down: "传送门",
|
|
118
|
+
right: "中央广场"
|
|
119
|
+
},
|
|
120
|
+
"银行": {
|
|
121
|
+
floor: 1,
|
|
122
|
+
areaName: "银行",
|
|
123
|
+
type: "安全区" /* 安全区 */,
|
|
124
|
+
needLv: 1,
|
|
125
|
+
down: "1层-商店",
|
|
126
|
+
left: "中央广场"
|
|
127
|
+
},
|
|
128
|
+
"1层-商店": {
|
|
129
|
+
floor: 1,
|
|
130
|
+
areaName: "1层-商店",
|
|
131
|
+
type: "安全区" /* 安全区 */,
|
|
132
|
+
needLv: 1,
|
|
133
|
+
right: "农田",
|
|
134
|
+
left: "新手村"
|
|
135
|
+
},
|
|
136
|
+
"传送门": {
|
|
137
|
+
floor: 1,
|
|
138
|
+
areaName: "传送门",
|
|
139
|
+
type: "传送门" /* 传送门 */,
|
|
140
|
+
needLv: 1,
|
|
141
|
+
top: "酒馆",
|
|
142
|
+
right: "新手村",
|
|
143
|
+
left: "爱之湖"
|
|
144
|
+
},
|
|
145
|
+
"爱之湖": {
|
|
146
|
+
floor: 1,
|
|
147
|
+
areaName: "传送门",
|
|
148
|
+
type: "安全区" /* 安全区 */,
|
|
149
|
+
needLv: 1,
|
|
150
|
+
right: "传送门"
|
|
151
|
+
},
|
|
152
|
+
"新手村": {
|
|
153
|
+
floor: 1,
|
|
154
|
+
areaName: "新手村",
|
|
155
|
+
type: "安全区" /* 安全区 */,
|
|
156
|
+
needLv: 1,
|
|
157
|
+
top: "中央广场",
|
|
158
|
+
down: "绿野平原通道",
|
|
159
|
+
left: "传送门",
|
|
160
|
+
right: "1层-商店"
|
|
161
|
+
},
|
|
162
|
+
"绿野平原通道": {
|
|
163
|
+
floor: 1,
|
|
164
|
+
areaName: "绿野平原通道",
|
|
165
|
+
type: "安全区" /* 安全区 */,
|
|
166
|
+
needLv: 1,
|
|
167
|
+
top: "新手村",
|
|
168
|
+
down: "绿野平原一"
|
|
169
|
+
},
|
|
170
|
+
"绿野平原一": {
|
|
171
|
+
floor: 1,
|
|
172
|
+
areaName: "绿野平原一",
|
|
173
|
+
type: "冒险区" /* 冒险区 */,
|
|
174
|
+
monster: [{ name: "小蜜蜂", lv: 1 }, { name: "dora", lv: 2 }],
|
|
175
|
+
needLv: 1,
|
|
176
|
+
top: "绿野平原通道",
|
|
177
|
+
left: "绿野平原二",
|
|
178
|
+
right: "绿野平原三",
|
|
179
|
+
down: "绿野平原四"
|
|
180
|
+
},
|
|
181
|
+
"绿野平原二": {
|
|
182
|
+
floor: 1,
|
|
183
|
+
areaName: "绿野平原二",
|
|
184
|
+
type: "冒险区" /* 冒险区 */,
|
|
185
|
+
needLv: 1,
|
|
186
|
+
right: "绿野平原一",
|
|
187
|
+
down: "绿野平原五"
|
|
188
|
+
},
|
|
189
|
+
"绿野平原三": {
|
|
190
|
+
floor: 1,
|
|
191
|
+
areaName: "绿野平原三",
|
|
192
|
+
type: "冒险区" /* 冒险区 */,
|
|
193
|
+
needLv: 1,
|
|
194
|
+
left: "绿野平原一",
|
|
195
|
+
down: "绿野平原六"
|
|
196
|
+
},
|
|
197
|
+
"绿野平原四": {
|
|
198
|
+
floor: 1,
|
|
199
|
+
areaName: "绿野平原四",
|
|
200
|
+
type: "冒险区" /* 冒险区 */,
|
|
201
|
+
needLv: 1,
|
|
202
|
+
top: "绿野平原一",
|
|
203
|
+
down: "野猪巢穴"
|
|
204
|
+
},
|
|
205
|
+
"绿野平原六": {
|
|
206
|
+
floor: 1,
|
|
207
|
+
areaName: "绿野平原六",
|
|
208
|
+
type: "冒险区" /* 冒险区 */,
|
|
209
|
+
needLv: 1,
|
|
210
|
+
left: "绿野平原四",
|
|
211
|
+
top: "绿野平原三"
|
|
212
|
+
},
|
|
213
|
+
"野猪巢穴": {
|
|
214
|
+
floor: 1,
|
|
215
|
+
areaName: "野猪巢穴",
|
|
216
|
+
type: "冒险区" /* 冒险区 */,
|
|
217
|
+
needLv: 1,
|
|
218
|
+
top: "绿野平原四"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
console.log(JSON.stringify(GensokyoMap.mapLocalData));
|
|
223
|
+
const userPoistionList = await ctx.database.get("smm_gensokyo_map_position", {});
|
|
224
|
+
const poistionTemp = {};
|
|
225
|
+
userPoistionList.forEach((poistion) => {
|
|
226
|
+
poistionTemp[poistion.userId] = poistion;
|
|
227
|
+
});
|
|
228
|
+
GensokyoMap.userCurrentLoal = poistionTemp;
|
|
229
|
+
},
|
|
230
|
+
/** 获取层的数据 */
|
|
231
|
+
getBaseFloorLocal(floor) {
|
|
232
|
+
return GensokyoMap.mapLocalData[floor] || null;
|
|
233
|
+
},
|
|
234
|
+
/** 获取用户当前区域信息 */
|
|
235
|
+
getUserCurrentArea(userid) {
|
|
236
|
+
const { floor, areaName } = GensokyoMap.userCurrentLoal[userid] || {};
|
|
237
|
+
if (!(floor && areaName)) return null;
|
|
238
|
+
return GensokyoMap.mapLocalData[floor][areaName] || null;
|
|
239
|
+
},
|
|
240
|
+
/** 初始化用户位置 */
|
|
241
|
+
initUserPoistion(session, userData) {
|
|
242
|
+
if (!GensokyoMap.userCurrentLoal[session.userId]) {
|
|
243
|
+
GensokyoMap.userCurrentLoal[session.userId] = {
|
|
244
|
+
userId: session.userId,
|
|
245
|
+
floor: 1,
|
|
246
|
+
areaName: "传送门",
|
|
247
|
+
moveing: false,
|
|
248
|
+
playName: userData.playName
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
GensokyoMap.setLocalStoragePoistionData(session.userId);
|
|
252
|
+
},
|
|
253
|
+
/** 位置信息存储到数据库 */
|
|
254
|
+
async setLocalStoragePoistionData(userId) {
|
|
255
|
+
const poistionData = { ...GensokyoMap.userCurrentLoal[userId] };
|
|
256
|
+
if (poistionData) {
|
|
257
|
+
const [localData] = await GensokyoMap.ctx.database.get("smm_gensokyo_map_position", { userId });
|
|
258
|
+
if (!localData) {
|
|
259
|
+
await GensokyoMap.ctx.database.create("smm_gensokyo_map_position", poistionData);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
delete poistionData.userId;
|
|
263
|
+
await GensokyoMap.ctx.database.set("smm_gensokyo_map_position", { userId }, poistionData);
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
/** 用户移动 */
|
|
267
|
+
async move(session, type, fn) {
|
|
268
|
+
const userCurrentArea = GensokyoMap.userCurrentLoal[session.userId] || {};
|
|
269
|
+
const { floor, areaName, moveing } = userCurrentArea;
|
|
270
|
+
if (moveing) {
|
|
271
|
+
await session.send("当前移动冷却中,请稍等...");
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
if (!(floor && areaName)) {
|
|
275
|
+
await session.send("您当前位置有误,请使用(还没写好的指令)脱离卡死...");
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
userCurrentArea.moveing = true;
|
|
279
|
+
const nowPosition = GensokyoMap.mapLocalData[floor][areaName];
|
|
280
|
+
if (!nowPosition[type]) {
|
|
281
|
+
await session.send("抱歉,此路不通!");
|
|
282
|
+
userCurrentArea.moveing = false;
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
const newArea = GensokyoMap.mapLocalData[floor][nowPosition[type]];
|
|
286
|
+
if (!newArea) {
|
|
287
|
+
await session.send("进入失败,地图中不存在 " + nowPosition[type] + " 这个区域。");
|
|
288
|
+
userCurrentArea.moveing = false;
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (newArea.type == "禁用" /* 禁用 */) {
|
|
292
|
+
await session.send(`该区域暂时未开放...`);
|
|
293
|
+
userCurrentArea.moveing = false;
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (newArea.needLv > 1) {
|
|
297
|
+
await session.send(`当前区域由于您的等级未达到最低要求,暂时无法进入。
|
|
298
|
+
需要等级:${newArea.needLv}级`);
|
|
299
|
+
userCurrentArea.moveing = false;
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
userCurrentArea.areaName = newArea.areaName;
|
|
303
|
+
const areaInfo = {
|
|
304
|
+
user: { ...userCurrentArea },
|
|
305
|
+
map: { ...newArea }
|
|
306
|
+
};
|
|
307
|
+
fn && await fn(areaInfo);
|
|
308
|
+
await delay(3e3);
|
|
309
|
+
GensokyoMap.setLocalStoragePoistionData(session.userId);
|
|
310
|
+
userCurrentArea.moveing = false;
|
|
311
|
+
return;
|
|
312
|
+
},
|
|
313
|
+
/** 区域信息格式化 */
|
|
314
|
+
userAreaTextFormat(gameName, data) {
|
|
315
|
+
const liveUser = [];
|
|
316
|
+
Object.keys(GensokyoMap.userCurrentLoal).forEach((userId) => {
|
|
317
|
+
const areaItem = GensokyoMap.userCurrentLoal[userId];
|
|
318
|
+
if (areaItem.areaName == data.map.areaName && areaItem.floor == data.map.floor) {
|
|
319
|
+
if (gameName !== areaItem.playName) {
|
|
320
|
+
liveUser.push(areaItem.playName);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
const str = `${gameName}[萌新] 当前位置:
|
|
325
|
+
`;
|
|
326
|
+
const mapInfo = `区域:【${data.map.areaName}】
|
|
327
|
+
` + (data.map.info ? data.map.info + "\n\n" : "\n") + (data.map.top ? `上:【${data.map.top}】
|
|
328
|
+
` : "") + (data.map.down ? `下:【${data.map.down}】
|
|
329
|
+
` : "") + (data.map.left ? `左:【${data.map.left}】
|
|
330
|
+
` : "") + (data.map.right ? `右:【${data.map.right}】
|
|
331
|
+
` : "") + (data.map.type == "传送门" /* 传送门 */ ? `
|
|
332
|
+
[!]传送门区域` : "") + (data.map.shopName ? `
|
|
333
|
+
[!]存在商店:${data.map.shopName}` : "") + (data.map.npc ? `
|
|
334
|
+
[!]存在npc:${data.map.npc.join("、")}` : "") + (data.map.monster ? `
|
|
335
|
+
[!]存在野怪:${data.map.monster.map((i) => `lv.${i.lv} ${i.name}`).join("、")}` : "") + (liveUser.length ? `
|
|
336
|
+
[!]区域玩家:${liveUser.length > 3 ? liveUser.slice(0, 3).join("、") + `...等${liveUser.length}` : liveUser.join("、")}` : "");
|
|
337
|
+
return str + mapInfo;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// src/users.ts
|
|
342
|
+
var UserOccDict = {
|
|
343
|
+
["剑士" /* 剑士 */]: {
|
|
344
|
+
info: "擅长近战攻击,拥有强大的属性能力",
|
|
345
|
+
initStatus: {
|
|
346
|
+
userId: "",
|
|
347
|
+
playName: "",
|
|
348
|
+
type: "剑士" /* 剑士 */,
|
|
349
|
+
exp: 0,
|
|
350
|
+
maxExp: 100,
|
|
351
|
+
lv: 1,
|
|
352
|
+
hp: 120,
|
|
353
|
+
maxHp: 120,
|
|
354
|
+
mp: 80,
|
|
355
|
+
maxMp: 80,
|
|
356
|
+
pp: 100,
|
|
357
|
+
maxPp: 100,
|
|
358
|
+
atk: 12,
|
|
359
|
+
def: 5,
|
|
360
|
+
chr: 50,
|
|
361
|
+
ghd: 1.2,
|
|
362
|
+
speed: 5,
|
|
363
|
+
evasion: 100,
|
|
364
|
+
hit: 1e3
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
["法师" /* 法师 */]: {
|
|
368
|
+
info: "精通元素魔法,能够打出爆发伤害",
|
|
369
|
+
initStatus: {
|
|
370
|
+
userId: "",
|
|
371
|
+
playName: "",
|
|
372
|
+
type: "法师" /* 法师 */,
|
|
373
|
+
exp: 0,
|
|
374
|
+
maxExp: 100,
|
|
375
|
+
lv: 1,
|
|
376
|
+
hp: 100,
|
|
377
|
+
maxHp: 100,
|
|
378
|
+
mp: 100,
|
|
379
|
+
maxMp: 100,
|
|
380
|
+
pp: 100,
|
|
381
|
+
maxPp: 100,
|
|
382
|
+
atk: 10,
|
|
383
|
+
def: 2,
|
|
384
|
+
chr: 50,
|
|
385
|
+
ghd: 1.2,
|
|
386
|
+
speed: 5,
|
|
387
|
+
evasion: 100,
|
|
388
|
+
hit: 1e3
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
["刺客" /* 刺客 */]: {
|
|
392
|
+
info: "迅捷攻击,高闪避值的高敏玩家",
|
|
393
|
+
initStatus: {
|
|
394
|
+
userId: "",
|
|
395
|
+
playName: "",
|
|
396
|
+
type: "刺客" /* 刺客 */,
|
|
397
|
+
exp: 0,
|
|
398
|
+
maxExp: 100,
|
|
399
|
+
lv: 1,
|
|
400
|
+
hp: 90,
|
|
401
|
+
maxHp: 90,
|
|
402
|
+
mp: 70,
|
|
403
|
+
maxMp: 70,
|
|
404
|
+
pp: 100,
|
|
405
|
+
maxPp: 100,
|
|
406
|
+
atk: 8,
|
|
407
|
+
def: 2,
|
|
408
|
+
chr: 80,
|
|
409
|
+
ghd: 1.3,
|
|
410
|
+
speed: 6,
|
|
411
|
+
evasion: 120,
|
|
412
|
+
hit: 1e3
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
var User = {
|
|
417
|
+
config: {},
|
|
418
|
+
ctx: {},
|
|
419
|
+
userTempData: {},
|
|
420
|
+
async init(config, ctx) {
|
|
421
|
+
User.config = config;
|
|
422
|
+
User.ctx = ctx;
|
|
423
|
+
ctx.model.extend(
|
|
424
|
+
"smm_gensokyo_user_attribute",
|
|
425
|
+
{
|
|
426
|
+
userId: "string",
|
|
427
|
+
playName: "string",
|
|
428
|
+
type: "string",
|
|
429
|
+
exp: "integer",
|
|
430
|
+
lv: "integer",
|
|
431
|
+
hp: "integer",
|
|
432
|
+
mp: "integer",
|
|
433
|
+
pp: "integer"
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
primary: "userId",
|
|
437
|
+
autoInc: false
|
|
438
|
+
}
|
|
439
|
+
);
|
|
440
|
+
const userData = await ctx.database.get("smm_gensokyo_user_attribute", {});
|
|
441
|
+
const temp = {};
|
|
442
|
+
userData.forEach((item) => {
|
|
443
|
+
temp[item.userId] = item;
|
|
444
|
+
});
|
|
445
|
+
User.userTempData = temp;
|
|
446
|
+
},
|
|
447
|
+
/** 获取角色基础属性 */
|
|
448
|
+
async getUserAttribute(session) {
|
|
449
|
+
if (!User.userTempData[session.userId]) {
|
|
450
|
+
await session.send("未创建账户,请发送 /开始注册 完成账号的注册!");
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
return User.getUserAddLvAttribute(session.userId);
|
|
454
|
+
},
|
|
455
|
+
/** 获取角色实际等级属性数据 */
|
|
456
|
+
getUserAddLvAttribute(userId) {
|
|
457
|
+
const UserDict = User.userTempData[userId];
|
|
458
|
+
if (!UserDict) return null;
|
|
459
|
+
const UserData = {
|
|
460
|
+
...UserOccDict[UserDict.type].initStatus,
|
|
461
|
+
lv: UserDict.lv,
|
|
462
|
+
hp: UserDict.hp,
|
|
463
|
+
exp: UserDict.exp,
|
|
464
|
+
pp: UserDict.pp,
|
|
465
|
+
playName: UserDict.playName,
|
|
466
|
+
userId: UserDict.userId
|
|
467
|
+
};
|
|
468
|
+
const lv = UserData.lv;
|
|
469
|
+
const benchmark = {
|
|
470
|
+
10: {
|
|
471
|
+
hp: 1.4,
|
|
472
|
+
maxHp: 1.4,
|
|
473
|
+
mp: 1.2,
|
|
474
|
+
maxMp: 1.2,
|
|
475
|
+
atk: 1.2,
|
|
476
|
+
def: 1.1,
|
|
477
|
+
chr: 1.1,
|
|
478
|
+
evasion: 1.2,
|
|
479
|
+
hit: 1.2,
|
|
480
|
+
ghd: 1,
|
|
481
|
+
speed: 1.05
|
|
482
|
+
},
|
|
483
|
+
20: {
|
|
484
|
+
hp: 1.35,
|
|
485
|
+
maxHp: 1.35,
|
|
486
|
+
mp: 1.1,
|
|
487
|
+
maxMp: 1.1,
|
|
488
|
+
atk: 1.1,
|
|
489
|
+
def: 1.1,
|
|
490
|
+
chr: 1.1,
|
|
491
|
+
evasion: 1.1,
|
|
492
|
+
hit: 1.1,
|
|
493
|
+
ghd: 1,
|
|
494
|
+
speed: 1.05
|
|
495
|
+
},
|
|
496
|
+
40: {
|
|
497
|
+
hp: 1.2,
|
|
498
|
+
maxHp: 1.2,
|
|
499
|
+
mp: 1.05,
|
|
500
|
+
maxMp: 1.05,
|
|
501
|
+
atk: 1.1,
|
|
502
|
+
def: 1.05,
|
|
503
|
+
chr: 1.05,
|
|
504
|
+
evasion: 1.05,
|
|
505
|
+
hit: 1.05,
|
|
506
|
+
ghd: 1.05,
|
|
507
|
+
speed: 1.05
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
const temp = {};
|
|
511
|
+
const lvScope = Object.keys(benchmark).reverse().find((item) => Number(item) < lv) || 10;
|
|
512
|
+
const useBenchmark = benchmark[lvScope];
|
|
513
|
+
Object.keys(UserData).forEach((i) => {
|
|
514
|
+
temp[i] = UserData[i];
|
|
515
|
+
if (useBenchmark[i]) {
|
|
516
|
+
temp[i] += Math.floor(temp[i] * (useBenchmark[i] - 1) * (lv - 1));
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
return temp;
|
|
520
|
+
},
|
|
521
|
+
/** 通过 userId 获取角色属性 */
|
|
522
|
+
getUserAttributeByUserId(userId) {
|
|
523
|
+
return User.getUserAddLvAttribute(userId) || null;
|
|
524
|
+
},
|
|
525
|
+
/** 创建游戏账号 */
|
|
526
|
+
async createPlayUser(session) {
|
|
527
|
+
const [data] = await User.ctx.database.get("smm_gensokyo_user_attribute", { userId: session.userId });
|
|
528
|
+
if (data) {
|
|
529
|
+
await session.send("已存在账号,请勿重复创建!");
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
await session.send("请输入自己的游戏昵称:(60s)");
|
|
533
|
+
const playname = await session.prompt(6e4);
|
|
534
|
+
if (playname == void 0) return;
|
|
535
|
+
const [repeat] = await User.ctx.database.get("smm_gensokyo_user_attribute", { playName: playname.trim() });
|
|
536
|
+
if (repeat) {
|
|
537
|
+
await session.send("名字重复,请更换一个名字。");
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
if (playname.trim().length > 6 || playname.trim().length < 1) {
|
|
541
|
+
await session.send("名字长度有问题,要求小于 6个字,大于 1个字");
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
await session.send(`请输入要专职的职业:(60s)
|
|
545
|
+
${Object.keys(UserOccDict).map((i) => `【${i}】:${UserOccDict[i].info}`).join("\n")}`);
|
|
546
|
+
let jobType = await session.prompt(6e4);
|
|
547
|
+
if (jobType == void 0) return;
|
|
548
|
+
while (!Object.keys(UserOccDict).includes(jobType)) {
|
|
549
|
+
await session.send("未找到该职业,请重新选择!");
|
|
550
|
+
jobType = await session.prompt(6e4);
|
|
551
|
+
}
|
|
552
|
+
const temp = {
|
|
553
|
+
userId: session.userId,
|
|
554
|
+
playName: playname.trim(),
|
|
555
|
+
type: jobType,
|
|
556
|
+
hp: UserOccDict[jobType].initStatus.hp,
|
|
557
|
+
pp: UserOccDict[jobType].initStatus.pp,
|
|
558
|
+
mp: UserOccDict[jobType].initStatus.mp,
|
|
559
|
+
lv: 1,
|
|
560
|
+
exp: 0
|
|
561
|
+
};
|
|
562
|
+
User.ctx.database.create("smm_gensokyo_user_attribute", temp);
|
|
563
|
+
User.userTempData[session.userId] = temp;
|
|
564
|
+
await session.send("创建成功!\n" + User.userAttributeTextFormat(session.userId));
|
|
565
|
+
},
|
|
566
|
+
/** 信息格式化 */
|
|
567
|
+
userAttributeTextFormat(userId) {
|
|
568
|
+
if (!User.userTempData[userId]) {
|
|
569
|
+
return "没有找到您的角色信息";
|
|
570
|
+
}
|
|
571
|
+
const temp = User.getUserAttributeByUserId(userId);
|
|
572
|
+
return `昵称:${temp.playName}
|
|
573
|
+
职位:${temp.type}
|
|
574
|
+
等级:${temp.lv} (${temp.exp}/${temp.maxExp})
|
|
575
|
+
-----------------
|
|
576
|
+
【生命值】${temp.hp}/${temp.maxHp}
|
|
577
|
+
【魔法值】${temp.mp}/${temp.maxMp}
|
|
578
|
+
【活力值】${temp.pp}/${temp.maxPp}
|
|
579
|
+
-----------------
|
|
580
|
+
【攻击力】${temp.atk} (+0)
|
|
581
|
+
【防御力】${temp.def} (+0)
|
|
582
|
+
【命中值】${temp.hit} (+0)
|
|
583
|
+
【速度值】${temp.speed} (+0)
|
|
584
|
+
【闪避值】${temp.evasion} (+0)
|
|
585
|
+
【暴击率】${(temp.chr / 10).toFixed(1)}% (+0%)
|
|
586
|
+
【暴击伤害】${(temp.ghd * 100).toFixed(1)}% (+0%)`;
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
|
|
590
|
+
// src/monster.ts
|
|
591
|
+
var Monster = {
|
|
592
|
+
config: {},
|
|
593
|
+
ctx: {},
|
|
594
|
+
monsterTempData: {},
|
|
595
|
+
async init(config, ctx) {
|
|
596
|
+
Monster.config = config;
|
|
597
|
+
Monster.ctx = ctx;
|
|
598
|
+
ctx.model.extend(
|
|
599
|
+
"smm_gensokyo_monster_attribute",
|
|
600
|
+
{
|
|
601
|
+
id: "integer",
|
|
602
|
+
name: "string",
|
|
603
|
+
info: "string",
|
|
604
|
+
type: "string",
|
|
605
|
+
hp: "integer",
|
|
606
|
+
maxHp: "integer",
|
|
607
|
+
mp: "integer",
|
|
608
|
+
maxMp: "integer",
|
|
609
|
+
atk: "integer",
|
|
610
|
+
def: "integer",
|
|
611
|
+
chr: "integer",
|
|
612
|
+
evasion: "integer",
|
|
613
|
+
hit: "integer",
|
|
614
|
+
ghd: "integer",
|
|
615
|
+
speed: "integer"
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
primary: "id",
|
|
619
|
+
autoInc: false
|
|
620
|
+
}
|
|
621
|
+
);
|
|
622
|
+
const monsterData = await ctx.database.get("smm_gensokyo_monster_attribute", {});
|
|
623
|
+
if (monsterData.length == 0) {
|
|
624
|
+
Monster.monsterTempData = Monster._createInitMonsterData();
|
|
625
|
+
} else {
|
|
626
|
+
const temp = {};
|
|
627
|
+
monsterData.forEach((item) => {
|
|
628
|
+
temp[item.id] = item;
|
|
629
|
+
});
|
|
630
|
+
Monster.monsterTempData = temp;
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
/** 赋予原始的怪物数据 */
|
|
634
|
+
_createInitMonsterData() {
|
|
635
|
+
const monsterData = {
|
|
636
|
+
"小蜜蜂": {
|
|
637
|
+
name: "小蜜蜂",
|
|
638
|
+
type: "野怪" /* 野怪 */,
|
|
639
|
+
info: "幻想乡一层常见的生物",
|
|
640
|
+
hp: 50,
|
|
641
|
+
maxHp: 50,
|
|
642
|
+
mp: 30,
|
|
643
|
+
maxMp: 30,
|
|
644
|
+
atk: 7,
|
|
645
|
+
def: 2,
|
|
646
|
+
chr: 50,
|
|
647
|
+
evasion: 100,
|
|
648
|
+
hit: 1e3,
|
|
649
|
+
ghd: 1.2,
|
|
650
|
+
speed: 4
|
|
651
|
+
},
|
|
652
|
+
"小蜘蛛": {
|
|
653
|
+
name: "小蜘蛛",
|
|
654
|
+
type: "野怪" /* 野怪 */,
|
|
655
|
+
info: "幻想乡一层常见的生物",
|
|
656
|
+
hp: 55,
|
|
657
|
+
maxHp: 55,
|
|
658
|
+
mp: 30,
|
|
659
|
+
maxMp: 30,
|
|
660
|
+
atk: 10,
|
|
661
|
+
def: 3,
|
|
662
|
+
chr: 50,
|
|
663
|
+
evasion: 200,
|
|
664
|
+
hit: 1e3,
|
|
665
|
+
ghd: 1.2,
|
|
666
|
+
speed: 4
|
|
667
|
+
},
|
|
668
|
+
"dora": {
|
|
669
|
+
name: "dora",
|
|
670
|
+
type: "野怪" /* 野怪 */,
|
|
671
|
+
info: "偶尔出没在一层世界的奇怪生物",
|
|
672
|
+
hp: 88,
|
|
673
|
+
maxHp: 88,
|
|
674
|
+
mp: 10,
|
|
675
|
+
maxMp: 10,
|
|
676
|
+
atk: 20,
|
|
677
|
+
def: 5,
|
|
678
|
+
chr: 200,
|
|
679
|
+
evasion: 300,
|
|
680
|
+
hit: 1e3,
|
|
681
|
+
ghd: 1.2,
|
|
682
|
+
speed: 4
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
return monsterData;
|
|
686
|
+
},
|
|
687
|
+
getMonsterAttributeData(monsterName, lv) {
|
|
688
|
+
const monster = Monster.monsterTempData[monsterName];
|
|
689
|
+
if (!monster) return null;
|
|
690
|
+
const benchmark = {
|
|
691
|
+
10: {
|
|
692
|
+
hp: 1.4,
|
|
693
|
+
maxHp: 1.4,
|
|
694
|
+
mp: 1.2,
|
|
695
|
+
maxMp: 1.2,
|
|
696
|
+
atk: 1.2,
|
|
697
|
+
def: 1.1,
|
|
698
|
+
chr: 1.1,
|
|
699
|
+
evasion: 1.2,
|
|
700
|
+
hit: 1.2,
|
|
701
|
+
ghd: 1,
|
|
702
|
+
speed: 1.05
|
|
703
|
+
},
|
|
704
|
+
20: {
|
|
705
|
+
hp: 1.35,
|
|
706
|
+
maxHp: 1.35,
|
|
707
|
+
mp: 1.1,
|
|
708
|
+
maxMp: 1.1,
|
|
709
|
+
atk: 1.1,
|
|
710
|
+
def: 1.1,
|
|
711
|
+
chr: 1.1,
|
|
712
|
+
evasion: 1.1,
|
|
713
|
+
hit: 1.1,
|
|
714
|
+
ghd: 1,
|
|
715
|
+
speed: 1.05
|
|
716
|
+
},
|
|
717
|
+
40: {
|
|
718
|
+
hp: 1.2,
|
|
719
|
+
maxHp: 1.2,
|
|
720
|
+
mp: 1.05,
|
|
721
|
+
maxMp: 1.05,
|
|
722
|
+
atk: 1.1,
|
|
723
|
+
def: 1.05,
|
|
724
|
+
chr: 1.05,
|
|
725
|
+
evasion: 1.05,
|
|
726
|
+
hit: 1.05,
|
|
727
|
+
ghd: 1.05,
|
|
728
|
+
speed: 1.05
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
const temp = { lv };
|
|
732
|
+
const lvScope = Object.keys(benchmark).reverse().find((item) => Number(item) < lv) || 10;
|
|
733
|
+
const useBenchmark = benchmark[lvScope];
|
|
734
|
+
console.log(useBenchmark);
|
|
735
|
+
Object.keys(monster).forEach((i) => {
|
|
736
|
+
temp[i] = monster[i];
|
|
737
|
+
if (useBenchmark[i]) {
|
|
738
|
+
temp[i] += Math.floor(temp[i] * (useBenchmark[i] - 1) * (lv - 1));
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
return temp;
|
|
742
|
+
},
|
|
743
|
+
/** 格式化怪物属性数据 */
|
|
744
|
+
monsterAttributeTextFormat(monster) {
|
|
745
|
+
const { name: name2, type, lv, hp, maxHp, mp, maxMp, atk, def, chr, evasion, hit, ghd, speed, info } = monster;
|
|
746
|
+
const attributeText = `Lv.${lv}【${name2}】
|
|
747
|
+
|
|
748
|
+
怪物类型:${type}
|
|
749
|
+
生命值:${hp}/${maxHp}
|
|
750
|
+
魔法值:${mp}/${maxMp}
|
|
751
|
+
攻击力:${atk}
|
|
752
|
+
防御力:${def}
|
|
753
|
+
闪避值:${evasion}
|
|
754
|
+
命中值:${hit}
|
|
755
|
+
速度值:${speed}
|
|
756
|
+
暴击率:${(chr / 10).toFixed(1)}%
|
|
757
|
+
爆伤倍率:${(ghd * 100).toFixed(0)}%` + (info ? "\n\n" + info : "");
|
|
758
|
+
return attributeText;
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
// src/utlis.ts
|
|
763
|
+
var random = /* @__PURE__ */ __name((min, max) => {
|
|
764
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
765
|
+
}, "random");
|
|
766
|
+
var generateHealthDisplay = /* @__PURE__ */ __name((current, total) => {
|
|
767
|
+
const ratio = current / total;
|
|
768
|
+
const displayLength = 10;
|
|
769
|
+
const filledLength = Math.floor(ratio * displayLength);
|
|
770
|
+
const unfilledLength = displayLength - filledLength;
|
|
771
|
+
const filled = "■".repeat(filledLength);
|
|
772
|
+
const unfilled = "□".repeat(unfilledLength);
|
|
773
|
+
return filled + unfilled;
|
|
774
|
+
}, "generateHealthDisplay");
|
|
775
|
+
|
|
776
|
+
// src/damage.ts
|
|
777
|
+
var Damage = class {
|
|
778
|
+
static {
|
|
779
|
+
__name(this, "Damage");
|
|
780
|
+
}
|
|
781
|
+
config;
|
|
782
|
+
constructor(agent, realHarm = false) {
|
|
783
|
+
this.config = {
|
|
784
|
+
agent: { self: { ...agent.self }, goal: { ...agent.goal } },
|
|
785
|
+
harm: 0,
|
|
786
|
+
default_harm: agent.self.atk + agent.self.gain.atk,
|
|
787
|
+
isRealHarm: realHarm,
|
|
788
|
+
isEvasion: false,
|
|
789
|
+
isCsp: false,
|
|
790
|
+
isBadDef: false
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
/** 伤害判定前 */
|
|
794
|
+
before(fn) {
|
|
795
|
+
fn && fn(this.config);
|
|
796
|
+
return this;
|
|
797
|
+
}
|
|
798
|
+
/** 真实伤害判定 */
|
|
799
|
+
beforRealHarm(fn) {
|
|
800
|
+
fn && fn(this.config);
|
|
801
|
+
if (this.config.isEvasion) {
|
|
802
|
+
this.config.harm = this.config.default_harm;
|
|
803
|
+
}
|
|
804
|
+
return this;
|
|
805
|
+
}
|
|
806
|
+
/** 是否闪避判定 */
|
|
807
|
+
evasion(fn) {
|
|
808
|
+
const { self, goal } = this.config.agent;
|
|
809
|
+
if (this.config.isRealHarm) return this;
|
|
810
|
+
const evaVal = (goal.evasion - (self.hit - 1e3)) / 10;
|
|
811
|
+
if (random(0, 100) <= evaVal) {
|
|
812
|
+
this.config.isEvasion = true;
|
|
813
|
+
fn && fn(this.config);
|
|
814
|
+
return this;
|
|
815
|
+
}
|
|
816
|
+
fn && fn(this.config);
|
|
817
|
+
return this;
|
|
818
|
+
}
|
|
819
|
+
/** 是否暴击判定 */
|
|
820
|
+
csp(fn) {
|
|
821
|
+
const { self, goal } = this.config.agent;
|
|
822
|
+
if (this.config.isRealHarm) return this;
|
|
823
|
+
if (this.config.isEvasion) return this;
|
|
824
|
+
const cspVal = (self.chr - goal.csr) / 10;
|
|
825
|
+
if (random(0, 100) <= cspVal) {
|
|
826
|
+
this.config.isCsp = true;
|
|
827
|
+
this.config.harm = Math.floor(this.config.default_harm * self.ghd);
|
|
828
|
+
fn && fn(this.config);
|
|
829
|
+
return this;
|
|
830
|
+
}
|
|
831
|
+
this.config.harm = this.config.default_harm;
|
|
832
|
+
fn && fn(this.config);
|
|
833
|
+
return this;
|
|
834
|
+
}
|
|
835
|
+
/** 防御结算 */
|
|
836
|
+
beforDef(fn) {
|
|
837
|
+
const { goal } = this.config.agent;
|
|
838
|
+
if (this.config.isRealHarm) return this;
|
|
839
|
+
if (this.config.isEvasion) return this;
|
|
840
|
+
const dpVal = goal.def;
|
|
841
|
+
fn && fn(this.config);
|
|
842
|
+
if (this.config.harm - dpVal > 0) {
|
|
843
|
+
this.config.harm -= dpVal;
|
|
844
|
+
} else {
|
|
845
|
+
this.config.isBadDef = true;
|
|
846
|
+
this.config.harm = 1;
|
|
847
|
+
}
|
|
848
|
+
return this;
|
|
849
|
+
}
|
|
850
|
+
result(fn) {
|
|
851
|
+
this.before((val) => {
|
|
852
|
+
fn?.before && fn.before(val);
|
|
853
|
+
}).beforRealHarm((val) => {
|
|
854
|
+
fn?.beforRealHarm && fn.beforRealHarm(val);
|
|
855
|
+
}).evasion((val) => {
|
|
856
|
+
fn?.evasion && fn.evasion(val);
|
|
857
|
+
}).csp((val) => {
|
|
858
|
+
fn?.csp && fn.csp(val);
|
|
859
|
+
}).beforDef((val) => {
|
|
860
|
+
fn?.beforDef && fn.beforDef(val);
|
|
861
|
+
});
|
|
862
|
+
return this.config;
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
function giveDamage(self, goal, damage) {
|
|
866
|
+
if (goal.hp - damage.harm > 0) {
|
|
867
|
+
goal.hp -= damage.harm;
|
|
868
|
+
return damage.harm;
|
|
869
|
+
} else {
|
|
870
|
+
const lostHp = goal.hp;
|
|
871
|
+
goal.hp = 0;
|
|
872
|
+
return lostHp;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
__name(giveDamage, "giveDamage");
|
|
876
|
+
|
|
877
|
+
// src/battle.ts
|
|
878
|
+
var BattleData = {
|
|
879
|
+
config: {},
|
|
880
|
+
ctx: {},
|
|
881
|
+
historyTemp: {},
|
|
882
|
+
lastPlay: {},
|
|
883
|
+
teamTemp: {},
|
|
884
|
+
init(config, ctx) {
|
|
885
|
+
this.config = config;
|
|
886
|
+
this.ctx = ctx;
|
|
887
|
+
},
|
|
888
|
+
/** 玩家是否正在战斗 */
|
|
889
|
+
isBattle(session) {
|
|
890
|
+
return !!BattleData.lastPlay[session.userId];
|
|
891
|
+
},
|
|
892
|
+
/** 玩家是否在队伍中 */
|
|
893
|
+
isTeam(session) {
|
|
894
|
+
return !!BattleData.teamTemp[session.userId];
|
|
895
|
+
},
|
|
896
|
+
/** 创建战斗-与怪物 */
|
|
897
|
+
async createBattleByMonster(session, goal) {
|
|
898
|
+
if (BattleData.isBattle(session)) {
|
|
899
|
+
await session.send("当前正在战斗,还不能逃脱!");
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
const battle_user = [];
|
|
903
|
+
const battle_monsterList = [];
|
|
904
|
+
const playUser = [];
|
|
905
|
+
if (BattleData.isTeam(session) && BattleData.teamTemp[session.userId].identity == "队员") {
|
|
906
|
+
await session.send("你不是队伍的队长,无法主动操作战斗!");
|
|
907
|
+
return;
|
|
908
|
+
} else if (BattleData.isTeam(session)) {
|
|
909
|
+
Object.keys(BattleData.teamTemp).forEach((item) => {
|
|
910
|
+
if (BattleData.teamTemp[item].for == session.userId) {
|
|
911
|
+
playUser.push(item);
|
|
912
|
+
battle_user.push(initBattleAttribute(User.getUserAttributeByUserId(item)));
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
} else {
|
|
916
|
+
playUser.push(session.userId);
|
|
917
|
+
battle_user.push(initBattleAttribute(User.getUserAttributeByUserId(session.userId)));
|
|
918
|
+
}
|
|
919
|
+
goal.forEach((item) => {
|
|
920
|
+
battle_monsterList.push(initBattleAttribute(Monster.getMonsterAttributeData(item.name, item.lv)));
|
|
921
|
+
});
|
|
922
|
+
playUser.forEach((userId) => {
|
|
923
|
+
BattleData.lastPlay[userId] = {
|
|
924
|
+
self: battle_user.map((i) => ({ ...i, for: "self" })),
|
|
925
|
+
goal: battle_monsterList.map((i) => ({ ...i, for: "goal" }))
|
|
926
|
+
};
|
|
927
|
+
});
|
|
928
|
+
await session.send(`开始与 ${goal.map((i) => i.name).join("、")} 进行战斗`);
|
|
929
|
+
console.log(BattleData.lastPlay[session.userId]);
|
|
930
|
+
},
|
|
931
|
+
/** 文本化当前战况 */
|
|
932
|
+
battleSituationTextFormat(team) {
|
|
933
|
+
const selfTemp = [];
|
|
934
|
+
const goalTemp = [];
|
|
935
|
+
team.self.forEach((item) => {
|
|
936
|
+
if (item.hp > 0) {
|
|
937
|
+
selfTemp.push(`lv.${item.lv}[${item.name}]:
|
|
938
|
+
${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${item.maxHp + item.gain.maxHp})`);
|
|
939
|
+
} else {
|
|
940
|
+
selfTemp.push(`lv.${item.lv}[${item.name}]:已阵亡`);
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
team.goal.forEach((item) => {
|
|
944
|
+
if (item.hp > 0) {
|
|
945
|
+
goalTemp.push(`lv.${item.lv}[${item.name}]:
|
|
946
|
+
${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${item.maxHp + item.gain.maxHp})`);
|
|
947
|
+
} else {
|
|
948
|
+
goalTemp.push(`lv.${item.lv}[${item.name}]:已阵亡`);
|
|
949
|
+
}
|
|
950
|
+
});
|
|
951
|
+
return `[当前战况]
|
|
952
|
+
我方阵容:
|
|
953
|
+
` + selfTemp.join("\n") + "\n\n敌方阵容:\n" + goalTemp.join("\n");
|
|
954
|
+
},
|
|
955
|
+
/** 判断输赢 */
|
|
956
|
+
playOver(team) {
|
|
957
|
+
const self = team.self.every((item) => item.hp <= 0);
|
|
958
|
+
const goal = team.goal.every((item) => item.hp <= 0);
|
|
959
|
+
if (self && goal) {
|
|
960
|
+
return { over: true, type: "平局" };
|
|
961
|
+
} else if (self) {
|
|
962
|
+
return { over: true, type: "敌方赢" };
|
|
963
|
+
} else if (goal) {
|
|
964
|
+
return { over: true, type: "我方赢" };
|
|
965
|
+
}
|
|
966
|
+
return { over: false, type: "未结束" };
|
|
967
|
+
},
|
|
968
|
+
/** 清理战场 */
|
|
969
|
+
clearBattleData(session) {
|
|
970
|
+
if (BattleData.isTeam(session)) {
|
|
971
|
+
const userId = BattleData.teamTemp[session.userId].for;
|
|
972
|
+
Object.keys(BattleData.teamTemp).forEach((item) => {
|
|
973
|
+
if (BattleData.teamTemp[item].for == userId) {
|
|
974
|
+
delete BattleData.lastPlay[item];
|
|
975
|
+
}
|
|
976
|
+
});
|
|
977
|
+
} else {
|
|
978
|
+
delete BattleData.lastPlay[session.userId];
|
|
979
|
+
}
|
|
980
|
+
},
|
|
981
|
+
async play(session, atkType, select) {
|
|
982
|
+
if (!BattleData.isBattle(session)) {
|
|
983
|
+
await session.send("您并没有任何参与战斗。");
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
const currentBattle = BattleData.lastPlay[session.userId];
|
|
987
|
+
const allAgentList = [...currentBattle.goal, ...currentBattle.self].sort((a, b) => b.speed - a.speed);
|
|
988
|
+
const msgList = [];
|
|
989
|
+
for (const agent of allAgentList) {
|
|
990
|
+
if (agent.hp <= 0) continue;
|
|
991
|
+
let lifeGoalList = [];
|
|
992
|
+
if (agent.for == "self") {
|
|
993
|
+
lifeGoalList = currentBattle.goal.filter((item) => item.for == "goal" && item.hp > 0);
|
|
994
|
+
} else {
|
|
995
|
+
lifeGoalList = currentBattle.self.filter((item) => item.for == "self" && item.hp > 0);
|
|
996
|
+
}
|
|
997
|
+
if (!lifeGoalList.length) continue;
|
|
998
|
+
let selectGoal = {};
|
|
999
|
+
let isMy = false;
|
|
1000
|
+
if (agent.type == "玩家" && agent.userId == session.userId) {
|
|
1001
|
+
isMy = true;
|
|
1002
|
+
selectGoal = lifeGoalList.find((item) => item.name == select) || lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
|
|
1003
|
+
} else {
|
|
1004
|
+
selectGoal = lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
|
|
1005
|
+
}
|
|
1006
|
+
console.log(selectGoal);
|
|
1007
|
+
const damageInfo = new Damage({ self: agent, goal: selectGoal }).result({
|
|
1008
|
+
// 开始计算伤害前
|
|
1009
|
+
before: /* @__PURE__ */ __name((val) => {
|
|
1010
|
+
console.log(val);
|
|
1011
|
+
}, "before"),
|
|
1012
|
+
// 计算真实伤害前
|
|
1013
|
+
beforRealHarm: /* @__PURE__ */ __name((val) => {
|
|
1014
|
+
console.log(val);
|
|
1015
|
+
}, "beforRealHarm"),
|
|
1016
|
+
// 是否成功闪避
|
|
1017
|
+
evasion: /* @__PURE__ */ __name((val) => {
|
|
1018
|
+
console.log(val);
|
|
1019
|
+
}, "evasion"),
|
|
1020
|
+
// 是否成功暴击
|
|
1021
|
+
csp: /* @__PURE__ */ __name((val) => {
|
|
1022
|
+
console.log(val);
|
|
1023
|
+
}, "csp"),
|
|
1024
|
+
// 防御抵消前
|
|
1025
|
+
beforDef: /* @__PURE__ */ __name((val) => {
|
|
1026
|
+
console.log(val);
|
|
1027
|
+
}, "beforDef")
|
|
1028
|
+
});
|
|
1029
|
+
giveDamage(agent, selectGoal, damageInfo);
|
|
1030
|
+
msgList.push(
|
|
1031
|
+
`[${agent.type}]${agent.name} 使用普攻攻击了 [${selectGoal.type}]${selectGoal.name},造成了${damageInfo.harm}伤害。` + (damageInfo.isCsp ? `(暴击!)` : "") + (damageInfo.isEvasion ? `(闪避成功!)` : "") + (damageInfo.isBadDef ? `(未破防!)` : "")
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
await session.send(msgList.length ? `战斗记录:
|
|
1035
|
+
` + msgList.join("\n") : "");
|
|
1036
|
+
await session.send(BattleData.battleSituationTextFormat(currentBattle));
|
|
1037
|
+
const result = BattleData.playOver(currentBattle);
|
|
1038
|
+
if (result.over) {
|
|
1039
|
+
await session.send(result.type);
|
|
1040
|
+
BattleData.clearBattleData(session);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
function initBattleAttribute(data) {
|
|
1045
|
+
if ("playName" in data) {
|
|
1046
|
+
const userData = data;
|
|
1047
|
+
const temp = {
|
|
1048
|
+
userId: userData.userId,
|
|
1049
|
+
name: userData.playName,
|
|
1050
|
+
lv: userData.lv,
|
|
1051
|
+
type: "玩家",
|
|
1052
|
+
hp: userData.hp,
|
|
1053
|
+
maxHp: userData.maxHp,
|
|
1054
|
+
mp: userData.mp,
|
|
1055
|
+
maxMp: userData.maxMp,
|
|
1056
|
+
atk: userData.atk,
|
|
1057
|
+
def: userData.def,
|
|
1058
|
+
chr: userData.chr,
|
|
1059
|
+
ghd: userData.ghd,
|
|
1060
|
+
csr: 0,
|
|
1061
|
+
evasion: userData.evasion,
|
|
1062
|
+
hit: userData.hit,
|
|
1063
|
+
speed: userData.speed,
|
|
1064
|
+
gain: {
|
|
1065
|
+
maxHp: 0,
|
|
1066
|
+
maxMp: 0,
|
|
1067
|
+
atk: 0,
|
|
1068
|
+
def: 0,
|
|
1069
|
+
chr: 0,
|
|
1070
|
+
ghd: 0,
|
|
1071
|
+
evasion: 0,
|
|
1072
|
+
hit: 0,
|
|
1073
|
+
speed: 0
|
|
1074
|
+
},
|
|
1075
|
+
buff: []
|
|
1076
|
+
};
|
|
1077
|
+
return temp;
|
|
1078
|
+
} else {
|
|
1079
|
+
const monsterData = data;
|
|
1080
|
+
const temp = {
|
|
1081
|
+
name: monsterData.name,
|
|
1082
|
+
type: "怪物",
|
|
1083
|
+
lv: monsterData.lv,
|
|
1084
|
+
hp: monsterData.hp,
|
|
1085
|
+
maxHp: monsterData.maxHp,
|
|
1086
|
+
mp: monsterData.mp,
|
|
1087
|
+
maxMp: monsterData.maxMp,
|
|
1088
|
+
atk: monsterData.atk,
|
|
1089
|
+
def: monsterData.def,
|
|
1090
|
+
chr: monsterData.chr,
|
|
1091
|
+
ghd: monsterData.ghd,
|
|
1092
|
+
csr: 0,
|
|
1093
|
+
evasion: monsterData.evasion,
|
|
1094
|
+
hit: monsterData.hit,
|
|
1095
|
+
speed: monsterData.speed,
|
|
1096
|
+
gain: {
|
|
1097
|
+
maxHp: 0,
|
|
1098
|
+
maxMp: 0,
|
|
1099
|
+
atk: 0,
|
|
1100
|
+
def: 0,
|
|
1101
|
+
chr: 0,
|
|
1102
|
+
ghd: 0,
|
|
1103
|
+
evasion: 0,
|
|
1104
|
+
hit: 0,
|
|
1105
|
+
speed: 0
|
|
1106
|
+
},
|
|
1107
|
+
buff: []
|
|
1108
|
+
};
|
|
1109
|
+
return temp;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
__name(initBattleAttribute, "initBattleAttribute");
|
|
1113
|
+
|
|
1114
|
+
// src/index.ts
|
|
1115
|
+
var name = "smmcat-gensokyo";
|
|
1116
|
+
var inject = {
|
|
1117
|
+
required: ["monetary", "database"]
|
|
1118
|
+
};
|
|
1119
|
+
var Config = import_koishi.Schema.object({});
|
|
1120
|
+
function apply(ctx, config) {
|
|
1121
|
+
ctx.on("ready", () => {
|
|
1122
|
+
GensokyoMap.init(config, ctx);
|
|
1123
|
+
User.init(config, ctx);
|
|
1124
|
+
Monster.init(config, ctx);
|
|
1125
|
+
});
|
|
1126
|
+
ctx.command("幻想乡");
|
|
1127
|
+
ctx.command("幻想乡/移动.上").action(async ({ session }) => {
|
|
1128
|
+
console.log(session.userId.slice(0, 6) + "触发了上移动");
|
|
1129
|
+
const userData = await User.getUserAttribute(session);
|
|
1130
|
+
if (!userData) return;
|
|
1131
|
+
GensokyoMap.initUserPoistion(session, userData);
|
|
1132
|
+
GensokyoMap.move(session, "top" /* 上 */, async (val) => {
|
|
1133
|
+
await session.send("移动成功...");
|
|
1134
|
+
await session.send(GensokyoMap.userAreaTextFormat(userData.playName, val));
|
|
1135
|
+
});
|
|
1136
|
+
});
|
|
1137
|
+
ctx.command("幻想乡/移动.下").action(async ({ session }) => {
|
|
1138
|
+
console.log(session.userId.slice(0, 6) + "触发了下移动");
|
|
1139
|
+
const userData = await User.getUserAttribute(session);
|
|
1140
|
+
if (!userData) return;
|
|
1141
|
+
GensokyoMap.initUserPoistion(session, userData);
|
|
1142
|
+
GensokyoMap.move(session, "down" /* 下 */, async (val) => {
|
|
1143
|
+
await session.send("移动成功...");
|
|
1144
|
+
await session.send(GensokyoMap.userAreaTextFormat(userData.playName, val));
|
|
1145
|
+
});
|
|
1146
|
+
});
|
|
1147
|
+
ctx.command("幻想乡/移动.左").action(async ({ session }) => {
|
|
1148
|
+
console.log(session.userId.slice(0, 6) + "触发了左移动");
|
|
1149
|
+
const userData = await User.getUserAttribute(session);
|
|
1150
|
+
if (!userData) return;
|
|
1151
|
+
GensokyoMap.initUserPoistion(session, userData);
|
|
1152
|
+
GensokyoMap.move(session, "left" /* 左 */, async (val) => {
|
|
1153
|
+
await session.send("移动成功...");
|
|
1154
|
+
await session.send(GensokyoMap.userAreaTextFormat(userData.playName, val));
|
|
1155
|
+
});
|
|
1156
|
+
});
|
|
1157
|
+
ctx.command("幻想乡/移动.右").action(async ({ session }) => {
|
|
1158
|
+
console.log(session.userId.slice(0, 6) + "触发了右移动");
|
|
1159
|
+
const userData = await User.getUserAttribute(session);
|
|
1160
|
+
if (!userData) return;
|
|
1161
|
+
GensokyoMap.initUserPoistion(session, userData);
|
|
1162
|
+
GensokyoMap.move(session, "right" /* 右 */, async (val) => {
|
|
1163
|
+
await session.send("移动成功...");
|
|
1164
|
+
await session.send(GensokyoMap.userAreaTextFormat(userData.playName, val));
|
|
1165
|
+
});
|
|
1166
|
+
});
|
|
1167
|
+
ctx.command("幻想乡/位置").action(async ({ session }) => {
|
|
1168
|
+
const userData = await User.getUserAttribute(session);
|
|
1169
|
+
if (!userData) return;
|
|
1170
|
+
GensokyoMap.initUserPoistion(session, userData);
|
|
1171
|
+
const query = {
|
|
1172
|
+
user: GensokyoMap.userCurrentLoal[session.userId],
|
|
1173
|
+
map: GensokyoMap.getUserCurrentArea(session.userId)
|
|
1174
|
+
};
|
|
1175
|
+
if (!query.map) {
|
|
1176
|
+
return `无效区域`;
|
|
1177
|
+
}
|
|
1178
|
+
await session.send(GensokyoMap.userAreaTextFormat(userData.playName, query));
|
|
1179
|
+
});
|
|
1180
|
+
ctx.command("幻想乡/个人属性").action(async ({ session }) => {
|
|
1181
|
+
return `您的属性如下:
|
|
1182
|
+
` + User.userAttributeTextFormat(session.userId);
|
|
1183
|
+
});
|
|
1184
|
+
ctx.command("幻想乡/开始注册").action(async ({ session }) => {
|
|
1185
|
+
await User.createPlayUser(session);
|
|
1186
|
+
});
|
|
1187
|
+
ctx.command("幻想乡/查询怪物 <monster> <lv:posint>").action(async ({ session }, monster, lv) => {
|
|
1188
|
+
if (!monster) return `请输入要查询的怪物!`;
|
|
1189
|
+
if (!lv) lv = 1;
|
|
1190
|
+
const result = Monster.getMonsterAttributeData(monster, lv);
|
|
1191
|
+
if (!result) return `没有找到该怪物信息...`;
|
|
1192
|
+
return `查找成功!
|
|
1193
|
+
` + Monster.monsterAttributeTextFormat(result);
|
|
1194
|
+
});
|
|
1195
|
+
ctx.command("幻想乡/打怪遇敌 <goal>").action(async ({ session }, goal) => {
|
|
1196
|
+
const userData = await User.getUserAttribute(session);
|
|
1197
|
+
if (!userData) return;
|
|
1198
|
+
GensokyoMap.initUserPoistion(session, userData);
|
|
1199
|
+
const areaInfo = GensokyoMap.getUserCurrentArea(session.userId);
|
|
1200
|
+
if (goal) {
|
|
1201
|
+
if (!areaInfo.monster.map((i) => i.name).includes(goal)) {
|
|
1202
|
+
return `没有在该区域找到该怪物。`;
|
|
1203
|
+
}
|
|
1204
|
+
const selectMonster = areaInfo.monster.find((i) => i.name == goal);
|
|
1205
|
+
await BattleData.createBattleByMonster(session, [selectMonster]);
|
|
1206
|
+
} else {
|
|
1207
|
+
const selectMonster = areaInfo.monster;
|
|
1208
|
+
await BattleData.createBattleByMonster(session, selectMonster);
|
|
1209
|
+
}
|
|
1210
|
+
});
|
|
1211
|
+
ctx.command("幻想乡/打怪攻击 <goal>").action(async ({ session }, goal) => {
|
|
1212
|
+
const userData = await User.getUserAttribute(session);
|
|
1213
|
+
if (!userData) return;
|
|
1214
|
+
BattleData.play(session, "普攻", goal);
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1217
|
+
__name(apply, "apply");
|
|
1218
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1219
|
+
0 && (module.exports = {
|
|
1220
|
+
Config,
|
|
1221
|
+
apply,
|
|
1222
|
+
inject,
|
|
1223
|
+
name
|
|
1224
|
+
});
|