koishi-plugin-smmcat-gensokyo 0.0.3 → 0.0.5
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 +17 -1
- package/lib/damage.d.ts +3 -1
- package/lib/index.js +267 -23
- package/lib/map.d.ts +5 -0
- package/lib/skillFn.d.ts +74 -0
- package/lib/test.d.ts +5 -0
- package/package.json +1 -1
package/lib/battle.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Context, Session } from "koishi";
|
|
2
2
|
import { Config } from ".";
|
|
3
|
+
import { UserBaseAttribute } from "./users";
|
|
3
4
|
declare module 'koishi' {
|
|
4
5
|
interface Tables {
|
|
5
6
|
smm_gensokyo_battle_history: BattleHistory;
|
|
@@ -81,12 +82,15 @@ export type BattleAttribute = {
|
|
|
81
82
|
name: string;
|
|
82
83
|
time: number;
|
|
83
84
|
}[];
|
|
85
|
+
/** 持有技能 */
|
|
86
|
+
fn?: [];
|
|
84
87
|
};
|
|
85
88
|
/** 最后战斗状态 */
|
|
86
89
|
type LastPlay = {
|
|
87
90
|
[keys: string]: {
|
|
88
91
|
self: BattleAttribute[];
|
|
89
92
|
goal: BattleAttribute[];
|
|
93
|
+
isPK?: boolean;
|
|
90
94
|
};
|
|
91
95
|
};
|
|
92
96
|
export declare const BattleData: {
|
|
@@ -98,28 +102,40 @@ export declare const BattleData: {
|
|
|
98
102
|
init(config: Config, ctx: Context): void;
|
|
99
103
|
/** 玩家是否正在战斗 */
|
|
100
104
|
isBattle(session: Session): boolean;
|
|
105
|
+
/** 玩家是否正在战斗 */
|
|
106
|
+
isBattleByUserId(userId: string): boolean;
|
|
101
107
|
/** 玩家是否在队伍中 */
|
|
102
108
|
isTeam(session: Session): boolean;
|
|
109
|
+
isTeamByUserId(userId: string): boolean;
|
|
110
|
+
teamListByUser(userId: string): UserBaseAttribute[];
|
|
103
111
|
/** 创建战斗-与怪物 */
|
|
104
112
|
createBattleByMonster(session: Session, goal: {
|
|
105
113
|
name: string;
|
|
106
114
|
lv: number;
|
|
107
115
|
}[]): Promise<void>;
|
|
116
|
+
/** 创建战斗-与玩家 */
|
|
117
|
+
createBattleByUser(session: Session, goal: {
|
|
118
|
+
userId: string;
|
|
119
|
+
}[]): Promise<void>;
|
|
108
120
|
/** 文本化当前战况 */
|
|
109
121
|
battleSituationTextFormat(team: {
|
|
110
122
|
self: BattleAttribute[];
|
|
111
123
|
goal: BattleAttribute[];
|
|
124
|
+
isPK?: boolean;
|
|
112
125
|
}): string;
|
|
113
126
|
/** 判断输赢 */
|
|
114
127
|
playOver(team: {
|
|
115
128
|
self: BattleAttribute[];
|
|
116
129
|
goal: BattleAttribute[];
|
|
130
|
+
isPK?: boolean;
|
|
117
131
|
}): {
|
|
118
132
|
over: boolean;
|
|
119
133
|
type: string;
|
|
120
134
|
};
|
|
121
135
|
/** 清理战场 */
|
|
122
136
|
clearBattleData(session: Session): void;
|
|
123
|
-
play(session: Session, atkType:
|
|
137
|
+
play(session: Session, atkType: string, select?: string): Promise<void>;
|
|
124
138
|
};
|
|
139
|
+
/** 获取阵容角色名 */
|
|
140
|
+
export declare function getLineupName(agent: BattleAttribute): string;
|
|
125
141
|
export {};
|
package/lib/damage.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ type DamageCallback = {
|
|
|
10
10
|
interface Callback {
|
|
11
11
|
(data: DamageConfig): void;
|
|
12
12
|
}
|
|
13
|
-
type DamageConfig = {
|
|
13
|
+
export type DamageConfig = {
|
|
14
14
|
agent: {
|
|
15
15
|
self: BattleAttribute;
|
|
16
16
|
goal: BattleAttribute;
|
|
@@ -48,4 +48,6 @@ declare class Damage {
|
|
|
48
48
|
}
|
|
49
49
|
/** 给予目标伤害 */
|
|
50
50
|
declare function giveDamage(self: BattleAttribute, goal: BattleAttribute, damage: DamageConfig): number;
|
|
51
|
+
/** 伤害额外信息 */
|
|
52
|
+
export declare function moreDamageInfo(damage: DamageConfig): string;
|
|
51
53
|
export { Damage, giveDamage };
|
package/lib/index.js
CHANGED
|
@@ -308,10 +308,24 @@ var GensokyoMap = {
|
|
|
308
308
|
};
|
|
309
309
|
fn && await fn(areaInfo);
|
|
310
310
|
await delay(3e3);
|
|
311
|
-
GensokyoMap.setLocalStoragePoistionData(session.userId);
|
|
312
311
|
userCurrentArea.moveing = false;
|
|
312
|
+
GensokyoMap.setLocalStoragePoistionData(session.userId);
|
|
313
313
|
return;
|
|
314
314
|
},
|
|
315
|
+
/** 查询附近玩家 */
|
|
316
|
+
nearbyPlayersByUserId(userId) {
|
|
317
|
+
const areaData = GensokyoMap.getUserCurrentArea(userId);
|
|
318
|
+
const liveUser = [];
|
|
319
|
+
Object.keys(GensokyoMap.userCurrentLoal).forEach((_userId) => {
|
|
320
|
+
const userItem = GensokyoMap.userCurrentLoal[_userId];
|
|
321
|
+
if (userItem.areaName == areaData.areaName && userItem.floor == areaData.floor) {
|
|
322
|
+
if (userId !== userItem.userId) {
|
|
323
|
+
liveUser.push({ userId: userItem.userId, playName: userItem.playName });
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
return liveUser;
|
|
328
|
+
},
|
|
315
329
|
/** 区域信息格式化 */
|
|
316
330
|
userAreaTextFormat(gameName, data) {
|
|
317
331
|
const liveUser = [];
|
|
@@ -786,7 +800,7 @@ var Damage = class {
|
|
|
786
800
|
this.config = {
|
|
787
801
|
agent: { self: { ...agent.self }, goal: { ...agent.goal } },
|
|
788
802
|
harm: 0,
|
|
789
|
-
default_harm:
|
|
803
|
+
default_harm: 0,
|
|
790
804
|
isRealHarm: realHarm,
|
|
791
805
|
isEvasion: false,
|
|
792
806
|
isCsp: false,
|
|
@@ -795,13 +809,14 @@ var Damage = class {
|
|
|
795
809
|
}
|
|
796
810
|
/** 伤害判定前 */
|
|
797
811
|
before(fn) {
|
|
812
|
+
this.config.default_harm = this.config.agent.self.atk + this.config.agent.self.gain.atk;
|
|
798
813
|
fn && fn(this.config);
|
|
799
814
|
return this;
|
|
800
815
|
}
|
|
801
816
|
/** 真实伤害判定 */
|
|
802
817
|
beforRealHarm(fn) {
|
|
803
818
|
fn && fn(this.config);
|
|
804
|
-
if (this.config.
|
|
819
|
+
if (this.config.isRealHarm) {
|
|
805
820
|
this.config.harm = this.config.default_harm;
|
|
806
821
|
}
|
|
807
822
|
return this;
|
|
@@ -877,6 +892,65 @@ function giveDamage(self, goal, damage) {
|
|
|
877
892
|
}
|
|
878
893
|
}
|
|
879
894
|
__name(giveDamage, "giveDamage");
|
|
895
|
+
function moreDamageInfo(damage) {
|
|
896
|
+
return (damage.isCsp ? `(暴击!)` : "") + (damage.isEvasion ? `(闪避成功!)` : "") + (damage.isBadDef ? `(未破防!)` : "");
|
|
897
|
+
}
|
|
898
|
+
__name(moreDamageInfo, "moreDamageInfo");
|
|
899
|
+
|
|
900
|
+
// src/skillFn.ts
|
|
901
|
+
var skillFn = {
|
|
902
|
+
"重砍": {
|
|
903
|
+
name: "重砍",
|
|
904
|
+
type: "伤害技" /* 伤害技 */,
|
|
905
|
+
info: "[伤害技]消耗10MP,对敌方一个单位造成基于攻击力1.2倍伤害。该次伤害无视敌方30%防御!(最低无视1防御)",
|
|
906
|
+
mp: 10,
|
|
907
|
+
fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
|
|
908
|
+
const damageData = new Damage(agent).result({
|
|
909
|
+
before: /* @__PURE__ */ __name((val) => {
|
|
910
|
+
val.default_harm += Math.floor(val.default_harm * 0.2);
|
|
911
|
+
val.agent.goal.def -= Math.floor(val.agent.goal.def * 0.3) || 1;
|
|
912
|
+
}, "before")
|
|
913
|
+
});
|
|
914
|
+
fn({
|
|
915
|
+
damage: damageData,
|
|
916
|
+
type: this.type,
|
|
917
|
+
target: [agent.goal],
|
|
918
|
+
isNext: false
|
|
919
|
+
});
|
|
920
|
+
return `${getLineupName(agent.self)} 释放重砍,对 ${getLineupName(agent.goal)} 造成 ${damageData.harm} 伤害。` + moreDamageInfo(damageData);
|
|
921
|
+
}, "fn")
|
|
922
|
+
},
|
|
923
|
+
"濒死一击": {
|
|
924
|
+
name: "濒死一击",
|
|
925
|
+
type: "伤害技" /* 伤害技 */,
|
|
926
|
+
info: "[伤害技]血量低于40%可释放,消耗20MP,对敌方一个单位造成基于攻击力2倍伤害。该次伤害暴击率提高20%",
|
|
927
|
+
mp: 20,
|
|
928
|
+
fn: /* @__PURE__ */ __name(function(agent, agentList, fn) {
|
|
929
|
+
if (agent.self.hp / (agent.self.maxHp + agent.self.gain.maxHp) < 0.4) {
|
|
930
|
+
const damageData = new Damage(agent).result({
|
|
931
|
+
before: /* @__PURE__ */ __name((val) => {
|
|
932
|
+
val.default_harm += val.default_harm;
|
|
933
|
+
val.agent.self.chr += 200;
|
|
934
|
+
}, "before")
|
|
935
|
+
});
|
|
936
|
+
fn({
|
|
937
|
+
damage: damageData,
|
|
938
|
+
type: this.type,
|
|
939
|
+
target: [agent.goal],
|
|
940
|
+
isNext: false
|
|
941
|
+
});
|
|
942
|
+
return `${getLineupName(agent.self)} 释放濒死一击,对 ${getLineupName(agent.goal)} 造成 ${damageData.harm} 伤害。` + moreDamageInfo(damageData);
|
|
943
|
+
} else {
|
|
944
|
+
fn({
|
|
945
|
+
type: "释放失败" /* 释放失败 */,
|
|
946
|
+
isNext: true,
|
|
947
|
+
err: "释放失败,未达成条件。"
|
|
948
|
+
});
|
|
949
|
+
return ``;
|
|
950
|
+
}
|
|
951
|
+
}, "fn")
|
|
952
|
+
}
|
|
953
|
+
};
|
|
880
954
|
|
|
881
955
|
// src/battle.ts
|
|
882
956
|
var BattleData = {
|
|
@@ -893,10 +967,31 @@ var BattleData = {
|
|
|
893
967
|
isBattle(session) {
|
|
894
968
|
return !!BattleData.lastPlay[session.userId];
|
|
895
969
|
},
|
|
970
|
+
/** 玩家是否正在战斗 */
|
|
971
|
+
isBattleByUserId(userId) {
|
|
972
|
+
return !!BattleData.lastPlay[userId];
|
|
973
|
+
},
|
|
896
974
|
/** 玩家是否在队伍中 */
|
|
897
975
|
isTeam(session) {
|
|
898
976
|
return !!BattleData.teamTemp[session.userId];
|
|
899
977
|
},
|
|
978
|
+
isTeamByUserId(userId) {
|
|
979
|
+
return !!BattleData.teamTemp[userId];
|
|
980
|
+
},
|
|
981
|
+
// 返回队伍信息
|
|
982
|
+
teamListByUser(userId) {
|
|
983
|
+
const teamList = [];
|
|
984
|
+
if (!BattleData.teamTemp[userId]) {
|
|
985
|
+
return [];
|
|
986
|
+
}
|
|
987
|
+
const _userId = BattleData.teamTemp[userId].for;
|
|
988
|
+
Object.keys(BattleData.teamTemp).forEach((item) => {
|
|
989
|
+
if (BattleData.teamTemp[item].for == _userId) {
|
|
990
|
+
teamList.push(User.getUserAttributeByUserId(item));
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
return teamList;
|
|
994
|
+
},
|
|
900
995
|
/** 创建战斗-与怪物 */
|
|
901
996
|
async createBattleByMonster(session, goal) {
|
|
902
997
|
if (BattleData.isBattle(session)) {
|
|
@@ -923,14 +1018,69 @@ var BattleData = {
|
|
|
923
1018
|
goal.forEach((item) => {
|
|
924
1019
|
battle_monsterList.push(initBattleAttribute(Monster.getMonsterAttributeData(item.name, item.lv)));
|
|
925
1020
|
});
|
|
1021
|
+
const temp = {
|
|
1022
|
+
self: battle_user.map((i) => ({ ...i, for: "self" })),
|
|
1023
|
+
goal: battle_monsterList.map((i) => ({ ...i, for: "goal" }))
|
|
1024
|
+
};
|
|
926
1025
|
playUser.forEach((userId) => {
|
|
927
|
-
BattleData.lastPlay[userId] =
|
|
928
|
-
self: battle_user.map((i) => ({ ...i, for: "self" })),
|
|
929
|
-
goal: battle_monsterList.map((i) => ({ ...i, for: "goal" }))
|
|
930
|
-
};
|
|
1026
|
+
BattleData.lastPlay[userId] = temp;
|
|
931
1027
|
});
|
|
932
1028
|
await session.send(`开始与 ${goal.map((i) => i.name).join("、")} 进行战斗`);
|
|
933
1029
|
},
|
|
1030
|
+
/** 创建战斗-与玩家 */
|
|
1031
|
+
async createBattleByUser(session, goal) {
|
|
1032
|
+
if (BattleData.isBattle(session)) {
|
|
1033
|
+
await session.send("当前正在战斗,还不能逃脱!");
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
const battle_self = [];
|
|
1037
|
+
const battle_goal = [];
|
|
1038
|
+
const playUser = [];
|
|
1039
|
+
const lostMsg = [];
|
|
1040
|
+
goal = goal.filter((item) => {
|
|
1041
|
+
const isBattle = BattleData.isBattleByUserId(item.userId);
|
|
1042
|
+
const pyUser = User.userTempData[item.userId];
|
|
1043
|
+
if (isBattle) {
|
|
1044
|
+
lostMsg.push(`${pyUser.playName}正在参与着一场战斗,无法被PK选中。`);
|
|
1045
|
+
return false;
|
|
1046
|
+
}
|
|
1047
|
+
return true;
|
|
1048
|
+
});
|
|
1049
|
+
if (lostMsg.length) {
|
|
1050
|
+
await session.send(lostMsg.join("\n"));
|
|
1051
|
+
}
|
|
1052
|
+
if (!goal.length) {
|
|
1053
|
+
lostMsg.push(`PK失败,无任何目标进行PK`);
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
if (BattleData.isTeam(session) && BattleData.teamTemp[session.userId].identity == "队员") {
|
|
1057
|
+
await session.send("你不是队伍的队长,无法主动操作战斗!");
|
|
1058
|
+
return;
|
|
1059
|
+
} else if (BattleData.isTeam(session)) {
|
|
1060
|
+
Object.keys(BattleData.teamTemp).forEach((item) => {
|
|
1061
|
+
if (BattleData.teamTemp[item].for == session.userId) {
|
|
1062
|
+
playUser.push(item);
|
|
1063
|
+
battle_self.push(initBattleAttribute(User.getUserAttributeByUserId(item)));
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1066
|
+
} else {
|
|
1067
|
+
playUser.push(session.userId);
|
|
1068
|
+
battle_self.push(initBattleAttribute(User.getUserAttributeByUserId(session.userId)));
|
|
1069
|
+
}
|
|
1070
|
+
goal.forEach((item) => {
|
|
1071
|
+
playUser.push(item.userId);
|
|
1072
|
+
battle_goal.push(initBattleAttribute(User.getUserAttributeByUserId(item.userId)));
|
|
1073
|
+
});
|
|
1074
|
+
const pkTemp = {
|
|
1075
|
+
self: battle_self.map((i) => ({ ...i, for: "self" })),
|
|
1076
|
+
goal: battle_goal.map((i) => ({ ...i, for: "goal" })),
|
|
1077
|
+
isPK: true
|
|
1078
|
+
};
|
|
1079
|
+
playUser.forEach((userId) => {
|
|
1080
|
+
BattleData.lastPlay[userId] = pkTemp;
|
|
1081
|
+
});
|
|
1082
|
+
await session.send(`开始与玩家 ${battle_goal.map((i) => i.name).join("、")} 进行PK战斗`);
|
|
1083
|
+
},
|
|
934
1084
|
/** 文本化当前战况 */
|
|
935
1085
|
battleSituationTextFormat(team) {
|
|
936
1086
|
const selfTemp = [];
|
|
@@ -938,7 +1088,8 @@ var BattleData = {
|
|
|
938
1088
|
team.self.forEach((item) => {
|
|
939
1089
|
if (item.hp > 0) {
|
|
940
1090
|
selfTemp.push(`lv.${item.lv}[${item.name}]:
|
|
941
|
-
${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${item.maxHp + item.gain.maxHp})
|
|
1091
|
+
${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${item.maxHp + item.gain.maxHp})
|
|
1092
|
+
MP:${item.mp}/${item.maxMp + item.gain.maxMp}`);
|
|
942
1093
|
} else {
|
|
943
1094
|
selfTemp.push(`lv.${item.lv}[${item.name}]:已阵亡`);
|
|
944
1095
|
}
|
|
@@ -946,11 +1097,17 @@ ${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${ite
|
|
|
946
1097
|
team.goal.forEach((item) => {
|
|
947
1098
|
if (item.hp > 0) {
|
|
948
1099
|
goalTemp.push(`lv.${item.lv}[${item.name}]:
|
|
949
|
-
${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${item.maxHp + item.gain.maxHp})
|
|
1100
|
+
${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${item.maxHp + item.gain.maxHp})
|
|
1101
|
+
MP:${item.mp}/${item.maxMp + item.gain.maxMp}`);
|
|
950
1102
|
} else {
|
|
951
1103
|
goalTemp.push(`lv.${item.lv}[${item.name}]:已阵亡`);
|
|
952
1104
|
}
|
|
953
1105
|
});
|
|
1106
|
+
if (team.isPK) {
|
|
1107
|
+
return `[当前战况]
|
|
1108
|
+
攻击方:
|
|
1109
|
+
` + selfTemp.join("\n") + "\n\n防御方:\n" + goalTemp.join("\n");
|
|
1110
|
+
}
|
|
954
1111
|
return `[当前战况]
|
|
955
1112
|
我方阵容:
|
|
956
1113
|
` + selfTemp.join("\n") + "\n\n敌方阵容:\n" + goalTemp.join("\n");
|
|
@@ -962,19 +1119,20 @@ ${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${ite
|
|
|
962
1119
|
if (self && goal) {
|
|
963
1120
|
return { over: true, type: "平局" };
|
|
964
1121
|
} else if (self) {
|
|
965
|
-
return { over: true, type: "敌方赢" };
|
|
1122
|
+
return { over: true, type: team.isPK ? "防御方赢" : "敌方赢" };
|
|
966
1123
|
} else if (goal) {
|
|
967
|
-
return { over: true, type: "我方赢" };
|
|
1124
|
+
return { over: true, type: team.isPK ? "攻击方赢" : "我方赢" };
|
|
968
1125
|
}
|
|
969
1126
|
return { over: false, type: "未结束" };
|
|
970
1127
|
},
|
|
971
1128
|
/** 清理战场 */
|
|
972
1129
|
clearBattleData(session) {
|
|
973
1130
|
if (BattleData.isTeam(session)) {
|
|
974
|
-
const
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
1131
|
+
const currentBattle = BattleData.lastPlay[session.userId];
|
|
1132
|
+
const allAgentList = [...currentBattle.goal, ...currentBattle.self].sort((a, b) => b.speed - a.speed);
|
|
1133
|
+
allAgentList.forEach((item) => {
|
|
1134
|
+
if (item.type == "玩家") {
|
|
1135
|
+
delete BattleData.lastPlay[item.userId];
|
|
978
1136
|
}
|
|
979
1137
|
});
|
|
980
1138
|
} else {
|
|
@@ -992,25 +1150,71 @@ ${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${ite
|
|
|
992
1150
|
for (const agent of allAgentList) {
|
|
993
1151
|
if (agent.hp <= 0) continue;
|
|
994
1152
|
let lifeGoalList = [];
|
|
1153
|
+
let lifeSelfList = [];
|
|
995
1154
|
if (agent.for == "self") {
|
|
996
1155
|
lifeGoalList = currentBattle.goal.filter((item) => item.for == "goal" && item.hp > 0);
|
|
1156
|
+
lifeSelfList = currentBattle.self.filter((item) => item.for == "self" && item.hp > 0);
|
|
997
1157
|
} else {
|
|
998
1158
|
lifeGoalList = currentBattle.self.filter((item) => item.for == "self" && item.hp > 0);
|
|
1159
|
+
lifeSelfList = currentBattle.goal.filter((item) => item.for == "goal" && item.hp > 0);
|
|
999
1160
|
}
|
|
1000
1161
|
if (!lifeGoalList.length) continue;
|
|
1001
1162
|
let selectGoal = {};
|
|
1002
1163
|
let isMy = false;
|
|
1164
|
+
let funType = "普攻";
|
|
1003
1165
|
if (agent.type == "玩家" && agent.userId == session.userId) {
|
|
1004
1166
|
isMy = true;
|
|
1167
|
+
funType = atkType;
|
|
1005
1168
|
selectGoal = lifeGoalList.find((item) => item.name == select) || lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
|
|
1169
|
+
} else if (agent.type == "玩家") {
|
|
1170
|
+
selectGoal = lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
|
|
1006
1171
|
} else {
|
|
1007
1172
|
selectGoal = lifeGoalList[Math.floor(Math.random() * lifeGoalList.length)];
|
|
1008
1173
|
}
|
|
1009
|
-
const
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1174
|
+
const noralAtk = /* @__PURE__ */ __name(() => {
|
|
1175
|
+
const damageInfo = new Damage({ self: agent, goal: selectGoal }).result();
|
|
1176
|
+
giveDamage(agent, selectGoal, damageInfo);
|
|
1177
|
+
msgList.push(
|
|
1178
|
+
`${getLineupName(agent)} 使用普攻攻击了 ${getLineupName(selectGoal)},造成了${damageInfo.harm}伤害。` + moreDamageInfo(damageInfo)
|
|
1179
|
+
);
|
|
1180
|
+
}, "noralAtk");
|
|
1181
|
+
if (funType == "普攻") {
|
|
1182
|
+
noralAtk();
|
|
1183
|
+
} else {
|
|
1184
|
+
if (skillFn[atkType]) {
|
|
1185
|
+
const selectFn = skillFn[atkType];
|
|
1186
|
+
if (selectFn.mp == 0 || agent.mp - selectFn.mp >= 0) {
|
|
1187
|
+
agent.mp -= selectFn.mp;
|
|
1188
|
+
let isNext = false;
|
|
1189
|
+
const fnMsg = selectFn.fn(
|
|
1190
|
+
{ self: agent, goal: selectGoal },
|
|
1191
|
+
{ selfList: lifeSelfList, goalList: lifeGoalList },
|
|
1192
|
+
(val) => {
|
|
1193
|
+
switch (val.type) {
|
|
1194
|
+
case "伤害技" /* 伤害技 */:
|
|
1195
|
+
val.target.map((goal) => {
|
|
1196
|
+
giveDamage(agent, goal, val.damage);
|
|
1197
|
+
});
|
|
1198
|
+
break;
|
|
1199
|
+
case "释放失败" /* 释放失败 */:
|
|
1200
|
+
val.err && session.send(val.err);
|
|
1201
|
+
default:
|
|
1202
|
+
break;
|
|
1203
|
+
}
|
|
1204
|
+
isNext = val.isNext;
|
|
1205
|
+
}
|
|
1206
|
+
);
|
|
1207
|
+
fnMsg && msgList.push(fnMsg);
|
|
1208
|
+
isNext && noralAtk();
|
|
1209
|
+
} else {
|
|
1210
|
+
await session.send(`MP不足,释放失败!`);
|
|
1211
|
+
noralAtk();
|
|
1212
|
+
}
|
|
1213
|
+
} else {
|
|
1214
|
+
await session.send(`未持有该技能或者该技能不存在,释放失败!`);
|
|
1215
|
+
noralAtk();
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1014
1218
|
}
|
|
1015
1219
|
await session.send(msgList.length ? `战斗记录:
|
|
1016
1220
|
` + msgList.join("\n") : "");
|
|
@@ -1022,6 +1226,10 @@ ${generateHealthDisplay(item.hp, item.maxHp + item.gain.maxHp)}(${item.hp}/${ite
|
|
|
1022
1226
|
}
|
|
1023
1227
|
}
|
|
1024
1228
|
};
|
|
1229
|
+
function getLineupName(agent) {
|
|
1230
|
+
return `[${agent.type}]${agent.name}`;
|
|
1231
|
+
}
|
|
1232
|
+
__name(getLineupName, "getLineupName");
|
|
1025
1233
|
function initBattleAttribute(data) {
|
|
1026
1234
|
if ("playName" in data) {
|
|
1027
1235
|
const userData = data;
|
|
@@ -1053,7 +1261,8 @@ function initBattleAttribute(data) {
|
|
|
1053
1261
|
hit: 0,
|
|
1054
1262
|
speed: 0
|
|
1055
1263
|
},
|
|
1056
|
-
buff: []
|
|
1264
|
+
buff: [],
|
|
1265
|
+
fn: []
|
|
1057
1266
|
};
|
|
1058
1267
|
return temp;
|
|
1059
1268
|
} else {
|
|
@@ -1085,7 +1294,8 @@ function initBattleAttribute(data) {
|
|
|
1085
1294
|
hit: 0,
|
|
1086
1295
|
speed: 0
|
|
1087
1296
|
},
|
|
1088
|
-
buff: []
|
|
1297
|
+
buff: [],
|
|
1298
|
+
fn: []
|
|
1089
1299
|
};
|
|
1090
1300
|
return temp;
|
|
1091
1301
|
}
|
|
@@ -1219,7 +1429,7 @@ function apply(ctx, config) {
|
|
|
1219
1429
|
GensokyoMap.initUserPoistion(session, userData);
|
|
1220
1430
|
const areaInfo = GensokyoMap.getUserCurrentArea(session.userId);
|
|
1221
1431
|
if (goal) {
|
|
1222
|
-
if (!areaInfo.monster
|
|
1432
|
+
if (!areaInfo.monster?.map((i) => i.name).includes(goal)) {
|
|
1223
1433
|
return `没有在该区域找到该怪物。`;
|
|
1224
1434
|
}
|
|
1225
1435
|
const selectMonster = areaInfo.monster.find((i) => i.name == goal);
|
|
@@ -1234,6 +1444,40 @@ function apply(ctx, config) {
|
|
|
1234
1444
|
if (!userData) return;
|
|
1235
1445
|
BattleData.play(session, "普攻", goal);
|
|
1236
1446
|
});
|
|
1447
|
+
ctx.command("幻想乡/打怪技能 <skill> <goal>").action(async ({ session }, skill, goal) => {
|
|
1448
|
+
const userData = await User.getUserAttribute(session);
|
|
1449
|
+
if (!userData) return;
|
|
1450
|
+
BattleData.play(session, skill, goal);
|
|
1451
|
+
});
|
|
1452
|
+
ctx.command("打怪pk <goal>").action(async ({ session }, goal) => {
|
|
1453
|
+
const userData = await User.getUserAttribute(session);
|
|
1454
|
+
if (!userData) return;
|
|
1455
|
+
GensokyoMap.initUserPoistion(session, userData);
|
|
1456
|
+
if (!goal) {
|
|
1457
|
+
await session.send("请选择PK目标!");
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
const nearUserItem = GensokyoMap.nearbyPlayersByUserId(session.userId);
|
|
1461
|
+
const exist = nearUserItem.find((item) => item.playName == goal.trim());
|
|
1462
|
+
if (!exist) {
|
|
1463
|
+
await session.send(`PK失败,当前区域未存在【${goal}】玩家`);
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1466
|
+
if (BattleData.isTeamByUserId(exist.userId)) {
|
|
1467
|
+
const teamItem = BattleData.teamListByUser(exist.userId);
|
|
1468
|
+
await session.send(`对方有组队,您将扮演攻击方与对方队伍进行战斗。`);
|
|
1469
|
+
await BattleData.createBattleByUser(session, teamItem.map((item) => ({ userId: item.userId })));
|
|
1470
|
+
} else {
|
|
1471
|
+
await session.send(`您将扮演攻击方与对方进行战斗。`);
|
|
1472
|
+
await BattleData.createBattleByUser(session, [{ userId: exist.userId }]);
|
|
1473
|
+
}
|
|
1474
|
+
});
|
|
1475
|
+
ctx.command("技能查询 <goal>").action(async ({ session }, goal) => {
|
|
1476
|
+
if (!goal) return `请输入技能名,例如 /技能查询 重砍`;
|
|
1477
|
+
if (!skillFn[goal]) return `没有存在 ${goal} 技能!`;
|
|
1478
|
+
return `[${goal}]信息如下:
|
|
1479
|
+
` + skillFn[goal].info;
|
|
1480
|
+
});
|
|
1237
1481
|
}
|
|
1238
1482
|
__name(apply, "apply");
|
|
1239
1483
|
// Annotate the CommonJS export names for ESM import in node:
|
package/lib/map.d.ts
CHANGED
|
@@ -98,6 +98,11 @@ export declare const GensokyoMap: {
|
|
|
98
98
|
setLocalStoragePoistionData(userId: string): Promise<void>;
|
|
99
99
|
/** 用户移动 */
|
|
100
100
|
move(session: Session, type: MoveType, fn?: (area: AreaCallbackData) => Promise<void>): Promise<void>;
|
|
101
|
+
/** 查询附近玩家 */
|
|
102
|
+
nearbyPlayersByUserId(userId: string): {
|
|
103
|
+
userId: string;
|
|
104
|
+
playName: string;
|
|
105
|
+
}[];
|
|
101
106
|
/** 区域信息格式化 */
|
|
102
107
|
userAreaTextFormat(gameName: string, data: AreaCallbackData): string;
|
|
103
108
|
};
|
package/lib/skillFn.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { BattleAttribute } from "./battle";
|
|
2
|
+
import { DamageConfig } from "./damage";
|
|
3
|
+
export declare enum SkillType {
|
|
4
|
+
释放失败 = "\u91CA\u653E\u5931\u8D25",
|
|
5
|
+
伤害技 = "\u4F24\u5BB3\u6280",
|
|
6
|
+
增益技 = "\u589E\u76CA\u6280",
|
|
7
|
+
治疗技 = "\u6CBB\u7597\u6280",
|
|
8
|
+
奥义 = "\u5965\u4E49"
|
|
9
|
+
}
|
|
10
|
+
interface DamageSkillParams {
|
|
11
|
+
/** 伤害类型 */
|
|
12
|
+
type: SkillType.伤害技;
|
|
13
|
+
/** 伤害信息 */
|
|
14
|
+
damage: DamageConfig;
|
|
15
|
+
/** 释放目标 */
|
|
16
|
+
target: BattleAttribute[];
|
|
17
|
+
/** 是否衔接普攻 */
|
|
18
|
+
isNext: boolean;
|
|
19
|
+
}
|
|
20
|
+
interface BuffSkillParams {
|
|
21
|
+
type: SkillType.增益技;
|
|
22
|
+
buffs: {
|
|
23
|
+
val: number;
|
|
24
|
+
time: number;
|
|
25
|
+
name: number;
|
|
26
|
+
}[];
|
|
27
|
+
target: BattleAttribute | BattleAttribute[];
|
|
28
|
+
/** 是否衔接普攻 */
|
|
29
|
+
isNext: boolean;
|
|
30
|
+
}
|
|
31
|
+
interface HealSkillParams {
|
|
32
|
+
type: SkillType.治疗技;
|
|
33
|
+
/** 是否衔接普攻 */
|
|
34
|
+
isNext: boolean;
|
|
35
|
+
}
|
|
36
|
+
interface UltimateSkillParams {
|
|
37
|
+
type: SkillType.奥义;
|
|
38
|
+
/** 是否衔接普攻 */
|
|
39
|
+
isNext: boolean;
|
|
40
|
+
}
|
|
41
|
+
interface ErrSkillParams {
|
|
42
|
+
type: SkillType.释放失败;
|
|
43
|
+
/** 是否衔接普攻 */
|
|
44
|
+
isNext: boolean;
|
|
45
|
+
/** 错误提示 */
|
|
46
|
+
err?: string;
|
|
47
|
+
}
|
|
48
|
+
type SkillParams = DamageSkillParams | BuffSkillParams | HealSkillParams | UltimateSkillParams | ErrSkillParams;
|
|
49
|
+
interface SkillConfig<T extends SkillType = SkillType> {
|
|
50
|
+
/** 技能名 */
|
|
51
|
+
name: string;
|
|
52
|
+
/** 技能类型 */
|
|
53
|
+
type: T;
|
|
54
|
+
/** 技能说明 */
|
|
55
|
+
info: string;
|
|
56
|
+
/** 消耗MP */
|
|
57
|
+
mp: number;
|
|
58
|
+
/** 技能函数 */
|
|
59
|
+
fn(agent: {
|
|
60
|
+
self: BattleAttribute;
|
|
61
|
+
goal: BattleAttribute;
|
|
62
|
+
}, agentList: {
|
|
63
|
+
selfList: BattleAttribute[];
|
|
64
|
+
goalList: BattleAttribute[];
|
|
65
|
+
}, cb?: (val: Extract<SkillParams, {
|
|
66
|
+
type: T;
|
|
67
|
+
}>) => void): string;
|
|
68
|
+
}
|
|
69
|
+
type SkillFn = {
|
|
70
|
+
[key: string]: SkillConfig;
|
|
71
|
+
};
|
|
72
|
+
export type UseAtkType = keyof typeof skillFn | '普攻';
|
|
73
|
+
export declare const skillFn: SkillFn;
|
|
74
|
+
export {};
|
package/lib/test.d.ts
ADDED