hrbattle 0.1.0
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/README.md +103 -0
- package/dist/battle/battleCore.d.ts +83 -0
- package/dist/battle/battleCore.js +779 -0
- package/dist/battle/config/json/designed-buffs.json +608 -0
- package/dist/battle/config/json/designed-hero-skill-books.json +146 -0
- package/dist/battle/config/json/designed-monster-skill-books.json +308 -0
- package/dist/battle/config/json/designed-roster.json +438 -0
- package/dist/battle/config/json/designed-skill-templates.json +81 -0
- package/dist/battle/config/jsonConfigLoader.d.ts +26 -0
- package/dist/battle/config/jsonConfigLoader.js +77 -0
- package/dist/battle/effectSystem.d.ts +26 -0
- package/dist/battle/effectSystem.js +175 -0
- package/dist/battle/eventBus.d.ts +8 -0
- package/dist/battle/eventBus.js +20 -0
- package/dist/battle/formula.d.ts +19 -0
- package/dist/battle/formula.js +92 -0
- package/dist/battle/logger.d.ts +28 -0
- package/dist/battle/logger.js +66 -0
- package/dist/battle/random.d.ts +6 -0
- package/dist/battle/random.js +16 -0
- package/dist/battle/script/designedScripts.d.ts +2 -0
- package/dist/battle/script/designedScripts.js +1013 -0
- package/dist/battle/script/monsterScripts.d.ts +2 -0
- package/dist/battle/script/monsterScripts.js +277 -0
- package/dist/battle/script/monsterScripts18xx.d.ts +2 -0
- package/dist/battle/script/monsterScripts18xx.js +330 -0
- package/dist/battle/script/monsterScripts19xx.d.ts +2 -0
- package/dist/battle/script/monsterScripts19xx.js +271 -0
- package/dist/battle/script/monsterScripts19xxPart2.d.ts +2 -0
- package/dist/battle/script/monsterScripts19xxPart2.js +400 -0
- package/dist/battle/skillEngine.d.ts +36 -0
- package/dist/battle/skillEngine.js +246 -0
- package/dist/battle/targeting.d.ts +3 -0
- package/dist/battle/targeting.js +38 -0
- package/dist/battle/turnbar.d.ts +8 -0
- package/dist/battle/turnbar.js +40 -0
- package/dist/battle/types.d.ts +302 -0
- package/dist/battle/types.js +1 -0
- package/dist/cocos-adapter/BattleFacade.d.ts +8 -0
- package/dist/cocos-adapter/BattleFacade.js +22 -0
- package/dist/cocos-adapter/clientBattleResult.d.ts +127 -0
- package/dist/cocos-adapter/clientBattleResult.js +413 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +8 -0
- package/package.json +32 -0
|
@@ -0,0 +1,1013 @@
|
|
|
1
|
+
import { monsterScripts16xx } from "./monsterScripts";
|
|
2
|
+
import { monsterScripts18xx } from "./monsterScripts18xx";
|
|
3
|
+
import { monsterScripts19xxPart1 } from "./monsterScripts19xx";
|
|
4
|
+
import { monsterScripts19xxPart2 } from "./monsterScripts19xxPart2";
|
|
5
|
+
const ailishaOriginalPositions = new Map();
|
|
6
|
+
function buildEmptyResult(ctx, targets = ctx.targets) {
|
|
7
|
+
return {
|
|
8
|
+
skillId: ctx.skillId,
|
|
9
|
+
casterId: ctx.caster,
|
|
10
|
+
targets,
|
|
11
|
+
totalDamage: 0,
|
|
12
|
+
totalHeal: 0,
|
|
13
|
+
totalShield: 0,
|
|
14
|
+
triggeredBy: ctx.trigger
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function buildDamageHit(ctx, targetId, finalValue) {
|
|
18
|
+
return {
|
|
19
|
+
targetId,
|
|
20
|
+
effectType: "damage",
|
|
21
|
+
element: ctx.api.getUnit(ctx.caster)?.element ?? "fire",
|
|
22
|
+
skillType: "basic",
|
|
23
|
+
isCritical: false,
|
|
24
|
+
baseValue: finalValue,
|
|
25
|
+
criticalValue: finalValue,
|
|
26
|
+
finalValue,
|
|
27
|
+
isRepression: 0,
|
|
28
|
+
damageBreakdown: {
|
|
29
|
+
preMitigation: finalValue,
|
|
30
|
+
postMitigation: finalValue,
|
|
31
|
+
shieldAbsorbed: 0,
|
|
32
|
+
hpDamage: finalValue
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function buildBuffHit(ctx, targetId, buffId, resisted = false) {
|
|
37
|
+
return {
|
|
38
|
+
targetId,
|
|
39
|
+
effectType: "buff",
|
|
40
|
+
element: ctx.api.getUnit(ctx.caster)?.element ?? "fire",
|
|
41
|
+
skillType: "basic",
|
|
42
|
+
isCritical: false,
|
|
43
|
+
baseValue: 0,
|
|
44
|
+
criticalValue: 0,
|
|
45
|
+
finalValue: 0,
|
|
46
|
+
isRepression: 0,
|
|
47
|
+
appliedBuffId: resisted ? undefined : buffId,
|
|
48
|
+
resisted
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function buildShieldHit(ctx, targetId, finalValue) {
|
|
52
|
+
return {
|
|
53
|
+
targetId,
|
|
54
|
+
effectType: "shield",
|
|
55
|
+
element: ctx.api.getUnit(ctx.caster)?.element ?? "fire",
|
|
56
|
+
skillType: "basic",
|
|
57
|
+
isCritical: false,
|
|
58
|
+
baseValue: finalValue,
|
|
59
|
+
criticalValue: finalValue,
|
|
60
|
+
finalValue,
|
|
61
|
+
isRepression: 0
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function buildHealHit(ctx, targetId, finalValue) {
|
|
65
|
+
return {
|
|
66
|
+
targetId,
|
|
67
|
+
effectType: "heal",
|
|
68
|
+
element: ctx.api.getUnit(ctx.caster)?.element ?? "fire",
|
|
69
|
+
skillType: "basic",
|
|
70
|
+
isCritical: false,
|
|
71
|
+
baseValue: finalValue,
|
|
72
|
+
criticalValue: finalValue,
|
|
73
|
+
finalValue,
|
|
74
|
+
isRepression: 0
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const bladeUltimateScript = {
|
|
78
|
+
onCast(ctx) {
|
|
79
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
80
|
+
const targetId = ctx.targets[0];
|
|
81
|
+
if (!self || !targetId) {
|
|
82
|
+
return buildEmptyResult(ctx, targetId ? [targetId] : []);
|
|
83
|
+
}
|
|
84
|
+
const target = ctx.api.getUnit(targetId);
|
|
85
|
+
let totalDamage = 0;
|
|
86
|
+
const hits = [];
|
|
87
|
+
if (target && target.runtime.Hp * 100 < target.stats.Mhp * 50) {
|
|
88
|
+
// 策划:对生命值低于50%的敌人额外造成20%伤害
|
|
89
|
+
const damage = ctx.api.damage(ctx.caster, targetId, Math.floor(self.stats.Att * 0.2));
|
|
90
|
+
totalDamage += damage;
|
|
91
|
+
hits.push(buildDamageHit(ctx, targetId, damage));
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
...buildEmptyResult(ctx, [targetId]),
|
|
95
|
+
totalDamage,
|
|
96
|
+
hits
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
// 布莱德/岚普攻:对生命值高于70%的敌人造成额外20%伤害
|
|
101
|
+
const bladeBasicScript = {
|
|
102
|
+
onCast(ctx) {
|
|
103
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
104
|
+
const targetId = ctx.targets[0];
|
|
105
|
+
if (!self || !targetId) {
|
|
106
|
+
return buildEmptyResult(ctx, targetId ? [targetId] : []);
|
|
107
|
+
}
|
|
108
|
+
const target = ctx.api.getUnit(targetId);
|
|
109
|
+
let totalDamage = 0;
|
|
110
|
+
const hits = [];
|
|
111
|
+
if (target && target.runtime.Hp * 100 > target.stats.Mhp * 70) {
|
|
112
|
+
// 策划:对生命值高于70%的敌人造成额外20%伤害
|
|
113
|
+
const damage = ctx.api.damage(ctx.caster, targetId, Math.floor(self.stats.Att * 0.2));
|
|
114
|
+
totalDamage += damage;
|
|
115
|
+
hits.push(buildDamageHit(ctx, targetId, damage));
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
...buildEmptyResult(ctx, [targetId]),
|
|
119
|
+
totalDamage,
|
|
120
|
+
hits
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
const bladeCoreScript = {
|
|
125
|
+
onCast(ctx) {
|
|
126
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
127
|
+
if (!self) {
|
|
128
|
+
return buildEmptyResult(ctx, []);
|
|
129
|
+
}
|
|
130
|
+
const enemies = ctx.api.getAliveUnits().filter((unit) => unit.teamId !== self.teamId);
|
|
131
|
+
if (enemies.length === 0) {
|
|
132
|
+
return buildEmptyResult(ctx, []);
|
|
133
|
+
}
|
|
134
|
+
let totalDamage = 0;
|
|
135
|
+
const hitTargets = [];
|
|
136
|
+
const hits = [];
|
|
137
|
+
for (let i = 0; i < 3; i++) {
|
|
138
|
+
const target = enemies[ctx.api.randomInt(enemies.length)];
|
|
139
|
+
hitTargets.push(target.id);
|
|
140
|
+
const damage = ctx.api.damage(ctx.caster, target.id, Math.floor(self.stats.Att * 0.3));
|
|
141
|
+
totalDamage += damage;
|
|
142
|
+
hits.push(buildDamageHit(ctx, target.id, damage));
|
|
143
|
+
if (ctx.api.randomInt(10000) < 2000) {
|
|
144
|
+
ctx.api.gainEnergy(ctx.caster, 10);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
...buildEmptyResult(ctx, hitTargets),
|
|
149
|
+
totalDamage,
|
|
150
|
+
hits
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
const luoluoBasicScript = {
|
|
155
|
+
onCast(ctx) {
|
|
156
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "will");
|
|
157
|
+
return {
|
|
158
|
+
skillId: ctx.skillId,
|
|
159
|
+
casterId: ctx.caster,
|
|
160
|
+
targets: ctx.targets,
|
|
161
|
+
totalDamage: 0,
|
|
162
|
+
totalHeal: 0,
|
|
163
|
+
totalShield: 0,
|
|
164
|
+
triggeredBy: ctx.trigger
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
// 洛洛核心技:获得10%生命值的护盾,每层【惩戒/意志】使护盾强度增加10%
|
|
169
|
+
const luoluoCoreScript = {
|
|
170
|
+
onCast(ctx) {
|
|
171
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
172
|
+
let totalShield = 0;
|
|
173
|
+
const hits = [];
|
|
174
|
+
if (self) {
|
|
175
|
+
// 策划:10%Mhp护盾,每层意志增加10%
|
|
176
|
+
const willBuffs = ctx.api.getBuffs(ctx.caster).filter(b => b.id === "will");
|
|
177
|
+
const willStacks = willBuffs.reduce((sum, b) => sum + b.stacks, 0);
|
|
178
|
+
const shieldMultiplier = 1 + willStacks * 0.1;
|
|
179
|
+
const shield = Math.floor(self.stats.Mhp * 0.1 * shieldMultiplier);
|
|
180
|
+
ctx.api.shield(ctx.caster, shield);
|
|
181
|
+
totalShield += shield;
|
|
182
|
+
hits.push(buildShieldHit(ctx, ctx.caster, shield));
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
...buildEmptyResult(ctx, ctx.targets),
|
|
186
|
+
totalShield: totalShield,
|
|
187
|
+
hits
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
const miaoluoUltimateScript = {
|
|
192
|
+
onCast(ctx) {
|
|
193
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
194
|
+
const target = ctx.api
|
|
195
|
+
.getAliveUnits()
|
|
196
|
+
.filter((unit) => self && unit.teamId !== self.teamId)
|
|
197
|
+
.sort((a, b) => {
|
|
198
|
+
if (a.runtime.Hp !== b.runtime.Hp) {
|
|
199
|
+
return a.runtime.Hp - b.runtime.Hp;
|
|
200
|
+
}
|
|
201
|
+
return a.position - b.position;
|
|
202
|
+
})[0];
|
|
203
|
+
let totalDamage = 0;
|
|
204
|
+
const hits = [];
|
|
205
|
+
if (self && target) {
|
|
206
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "miaoluo-ultimate-focus");
|
|
207
|
+
hits.push(buildBuffHit(ctx, ctx.caster, "miaoluo-ultimate-focus"));
|
|
208
|
+
for (let i = 0; i < 3; i += 1) {
|
|
209
|
+
const damage = ctx.api.damage(ctx.caster, target.id, Math.floor(self.stats.Att * 0.6));
|
|
210
|
+
totalDamage += damage;
|
|
211
|
+
hits.push(buildDamageHit(ctx, target.id, damage));
|
|
212
|
+
}
|
|
213
|
+
if (ctx.api.hasBuff(target.id, "imbalance-vulnerability")) {
|
|
214
|
+
const damage = ctx.api.damage(ctx.caster, target.id, Math.floor(self.stats.Att * 0.3));
|
|
215
|
+
totalDamage += damage;
|
|
216
|
+
hits.push(buildDamageHit(ctx, target.id, damage));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
...buildEmptyResult(ctx, target ? [target.id] : []),
|
|
221
|
+
totalDamage,
|
|
222
|
+
hits
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
const miaoluoBasicScript = {
|
|
227
|
+
onCast(ctx) {
|
|
228
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
229
|
+
const target = ctx.api
|
|
230
|
+
.getAliveUnits()
|
|
231
|
+
.filter((unit) => self && unit.teamId !== self.teamId)
|
|
232
|
+
.sort((a, b) => {
|
|
233
|
+
if (a.runtime.Hp !== b.runtime.Hp) {
|
|
234
|
+
return a.runtime.Hp - b.runtime.Hp;
|
|
235
|
+
}
|
|
236
|
+
return a.position - b.position;
|
|
237
|
+
})[0];
|
|
238
|
+
let totalDamage = 0;
|
|
239
|
+
const hits = [];
|
|
240
|
+
if (self && target) {
|
|
241
|
+
const damage = ctx.api.damage(ctx.caster, target.id, Math.floor(self.stats.Att * 0.5));
|
|
242
|
+
totalDamage += damage;
|
|
243
|
+
hits.push(buildDamageHit(ctx, target.id, damage));
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
...buildEmptyResult(ctx, target ? [target.id] : []),
|
|
247
|
+
totalDamage,
|
|
248
|
+
hits
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
const miaoluoCoreScript = {
|
|
253
|
+
onCast(ctx) {
|
|
254
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
255
|
+
const target = ctx.api
|
|
256
|
+
.getAliveUnits()
|
|
257
|
+
.filter((unit) => self && unit.teamId !== self.teamId)
|
|
258
|
+
.sort((a, b) => {
|
|
259
|
+
if (a.runtime.Hp !== b.runtime.Hp) {
|
|
260
|
+
return a.runtime.Hp - b.runtime.Hp;
|
|
261
|
+
}
|
|
262
|
+
return a.position - b.position;
|
|
263
|
+
})[0];
|
|
264
|
+
let totalDamage = 0;
|
|
265
|
+
const hits = [];
|
|
266
|
+
if (self && target) {
|
|
267
|
+
const damage = ctx.api.damage(ctx.caster, target.id, Math.floor(self.stats.Att * 0.8));
|
|
268
|
+
totalDamage += damage;
|
|
269
|
+
hits.push(buildDamageHit(ctx, target.id, damage));
|
|
270
|
+
ctx.api.addBuff(ctx.caster, target.id, "static");
|
|
271
|
+
hits.push(buildBuffHit(ctx, target.id, "static"));
|
|
272
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "flash");
|
|
273
|
+
hits.push(buildBuffHit(ctx, ctx.caster, "flash"));
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
...buildEmptyResult(ctx, target ? [target.id] : []),
|
|
277
|
+
totalDamage,
|
|
278
|
+
hits
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
const cookBasicScript = {
|
|
283
|
+
onCast(ctx) {
|
|
284
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
285
|
+
const targetId = ctx.targets[0];
|
|
286
|
+
let totalDamage = 0;
|
|
287
|
+
const hits = [];
|
|
288
|
+
if (self) {
|
|
289
|
+
const selfCost = Math.floor(self.runtime.Hp * 0.1);
|
|
290
|
+
if (selfCost > 0) {
|
|
291
|
+
const damage = ctx.api.damage(ctx.caster, ctx.caster, selfCost);
|
|
292
|
+
totalDamage += damage;
|
|
293
|
+
hits.push(buildDamageHit(ctx, ctx.caster, damage));
|
|
294
|
+
if (targetId) {
|
|
295
|
+
const damage2 = ctx.api.damage(ctx.caster, targetId, Math.floor(selfCost * 0.5));
|
|
296
|
+
totalDamage += damage2;
|
|
297
|
+
hits.push(buildDamageHit(ctx, targetId, damage2));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
...buildEmptyResult(ctx, ctx.targets),
|
|
303
|
+
totalDamage,
|
|
304
|
+
hits
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
const cookCoreScript = {
|
|
309
|
+
onCast(ctx) {
|
|
310
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
311
|
+
const enemies = ctx.api
|
|
312
|
+
.getAliveUnits()
|
|
313
|
+
.filter((unit) => self && unit.teamId !== self.teamId)
|
|
314
|
+
.sort((a, b) => {
|
|
315
|
+
if (b.runtime.Hp !== a.runtime.Hp) {
|
|
316
|
+
return b.runtime.Hp - a.runtime.Hp;
|
|
317
|
+
}
|
|
318
|
+
return a.position - b.position;
|
|
319
|
+
});
|
|
320
|
+
const target = enemies[0];
|
|
321
|
+
let totalDamage = 0;
|
|
322
|
+
const hits = [];
|
|
323
|
+
if (self && target) {
|
|
324
|
+
const lostHp = Math.max(0, self.stats.Mhp - self.runtime.Hp);
|
|
325
|
+
const lostStepCount = Math.floor((lostHp * 10) / Math.max(1, self.stats.Mhp));
|
|
326
|
+
const multiplier = 1 + lostStepCount * 0.05;
|
|
327
|
+
const damage = ctx.api.damage(ctx.caster, target.id, Math.floor(self.stats.Att * multiplier));
|
|
328
|
+
totalDamage += damage;
|
|
329
|
+
hits.push(buildDamageHit(ctx, target.id, damage));
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
...buildEmptyResult(ctx, target ? [target.id] : []),
|
|
333
|
+
totalDamage,
|
|
334
|
+
hits
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
const cookUltimateScript = {
|
|
339
|
+
onCast(ctx) {
|
|
340
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
341
|
+
let totalHeal = 0;
|
|
342
|
+
const hits = [];
|
|
343
|
+
if (self) {
|
|
344
|
+
const lostHp = Math.max(0, self.stats.Mhp - self.runtime.Hp);
|
|
345
|
+
const heal = ctx.api.heal(ctx.caster, Math.floor(lostHp * 0.2));
|
|
346
|
+
totalHeal += heal;
|
|
347
|
+
hits.push(buildHealHit(ctx, ctx.caster, heal));
|
|
348
|
+
}
|
|
349
|
+
return {
|
|
350
|
+
...buildEmptyResult(ctx, ctx.targets),
|
|
351
|
+
totalHeal,
|
|
352
|
+
hits
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
const kesiCoreScript = {
|
|
357
|
+
onCast(ctx) {
|
|
358
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
359
|
+
if (!self) {
|
|
360
|
+
return buildEmptyResult(ctx, []);
|
|
361
|
+
}
|
|
362
|
+
const candidates = ctx.api.getAliveUnits().filter((unit) => unit.id !== ctx.caster);
|
|
363
|
+
if (candidates.length === 0) {
|
|
364
|
+
return buildEmptyResult(ctx, []);
|
|
365
|
+
}
|
|
366
|
+
const pool = [...candidates];
|
|
367
|
+
const hitTargets = [];
|
|
368
|
+
let totalDamage = 0;
|
|
369
|
+
const hits = [];
|
|
370
|
+
const hitCount = Math.min(4, pool.length);
|
|
371
|
+
for (let i = 0; i < hitCount; i++) {
|
|
372
|
+
const index = ctx.api.randomInt(pool.length);
|
|
373
|
+
const [target] = pool.splice(index, 1);
|
|
374
|
+
hitTargets.push(target.id);
|
|
375
|
+
const damage = ctx.api.damage(ctx.caster, target.id, Math.floor(self.stats.Att * 0.5));
|
|
376
|
+
totalDamage += damage;
|
|
377
|
+
hits.push(buildDamageHit(ctx, target.id, damage));
|
|
378
|
+
if (target.teamId === self.teamId) {
|
|
379
|
+
ctx.api.gainEnergy(ctx.caster, 10);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return {
|
|
383
|
+
...buildEmptyResult(ctx, hitTargets),
|
|
384
|
+
totalDamage,
|
|
385
|
+
hits
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
const kesiUltimateScript = {
|
|
390
|
+
onCast(ctx) {
|
|
391
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
392
|
+
if (!self) {
|
|
393
|
+
return buildEmptyResult(ctx, []);
|
|
394
|
+
}
|
|
395
|
+
const enemies = ctx.api.getAliveUnits().filter((unit) => unit.teamId !== self.teamId);
|
|
396
|
+
if (enemies.length === 0) {
|
|
397
|
+
return buildEmptyResult(ctx, []);
|
|
398
|
+
}
|
|
399
|
+
let totalDamage = 0;
|
|
400
|
+
const hitTargets = [];
|
|
401
|
+
const attacked = new Set();
|
|
402
|
+
const hits = [];
|
|
403
|
+
for (let i = 0; i < 8; i++) {
|
|
404
|
+
const target = enemies[ctx.api.randomInt(enemies.length)];
|
|
405
|
+
hitTargets.push(target.id);
|
|
406
|
+
attacked.add(target.id);
|
|
407
|
+
const damage = ctx.api.damage(ctx.caster, target.id, Math.floor(self.stats.Att * 0.8));
|
|
408
|
+
totalDamage += damage;
|
|
409
|
+
hits.push(buildDamageHit(ctx, target.id, damage));
|
|
410
|
+
}
|
|
411
|
+
for (const targetId of attacked) {
|
|
412
|
+
const target = ctx.api.getUnit(targetId);
|
|
413
|
+
if (!target) {
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
const dotValue = ctx.api
|
|
417
|
+
.getBuffs(targetId)
|
|
418
|
+
.filter((buff) => buff.stacks > 0 && buff.config.dotRatio)
|
|
419
|
+
.reduce((sum, buff) => sum + Math.floor(target.stats.Att * (buff.config.dotRatio ?? 0) * buff.stacks), 0);
|
|
420
|
+
if (dotValue > 0) {
|
|
421
|
+
const damage = ctx.api.damage(ctx.caster, targetId, Math.floor(dotValue * 0.6));
|
|
422
|
+
totalDamage += damage;
|
|
423
|
+
hits.push(buildDamageHit(ctx, target.id, damage));
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
...buildEmptyResult(ctx, hitTargets),
|
|
428
|
+
totalDamage,
|
|
429
|
+
hits
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
const kleiwuBasicScript = {
|
|
434
|
+
onCast(ctx) {
|
|
435
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
436
|
+
const targetId = ctx.targets[0];
|
|
437
|
+
if (!self || !targetId) {
|
|
438
|
+
return buildEmptyResult(ctx, targetId ? [targetId] : []);
|
|
439
|
+
}
|
|
440
|
+
const hits = [];
|
|
441
|
+
// 50%概率施加侵蚀
|
|
442
|
+
if (ctx.api.randomInt(10000) < 5000) {
|
|
443
|
+
ctx.api.addBuff(ctx.caster, targetId, "erosion");
|
|
444
|
+
hits.push(buildBuffHit(ctx, targetId, "erosion"));
|
|
445
|
+
}
|
|
446
|
+
return {
|
|
447
|
+
...buildEmptyResult(ctx, ctx.targets),
|
|
448
|
+
totalDamage: 0,
|
|
449
|
+
hits
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
const kleiwuCoreScript = {
|
|
454
|
+
onCast(ctx) {
|
|
455
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
456
|
+
const targetId = ctx.targets[0];
|
|
457
|
+
if (!self || !targetId) {
|
|
458
|
+
return buildEmptyResult(ctx, targetId ? [targetId] : []);
|
|
459
|
+
}
|
|
460
|
+
const hits = [];
|
|
461
|
+
// 赋予侵蚀
|
|
462
|
+
ctx.api.addBuff(ctx.caster, targetId, "erosion");
|
|
463
|
+
hits.push(buildBuffHit(ctx, targetId, "erosion"));
|
|
464
|
+
// 往前拉一格 - 位移
|
|
465
|
+
ctx.api.pushPosition(targetId, -1);
|
|
466
|
+
return {
|
|
467
|
+
...buildEmptyResult(ctx, ctx.targets),
|
|
468
|
+
hits
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
const kleiwuPassiveScript = {
|
|
473
|
+
onCast(ctx) {
|
|
474
|
+
ctx.api.onAnyEvent(ctx.caster, "OnDamageDealt", (data) => {
|
|
475
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
476
|
+
if (!self)
|
|
477
|
+
return;
|
|
478
|
+
if (ctx.api.isUnitTurn(ctx.caster)) {
|
|
479
|
+
ctx.api.gainEnergy(ctx.caster, 8);
|
|
480
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "rage");
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
ctx.api.onAnyEvent(ctx.caster, "OnImbalanceBreak", (data) => {
|
|
484
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
485
|
+
const source = ctx.api.getUnit(data.sourceId);
|
|
486
|
+
const target = ctx.api.getUnit(data.targetId);
|
|
487
|
+
if (!self || !source || !target || !self.runtime.alive || !source.runtime.alive || !target.runtime.alive) {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
if (self.id === source.id || self.teamId !== source.teamId || self.teamId === target.teamId) {
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
ctx.api.castSkill(ctx.caster, "11051", "chase", [target.id]);
|
|
494
|
+
});
|
|
495
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
const kleiwuUltimateScript = {
|
|
499
|
+
onCast(ctx) {
|
|
500
|
+
// 伤害和溅射由模板处理
|
|
501
|
+
// 额外累计30%失衡值由系统处理
|
|
502
|
+
return buildEmptyResult(ctx, ctx.targets);
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
const rudyCoreScript = {
|
|
506
|
+
onCast(ctx) {
|
|
507
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
508
|
+
if (!self) {
|
|
509
|
+
return buildEmptyResult(ctx, ctx.targets);
|
|
510
|
+
}
|
|
511
|
+
// 添加3层反击
|
|
512
|
+
for (let i = 0; i < 3; i++) {
|
|
513
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "counter");
|
|
514
|
+
}
|
|
515
|
+
return buildEmptyResult(ctx, ctx.targets);
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
// 鲁迪被动:拥有【反击】时首次受到致命伤时免死,恢复50%生命
|
|
519
|
+
const rudyPassiveScript = {
|
|
520
|
+
onCast(ctx) {
|
|
521
|
+
// 监听OnDeath事件,在死亡时触发免死+回血
|
|
522
|
+
ctx.api.onAnyEvent(ctx.caster, "OnDeath", (data) => {
|
|
523
|
+
if (data.targetId !== ctx.caster)
|
|
524
|
+
return;
|
|
525
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
526
|
+
if (!self)
|
|
527
|
+
return;
|
|
528
|
+
// 检查是否拥有反击且未使用过免死
|
|
529
|
+
const hasCounter = ctx.api.getBuffs(ctx.caster).some(b => b.id === "counter" && b.stacks > 0);
|
|
530
|
+
if (hasCounter && !ctx.api.hasBuff(ctx.caster, "rudy-cheat-death")) {
|
|
531
|
+
// 免死:恢复alive状态并回血50%最大生命
|
|
532
|
+
ctx.api.preventDeath(ctx.caster);
|
|
533
|
+
ctx.api.heal(ctx.caster, Math.floor(self.stats.Mhp * 0.5));
|
|
534
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "rudy-cheat-death");
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
const rudyUltimateScript = {
|
|
541
|
+
onCast(ctx) {
|
|
542
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
543
|
+
if (!self) {
|
|
544
|
+
return buildEmptyResult(ctx, ctx.targets);
|
|
545
|
+
}
|
|
546
|
+
// 添加3层反击
|
|
547
|
+
for (let i = 0; i < 3; i++) {
|
|
548
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "counter");
|
|
549
|
+
}
|
|
550
|
+
// 护盾由模板处理
|
|
551
|
+
return buildEmptyResult(ctx, ctx.targets);
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
const ailishaCoreScript = {
|
|
555
|
+
onCast(ctx) {
|
|
556
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
557
|
+
if (self) {
|
|
558
|
+
for (const unit of ctx.api.getAliveUnits()) {
|
|
559
|
+
if (unit.id === self.id || unit.teamId !== self.teamId) {
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
562
|
+
if (Math.abs(unit.position - self.position) <= 1) {
|
|
563
|
+
ctx.api.addBuff(self.id, unit.id, "share-damage");
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return {
|
|
568
|
+
skillId: ctx.skillId,
|
|
569
|
+
casterId: ctx.caster,
|
|
570
|
+
targets: ctx.targets,
|
|
571
|
+
totalDamage: 0,
|
|
572
|
+
totalHeal: 0,
|
|
573
|
+
totalShield: 0,
|
|
574
|
+
triggeredBy: ctx.trigger
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
// 艾莉莎大招:对生命值最高的敌人造成120%火属性伤害。消耗所有护盾恢复等量生命
|
|
579
|
+
const ailishaUltimateScript = {
|
|
580
|
+
onCast(ctx) {
|
|
581
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
582
|
+
const hits = [];
|
|
583
|
+
let totalHeal = 0;
|
|
584
|
+
if (self && self.runtime.Shield > 0) {
|
|
585
|
+
// 策划:消耗所有护盾恢复等量生命
|
|
586
|
+
const healAmount = self.runtime.Shield;
|
|
587
|
+
self.runtime.Shield = 0;
|
|
588
|
+
const heal = ctx.api.heal(ctx.caster, healAmount);
|
|
589
|
+
totalHeal += heal;
|
|
590
|
+
hits.push(buildHealHit(ctx, ctx.caster, heal));
|
|
591
|
+
}
|
|
592
|
+
if (self) {
|
|
593
|
+
ctx.api.removeBuff(ctx.caster, "ailisha-rebirth");
|
|
594
|
+
}
|
|
595
|
+
return {
|
|
596
|
+
...buildEmptyResult(ctx, ctx.targets),
|
|
597
|
+
totalHeal,
|
|
598
|
+
hits
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
const luolaiCoreScript = {
|
|
603
|
+
onCast(ctx) {
|
|
604
|
+
for (const unit of ctx.api.getAliveUnits()) {
|
|
605
|
+
if (unit.teamId !== ctx.api.getUnit(ctx.caster)?.teamId) {
|
|
606
|
+
continue;
|
|
607
|
+
}
|
|
608
|
+
ctx.api.addBuff(ctx.caster, unit.id, "condense");
|
|
609
|
+
}
|
|
610
|
+
return {
|
|
611
|
+
skillId: ctx.skillId,
|
|
612
|
+
casterId: ctx.caster,
|
|
613
|
+
targets: ctx.targets,
|
|
614
|
+
totalDamage: 0,
|
|
615
|
+
totalHeal: 0,
|
|
616
|
+
totalShield: 0,
|
|
617
|
+
triggeredBy: ctx.trigger
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
const luolaiBasicScript = {
|
|
622
|
+
onCast(ctx) {
|
|
623
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
624
|
+
if (!self) {
|
|
625
|
+
return buildEmptyResult(ctx, []);
|
|
626
|
+
}
|
|
627
|
+
const enemies = ctx.api.getAliveUnits().filter((unit) => unit.teamId !== self.teamId);
|
|
628
|
+
if (enemies.length === 0) {
|
|
629
|
+
return buildEmptyResult(ctx, []);
|
|
630
|
+
}
|
|
631
|
+
const target = enemies[ctx.api.randomInt(enemies.length)];
|
|
632
|
+
const allies = ctx.api.getAliveUnits()
|
|
633
|
+
.filter((unit) => unit.teamId === self.teamId)
|
|
634
|
+
.sort((a, b) => a.position - b.position);
|
|
635
|
+
const frontAlly = allies[0];
|
|
636
|
+
let totalDamage = 0;
|
|
637
|
+
let totalHeal = 0;
|
|
638
|
+
const hits = [];
|
|
639
|
+
const damage = ctx.api.damage(ctx.caster, target.id, Math.floor(self.stats.Att * 0.5));
|
|
640
|
+
totalDamage += damage;
|
|
641
|
+
hits.push(buildDamageHit(ctx, target.id, damage));
|
|
642
|
+
if (frontAlly) {
|
|
643
|
+
const heal = ctx.api.heal(frontAlly.id, Math.floor(damage * 0.5));
|
|
644
|
+
totalHeal += heal;
|
|
645
|
+
hits.push(buildHealHit(ctx, frontAlly.id, heal));
|
|
646
|
+
}
|
|
647
|
+
return {
|
|
648
|
+
...buildEmptyResult(ctx, [target.id]),
|
|
649
|
+
totalDamage,
|
|
650
|
+
totalHeal,
|
|
651
|
+
hits
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
const luolaiUltimateScript = {
|
|
656
|
+
onCast(ctx) {
|
|
657
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
658
|
+
if (!self) {
|
|
659
|
+
return buildEmptyResult(ctx, []);
|
|
660
|
+
}
|
|
661
|
+
const allies = ctx.api.getAliveUnits()
|
|
662
|
+
.filter((unit) => unit.teamId === self.teamId)
|
|
663
|
+
.sort((a, b) => a.position - b.position);
|
|
664
|
+
const frontAlly = allies[0];
|
|
665
|
+
if (!frontAlly) {
|
|
666
|
+
return buildEmptyResult(ctx, []);
|
|
667
|
+
}
|
|
668
|
+
const heal = ctx.api.heal(frontAlly.id, Math.floor(self.stats.Mhp * 0.2));
|
|
669
|
+
return {
|
|
670
|
+
...buildEmptyResult(ctx, [frontAlly.id]),
|
|
671
|
+
totalHeal: heal,
|
|
672
|
+
hits: [buildHealHit(ctx, frontAlly.id, heal)]
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
const pelaCoreScript = {
|
|
677
|
+
onCast(ctx) {
|
|
678
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
679
|
+
const target = ctx.api.getAliveUnits()
|
|
680
|
+
.filter((unit) => self && unit.teamId === self.teamId)
|
|
681
|
+
.sort((a, b) => b.position - a.position)[0];
|
|
682
|
+
if (target) {
|
|
683
|
+
ctx.api.addBuff(ctx.caster, target.id, "damage-up");
|
|
684
|
+
ctx.api.grantExtraTurn(target.id);
|
|
685
|
+
}
|
|
686
|
+
return {
|
|
687
|
+
skillId: ctx.skillId,
|
|
688
|
+
casterId: ctx.caster,
|
|
689
|
+
targets: ctx.targets,
|
|
690
|
+
totalDamage: 0,
|
|
691
|
+
totalHeal: 0,
|
|
692
|
+
totalShield: 0,
|
|
693
|
+
triggeredBy: ctx.trigger
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
// 佩拉大招:提高全体30%攻击力,附加自身10%暴击伤害持续2回合,赋予全体【行动提前】
|
|
698
|
+
const pelaUltimateScript = {
|
|
699
|
+
onCast(ctx) {
|
|
700
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
701
|
+
const allies = ctx.api.getAliveUnits().filter((u) => self && u.teamId === self.teamId);
|
|
702
|
+
for (const ally of allies) {
|
|
703
|
+
ctx.api.addBuff(ctx.caster, ally.id, "attack-up");
|
|
704
|
+
// 策划:赋予全体行动提前
|
|
705
|
+
ctx.api.adjustActionProgress(ally.id, 0.2);
|
|
706
|
+
}
|
|
707
|
+
// 策划:附加自身10%暴击伤害持续2回合
|
|
708
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "pela-crit-up");
|
|
709
|
+
return {
|
|
710
|
+
skillId: ctx.skillId,
|
|
711
|
+
casterId: ctx.caster,
|
|
712
|
+
targets: ctx.targets,
|
|
713
|
+
totalDamage: 0,
|
|
714
|
+
totalHeal: 0,
|
|
715
|
+
totalShield: 0,
|
|
716
|
+
triggeredBy: ctx.trigger
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
const cookPassiveScript = {
|
|
721
|
+
onCast(ctx) {
|
|
722
|
+
ctx.api.onAnyEvent(ctx.caster, "OnAfterDamage", (data) => {
|
|
723
|
+
if (data.targetId !== ctx.caster || data.value <= 0 || data.sourceId === data.targetId) {
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
727
|
+
if (!self || !self.runtime.alive) {
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "cook-restraint");
|
|
731
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "cook-counter");
|
|
732
|
+
});
|
|
733
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
734
|
+
}
|
|
735
|
+
};
|
|
736
|
+
const miaoluoPassiveScript = {
|
|
737
|
+
onCast(ctx) {
|
|
738
|
+
ctx.api.onAnyEvent(ctx.caster, "OnAfterDamage", (data) => {
|
|
739
|
+
if (data.value <= 0 || data.sourceId === ctx.caster) {
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
743
|
+
const source = ctx.api.getUnit(data.sourceId);
|
|
744
|
+
const target = ctx.api.getUnit(data.targetId);
|
|
745
|
+
if (!self || !source || !target || !self.runtime.alive || !source.runtime.alive || !target.runtime.alive) {
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
if (self.teamId !== source.teamId || self.teamId === target.teamId) {
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
if (!ctx.api.hasBuff(ctx.caster, "flash")) {
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
ctx.api.castSkill(ctx.caster, "11021", "chase", [target.id]);
|
|
755
|
+
});
|
|
756
|
+
ctx.api.onAnyEvent(ctx.caster, "OnAfterDamage", (data) => {
|
|
757
|
+
if (data.sourceId !== ctx.caster || data.value <= 0) {
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
761
|
+
const target = ctx.api.getUnit(data.targetId);
|
|
762
|
+
if (!self || !target || self.teamId === target.teamId || !ctx.api.hasBuff(ctx.caster, "miaoluo-ultimate-focus")) {
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
ctx.api.addBuff(ctx.caster, target.id, "imbalance-vulnerability");
|
|
766
|
+
});
|
|
767
|
+
ctx.api.onAnyEvent(ctx.caster, "OnAfterCast", (data) => {
|
|
768
|
+
if (data.actorId !== ctx.caster || data.skillId !== "11024") {
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
if (ctx.api.hasBuff(ctx.caster, "miaoluo-ultimate-focus")) {
|
|
772
|
+
ctx.api.removeBuff(ctx.caster, "miaoluo-ultimate-focus");
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
// 克丝被动:造成伤害时,概率施加【点燃】效果
|
|
779
|
+
const kesiPassiveScript = {
|
|
780
|
+
onCast(ctx) {
|
|
781
|
+
ctx.api.onAnyEvent(ctx.caster, "OnAfterDamage", (data) => {
|
|
782
|
+
if (data.sourceId === ctx.caster && data.value > 0) {
|
|
783
|
+
const target = ctx.api.getUnit(data.targetId);
|
|
784
|
+
if (target && target.teamId !== ctx.api.getUnit(ctx.caster)?.teamId) {
|
|
785
|
+
if (ctx.api.randomInt(10000) < 5000) {
|
|
786
|
+
ctx.api.addBuff(ctx.caster, data.targetId, "burn");
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
792
|
+
}
|
|
793
|
+
};
|
|
794
|
+
// 布莱德/岚被动:造成伤害时概率施加【点燃】效果,若击杀敌人则获得60%【行动提前】
|
|
795
|
+
const bladePassiveScript = {
|
|
796
|
+
onCast(ctx) {
|
|
797
|
+
ctx.api.onAnyEvent(ctx.caster, "OnAfterDamage", (data) => {
|
|
798
|
+
if (data.sourceId === ctx.caster && data.value > 0) {
|
|
799
|
+
const target = ctx.api.getUnit(data.targetId);
|
|
800
|
+
if (target && target.teamId !== ctx.api.getUnit(ctx.caster)?.teamId) {
|
|
801
|
+
if (ctx.api.randomInt(10000) < 5000) {
|
|
802
|
+
ctx.api.addBuff(ctx.caster, data.targetId, "burn");
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
ctx.api.onAnyEvent(ctx.caster, "OnKill", (data) => {
|
|
808
|
+
if (data.killerId === ctx.caster) {
|
|
809
|
+
ctx.api.adjustActionProgress(ctx.caster, 0.6);
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
// 洛洛被动:每次受到伤害时,获得【惩戒/意志】
|
|
816
|
+
const luoluoPassiveScript = {
|
|
817
|
+
onCast(ctx) {
|
|
818
|
+
// 监听 OnAfterDamage 事件(battleCore中实际存在的事件名)
|
|
819
|
+
ctx.api.onAnyEvent(ctx.caster, "OnAfterDamage", (data) => {
|
|
820
|
+
if (data.targetId === ctx.caster && data.value > 0) {
|
|
821
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "will");
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
825
|
+
}
|
|
826
|
+
};
|
|
827
|
+
// 艾莉莎被动:血量低于30%时移至队尾无法行动1回合,获得60%最大生命护盾,护盾消失回原位,每场2次
|
|
828
|
+
const ailishaPassiveScript = {
|
|
829
|
+
onCast(ctx) {
|
|
830
|
+
ctx.api.onAnyEvent(ctx.caster, "OnAfterDamage", (data) => {
|
|
831
|
+
if (data.targetId !== ctx.caster || data.value <= 0)
|
|
832
|
+
return;
|
|
833
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
834
|
+
if (!self || !self.runtime.alive)
|
|
835
|
+
return;
|
|
836
|
+
const rebirthStacks = ctx.api
|
|
837
|
+
.getBuffs(ctx.caster)
|
|
838
|
+
.filter((b) => b.id === "ailisha-rebirth")
|
|
839
|
+
.reduce((sum, item) => sum + item.stacks, 0);
|
|
840
|
+
if (rebirthStacks >= 2)
|
|
841
|
+
return;
|
|
842
|
+
if (self.runtime.Hp * 100 < self.stats.Mhp * 30) {
|
|
843
|
+
if (!ailishaOriginalPositions.has(ctx.caster)) {
|
|
844
|
+
ailishaOriginalPositions.set(ctx.caster, self.position);
|
|
845
|
+
}
|
|
846
|
+
const shield = Math.floor(self.stats.Mhp * 0.6);
|
|
847
|
+
ctx.api.shield(ctx.caster, shield);
|
|
848
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "ailisha-rebirth");
|
|
849
|
+
ctx.api.addBuff(ctx.caster, ctx.caster, "ailisha-silent");
|
|
850
|
+
ctx.api.pushPosition(ctx.caster, 999);
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
ctx.api.onAnyEvent(ctx.caster, "OnTurnStart", (data) => {
|
|
854
|
+
if (data.actorId !== ctx.caster)
|
|
855
|
+
return;
|
|
856
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
857
|
+
const originalPosition = ailishaOriginalPositions.get(ctx.caster);
|
|
858
|
+
if (!self || originalPosition === undefined || self.runtime.Shield > 0) {
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
if (self.position !== originalPosition) {
|
|
862
|
+
ctx.api.pushPosition(ctx.caster, originalPosition - self.position);
|
|
863
|
+
}
|
|
864
|
+
});
|
|
865
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
// 洛莱被动:治疗友军溢出的治疗量,转为友军伤害提升值,持续1回合
|
|
869
|
+
const luolaiPassiveScript = {
|
|
870
|
+
onCast(ctx) {
|
|
871
|
+
// 溢出治疗转伤害提升的逻辑需要在治疗系统中实现
|
|
872
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
// 提尔大招:攻击最近的敌人造成250%风属性伤害,并有30%概率将敌人击退2格
|
|
876
|
+
const tierUltimateScript = {
|
|
877
|
+
onCast(ctx) {
|
|
878
|
+
const targetId = ctx.targets[0];
|
|
879
|
+
if (!targetId)
|
|
880
|
+
return buildEmptyResult(ctx, []);
|
|
881
|
+
// 策划:30%概率击退2格
|
|
882
|
+
if (ctx.api.randomInt(10000) < 3000) {
|
|
883
|
+
ctx.api.pushPosition(targetId, 2);
|
|
884
|
+
}
|
|
885
|
+
return buildEmptyResult(ctx, [targetId]);
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
// 提尔被动:对敌人造成伤害时有50%概率将敌人部分负面效果扩散至相邻随机一名敌人
|
|
889
|
+
const tierPassiveScript = {
|
|
890
|
+
onCast(ctx) {
|
|
891
|
+
ctx.api.onAnyEvent(ctx.caster, "OnAfterDamage", (data) => {
|
|
892
|
+
if (data.sourceId === ctx.caster && data.value > 0) {
|
|
893
|
+
if (ctx.api.randomInt(10000) < 5000) {
|
|
894
|
+
const target = ctx.api.getUnit(data.targetId);
|
|
895
|
+
if (target) {
|
|
896
|
+
const debuffs = ctx.api.getBuffs(data.targetId).filter(b => b.stacks > 0);
|
|
897
|
+
if (debuffs.length > 0) {
|
|
898
|
+
const enemies = ctx.api.getAliveUnits().filter(u => u.teamId === target.teamId && u.id !== data.targetId);
|
|
899
|
+
if (enemies.length > 0) {
|
|
900
|
+
const randomEnemy = enemies[ctx.api.randomInt(enemies.length)];
|
|
901
|
+
const randomDebuff = debuffs[ctx.api.randomInt(debuffs.length)];
|
|
902
|
+
ctx.api.addBuff(ctx.caster, randomEnemy.id, randomDebuff.id);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
});
|
|
909
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
// 埃斯被动:攻击时概率施加【炫目】效果
|
|
913
|
+
const esPassiveScript = {
|
|
914
|
+
onCast(ctx) {
|
|
915
|
+
ctx.api.onAnyEvent(ctx.caster, "OnAfterDamage", (data) => {
|
|
916
|
+
if (data.sourceId === ctx.caster && data.value > 0) {
|
|
917
|
+
const target = ctx.api.getUnit(data.targetId);
|
|
918
|
+
if (target && target.teamId !== ctx.api.getUnit(ctx.caster)?.teamId) {
|
|
919
|
+
if (ctx.api.randomInt(10000) < 5000) {
|
|
920
|
+
ctx.api.addBuff(ctx.caster, data.targetId, "dazzle");
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
const esCoreScript = {
|
|
929
|
+
onCast(ctx) {
|
|
930
|
+
const self = ctx.api.getUnit(ctx.caster);
|
|
931
|
+
if (!self) {
|
|
932
|
+
return buildEmptyResult(ctx, []);
|
|
933
|
+
}
|
|
934
|
+
const enemies = ctx.api.getAliveUnits()
|
|
935
|
+
.filter((unit) => unit.teamId !== self.teamId)
|
|
936
|
+
.sort((a, b) => a.position - b.position)
|
|
937
|
+
.slice(0, 2);
|
|
938
|
+
let totalDamage = 0;
|
|
939
|
+
const hits = [];
|
|
940
|
+
for (const enemy of enemies) {
|
|
941
|
+
const damage = ctx.api.damage(ctx.caster, enemy.id, Math.floor(self.stats.Att * 0.35));
|
|
942
|
+
totalDamage += damage;
|
|
943
|
+
hits.push(buildDamageHit(ctx, enemy.id, damage));
|
|
944
|
+
const resisted = ctx.api.randomInt(10000) >= 5000;
|
|
945
|
+
if (!resisted) {
|
|
946
|
+
ctx.api.addBuff(ctx.caster, enemy.id, "dazzle");
|
|
947
|
+
}
|
|
948
|
+
hits.push(buildBuffHit(ctx, enemy.id, "dazzle", resisted));
|
|
949
|
+
}
|
|
950
|
+
return {
|
|
951
|
+
...buildEmptyResult(ctx, enemies.map((item) => item.id)),
|
|
952
|
+
totalDamage,
|
|
953
|
+
hits
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
};
|
|
957
|
+
// 佩拉被动:每次普攻后,自身行动条提高15%
|
|
958
|
+
const pelaPassiveScript = {
|
|
959
|
+
onCast(ctx) {
|
|
960
|
+
ctx.api.onAnyEvent(ctx.caster, "OnAfterDamage", (data) => {
|
|
961
|
+
if (data.sourceId === ctx.caster) {
|
|
962
|
+
// 判断是否是普攻(基础技能)
|
|
963
|
+
ctx.api.adjustActionProgress(ctx.caster, 0.15);
|
|
964
|
+
}
|
|
965
|
+
});
|
|
966
|
+
return buildEmptyResult(ctx, [ctx.caster]);
|
|
967
|
+
}
|
|
968
|
+
};
|
|
969
|
+
export const designedScripts = {
|
|
970
|
+
"blade.basic.script": bladeBasicScript,
|
|
971
|
+
"blade.core.script": bladeCoreScript,
|
|
972
|
+
"blade.ultimate.script": bladeUltimateScript,
|
|
973
|
+
"blade.passive.script": bladePassiveScript,
|
|
974
|
+
"kesi.core.script": kesiCoreScript,
|
|
975
|
+
"kesi.ultimate.script": kesiUltimateScript,
|
|
976
|
+
"kesi.passive.script": kesiPassiveScript,
|
|
977
|
+
"kleiwu.basic.script": kleiwuBasicScript,
|
|
978
|
+
"kleiwu.core.script": kleiwuCoreScript,
|
|
979
|
+
"kleiwu.passive.script": kleiwuPassiveScript,
|
|
980
|
+
"kleiwu.ultimate.script": kleiwuUltimateScript,
|
|
981
|
+
"luoluo.basic.script": luoluoBasicScript,
|
|
982
|
+
"luoluo.core.script": luoluoCoreScript,
|
|
983
|
+
"luoluo.passive.script": luoluoPassiveScript,
|
|
984
|
+
"miaoluo.basic.script": miaoluoBasicScript,
|
|
985
|
+
"miaoluo.core.script": miaoluoCoreScript,
|
|
986
|
+
"miaoluo.ultimate.script": miaoluoUltimateScript,
|
|
987
|
+
"miaoluo.passive.script": miaoluoPassiveScript,
|
|
988
|
+
"rudy.core.script": rudyCoreScript,
|
|
989
|
+
"rudy.passive.script": rudyPassiveScript,
|
|
990
|
+
"rudy.ultimate.script": rudyUltimateScript,
|
|
991
|
+
"ailisha.core.script": ailishaCoreScript,
|
|
992
|
+
"ailisha.ultimate.script": ailishaUltimateScript,
|
|
993
|
+
"ailisha.passive.script": ailishaPassiveScript,
|
|
994
|
+
"luolai.basic.script": luolaiBasicScript,
|
|
995
|
+
"luolai.core.script": luolaiCoreScript,
|
|
996
|
+
"luolai.ultimate.script": luolaiUltimateScript,
|
|
997
|
+
"luolai.passive.script": luolaiPassiveScript,
|
|
998
|
+
"pela.core.script": pelaCoreScript,
|
|
999
|
+
"pela.ultimate.script": pelaUltimateScript,
|
|
1000
|
+
"pela.passive.script": pelaPassiveScript,
|
|
1001
|
+
"cook.basic.script": cookBasicScript,
|
|
1002
|
+
"cook.core.script": cookCoreScript,
|
|
1003
|
+
"cook.ultimate.script": cookUltimateScript,
|
|
1004
|
+
"cook.passive.script": cookPassiveScript,
|
|
1005
|
+
"tier.passive.script": tierPassiveScript,
|
|
1006
|
+
"es.core.script": esCoreScript,
|
|
1007
|
+
"es.passive.script": esPassiveScript,
|
|
1008
|
+
"tier.ultimate.script": tierUltimateScript,
|
|
1009
|
+
...monsterScripts16xx,
|
|
1010
|
+
...monsterScripts18xx,
|
|
1011
|
+
...monsterScripts19xxPart1,
|
|
1012
|
+
...monsterScripts19xxPart2,
|
|
1013
|
+
};
|