koishi-plugin-ggcevo-game 1.4.46 → 1.4.48
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/boss/BattleEffectProcessor.d.ts +4 -1
- package/lib/boss/attackhandling.d.ts +7 -0
- package/lib/boss/damagecalculation.d.ts +1 -4
- package/lib/index.js +1934 -1856
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1270,1142 +1270,6 @@ var bossPool = [
|
|
|
1270
1270
|
}
|
|
1271
1271
|
];
|
|
1272
1272
|
|
|
1273
|
-
// src/boss/passive.ts
|
|
1274
|
-
var passiveConfig = {
|
|
1275
|
-
"弱化形态": {
|
|
1276
|
-
type: "伤害增减(负面)",
|
|
1277
|
-
description: "子代防御脆弱,受到的伤害提高10%"
|
|
1278
|
-
},
|
|
1279
|
-
"异形甲壳": {
|
|
1280
|
-
type: "伤害增减(正面)",
|
|
1281
|
-
description: "受到的伤害降低20%"
|
|
1282
|
-
},
|
|
1283
|
-
"冰霜回复": {
|
|
1284
|
-
type: "生存强化(生命回复)",
|
|
1285
|
-
description: "生命值≤30%时,立即回复自身40%最大生命值,并为所有其他存活异形回复10%最大生命值(生效后移除)"
|
|
1286
|
-
},
|
|
1287
|
-
"冰霜进化": {
|
|
1288
|
-
type: "状态免疫(寒冷伤害免疫)",
|
|
1289
|
-
description: "免疫寒冷伤害,受到寒冷攻击时回复等量生命值"
|
|
1290
|
-
},
|
|
1291
|
-
"冰霜环绕": {
|
|
1292
|
-
type: "生存强化(生命回复+群体增益)",
|
|
1293
|
-
description: "生命值≤30%时,立即回复自身45%最大生命值,并使所有存活异形获得「寒霜地狱」技能(生效后移除)"
|
|
1294
|
-
},
|
|
1295
|
-
"寒霜地狱": {
|
|
1296
|
-
type: "伤害增减(正面)",
|
|
1297
|
-
description: "受到的伤害降低30%"
|
|
1298
|
-
},
|
|
1299
|
-
"应激甲壳I": {
|
|
1300
|
-
type: "伤害增减(正面)",
|
|
1301
|
-
description: "受到的伤害降低20%"
|
|
1302
|
-
},
|
|
1303
|
-
"应激甲壳II": {
|
|
1304
|
-
type: "伤害增减(正面)",
|
|
1305
|
-
description: "受到的伤害降低25%"
|
|
1306
|
-
},
|
|
1307
|
-
"求生本能I": {
|
|
1308
|
-
type: "生存强化(生命回复)",
|
|
1309
|
-
description: "濒死时立即回复自身30%最大生命值(生效后移除)"
|
|
1310
|
-
},
|
|
1311
|
-
"求生本能II": {
|
|
1312
|
-
type: "生存强化(生命回复)",
|
|
1313
|
-
description: "濒死时立即回复自身50%最大生命值(生效后移除)"
|
|
1314
|
-
},
|
|
1315
|
-
"冷适应": {
|
|
1316
|
-
type: "状态免疫(寒冷伤害免疫)",
|
|
1317
|
-
description: "累计承受10次寒冷伤害后,获得「惧热」标签并永久免疫寒冷伤害"
|
|
1318
|
-
},
|
|
1319
|
-
"感染空间站": {
|
|
1320
|
-
type: "伤害增减(正面)",
|
|
1321
|
-
description: "当空间站哨枪塔存活时,自身受到的伤害降低50%"
|
|
1322
|
-
},
|
|
1323
|
-
"病毒云": {
|
|
1324
|
-
type: "伤害增减(正面)",
|
|
1325
|
-
description: "受到的伤害降低10%"
|
|
1326
|
-
},
|
|
1327
|
-
"霉菌滋生": {
|
|
1328
|
-
type: "生存强化(生命回复)",
|
|
1329
|
-
description: "受击后,若空间站哨枪塔存活,为其回复1%最大生命值"
|
|
1330
|
-
},
|
|
1331
|
-
"岗哨机枪": {
|
|
1332
|
-
type: "生存强化(生命回复)",
|
|
1333
|
-
description: "每累计承受10次攻击,为所有其他存活异形回复10%最大生命值"
|
|
1334
|
-
},
|
|
1335
|
-
"结构装甲": {
|
|
1336
|
-
type: "伤害增减(正面)",
|
|
1337
|
-
description: "受实弹/能量武器伤害降低20%,受热能武器伤害降低40%"
|
|
1338
|
-
},
|
|
1339
|
-
"吸血唾液": {
|
|
1340
|
-
type: "伤害增减(正面)",
|
|
1341
|
-
description: "受击获得1层「吸血唾液」(上限20层),每层使受到的伤害降低5%"
|
|
1342
|
-
},
|
|
1343
|
-
"进食": {
|
|
1344
|
-
type: "生存强化(生命回复)",
|
|
1345
|
-
description: "「吸血唾液」≥20层时,下次受击消耗所有层数并回复自身20%最大生命值"
|
|
1346
|
-
},
|
|
1347
|
-
"嗜血狂暴": {
|
|
1348
|
-
type: "伤害增减(正面)",
|
|
1349
|
-
description: "生命值≤50%时,受击额外获得1层「吸血唾液」且受到的伤害降低20%"
|
|
1350
|
-
},
|
|
1351
|
-
"吐血": {
|
|
1352
|
-
type: "伤害增减(负面)",
|
|
1353
|
-
description: "无「吸血唾液」层数时,受到的伤害提高20%"
|
|
1354
|
-
},
|
|
1355
|
-
"超导体": {
|
|
1356
|
-
type: "状态转换(护盾→重甲)",
|
|
1357
|
-
description: "生命值≤10%时,护盾标签永久转换为重甲标签"
|
|
1358
|
-
},
|
|
1359
|
-
"能量虹吸": {
|
|
1360
|
-
type: "伤害增减(正面)",
|
|
1361
|
-
description: "生命值≥70%时伤害降低40%,30%-70%时伤害降低20%"
|
|
1362
|
-
},
|
|
1363
|
-
"能源虹吸": {
|
|
1364
|
-
type: "伤害增减(正面)",
|
|
1365
|
-
description: "能量值≥80%时伤害降低50%,50%-80%时伤害降低30%"
|
|
1366
|
-
},
|
|
1367
|
-
"电能立场": {
|
|
1368
|
-
type: "状态免疫(伤害免疫)",
|
|
1369
|
-
description: "能量值≥30%时,55%概率免疫非热能伤害(每层寒冷降低5%触发概率)"
|
|
1370
|
-
},
|
|
1371
|
-
"电能冲击波": {
|
|
1372
|
-
type: "生存强化(能量回复)",
|
|
1373
|
-
description: "受击后回复100点能量"
|
|
1374
|
-
},
|
|
1375
|
-
"脉冲": {
|
|
1376
|
-
type: "生存强化(生命回复)",
|
|
1377
|
-
description: "能量值≥30%时,60%概率为所有存活异形回复100点生命(每层寒冷降低5%触发概率)"
|
|
1378
|
-
},
|
|
1379
|
-
"能量黑洞": {
|
|
1380
|
-
type: "伤害增减(正面)",
|
|
1381
|
-
description: "存在能量黑洞时,受到的伤害降低20%"
|
|
1382
|
-
},
|
|
1383
|
-
"火焰异形": {
|
|
1384
|
-
type: "状态免疫(火焰伤害免疫)",
|
|
1385
|
-
description: "免疫火焰伤害,受到火焰攻击时回复等量生命值"
|
|
1386
|
-
},
|
|
1387
|
-
"庞兽狂暴": {
|
|
1388
|
-
type: "伤害增减(正面)",
|
|
1389
|
-
description: "生命值≤50%时,受到的伤害降低50%"
|
|
1390
|
-
},
|
|
1391
|
-
"灼烧粘液": {
|
|
1392
|
-
type: "生存强化(生命回复)",
|
|
1393
|
-
description: "受击获得1层「灼烧粘液」;受火焰攻击时消耗所有层数并回复(层数×10)点生命"
|
|
1394
|
-
},
|
|
1395
|
-
"腐蚀胆汁": {
|
|
1396
|
-
type: "生存强化(生命回复)",
|
|
1397
|
-
description: "「灼烧粘液」≥10层时,下次受击消耗所有层数并为所有存活异形回复1000点生命"
|
|
1398
|
-
},
|
|
1399
|
-
"火焰吐息": {
|
|
1400
|
-
type: "生存强化(生命回复)",
|
|
1401
|
-
description: "「灼烧粘液」≥20层时,下次攻击消耗所有层数并为所有存活异形回复20%最大生命值"
|
|
1402
|
-
},
|
|
1403
|
-
"太阳耀斑": {
|
|
1404
|
-
type: "状态移除+状态免疫(寒冷伤害免疫)",
|
|
1405
|
-
description: "所有子代阵亡后,移除惧寒标签和孤立无援状态,并永久免疫寒冷伤害"
|
|
1406
|
-
},
|
|
1407
|
-
"燃烧潜地": {
|
|
1408
|
-
type: "生存强化(生命回复)",
|
|
1409
|
-
description: "生命值≤10%时立即回复50%最大生命值(生效后移除)"
|
|
1410
|
-
},
|
|
1411
|
-
"炼狱爆弹": {
|
|
1412
|
-
type: "伤害增减(正面)",
|
|
1413
|
-
description: "每层「灼烧粘液」使受到的伤害降低5%,存活子代存在时每层额外降低5%"
|
|
1414
|
-
},
|
|
1415
|
-
"猎手异形": {
|
|
1416
|
-
type: "伤害增减(条件性)+状态免疫(火焰/寒冷伤害免疫)",
|
|
1417
|
-
description: "存在其他存活异形时伤害降低20%,无其他存活异形时伤害提高20%;免疫火焰及寒冷伤害"
|
|
1418
|
-
},
|
|
1419
|
-
"狂暴": {
|
|
1420
|
-
type: "伤害增减(正面)",
|
|
1421
|
-
description: "生命值≤50%时,受到的伤害降低50%"
|
|
1422
|
-
},
|
|
1423
|
-
"伪装": {
|
|
1424
|
-
type: "伤害增减(正面)",
|
|
1425
|
-
description: "受击记录伤害来源武器名称,下次被同名武器攻击时伤害降低80%"
|
|
1426
|
-
},
|
|
1427
|
-
"致命一击": {
|
|
1428
|
-
type: "状态免疫(伤害免疫)",
|
|
1429
|
-
description: "受击时5%概率免疫该次伤害"
|
|
1430
|
-
},
|
|
1431
|
-
"星界之风": {
|
|
1432
|
-
type: "生存强化(生命回复)",
|
|
1433
|
-
description: "受击时5%概率为所有存活异形回复200点生命"
|
|
1434
|
-
},
|
|
1435
|
-
"心灵狂热": {
|
|
1436
|
-
type: "伤害增减(正面)",
|
|
1437
|
-
description: "生命值<50%时伤害降低20%且「星界之风」触发概率翻倍"
|
|
1438
|
-
},
|
|
1439
|
-
"宇宙能量": {
|
|
1440
|
-
type: "生存强化(能量/生命回复)",
|
|
1441
|
-
description: "受击回复等量能量值,能量溢出时转换为生命回复"
|
|
1442
|
-
},
|
|
1443
|
-
"复苏": {
|
|
1444
|
-
type: "生存强化(生命/能量回复)",
|
|
1445
|
-
description: "免疫致命伤害,回复60%最大生命与100%能量值,并获得「灵能构造炉」技能(生效后移除)"
|
|
1446
|
-
},
|
|
1447
|
-
"光影之刃": {
|
|
1448
|
-
type: "状态叠加(层数叠加)",
|
|
1449
|
-
description: "受击获得1层「光影之刃」(上限50层)"
|
|
1450
|
-
},
|
|
1451
|
-
"远古预兆": {
|
|
1452
|
-
type: "状态免疫(伤害免疫)+状态增强(触发概率提升)",
|
|
1453
|
-
description: "受击时1%概率免疫非热能伤害并回复100点能量,每层「光影之刃」使触发概率提升0.5%"
|
|
1454
|
-
},
|
|
1455
|
-
"超视距穿梭": {
|
|
1456
|
-
type: "伤害增减(条件性)",
|
|
1457
|
-
description: "能量≥60%时每层「光影之刃」使伤害降低10%,30%-60%时每层降低5%,能量≤10%时每层提高5%"
|
|
1458
|
-
},
|
|
1459
|
-
"灵能构造炉": {
|
|
1460
|
-
type: "状态获得(技能获得)",
|
|
1461
|
-
description: "受击时1%概率随机获得以下技能之一:天启超载护盾/塌缩脉冲/地毯式轰炸/轰炸引导"
|
|
1462
|
-
},
|
|
1463
|
-
"天启超载护盾": {
|
|
1464
|
-
type: "生存强化(生命回复)",
|
|
1465
|
-
description: "受击时10%概率触发,消耗当前「光影之刃」层数的一半(向下取整),并为所有存活异形回复(消耗层数×10)点生命"
|
|
1466
|
-
},
|
|
1467
|
-
"塌缩脉冲": {
|
|
1468
|
-
type: "状态叠加(层数叠加)",
|
|
1469
|
-
description: "受击后额外获得1层「光影之刃」"
|
|
1470
|
-
},
|
|
1471
|
-
"地毯式轰炸": {
|
|
1472
|
-
type: "状态移除+伤害增减(正面)",
|
|
1473
|
-
description: "移除孤立无援状态,受到的伤害降低80%"
|
|
1474
|
-
},
|
|
1475
|
-
"轰炸引导": {
|
|
1476
|
-
type: "生存强化(能量回复)",
|
|
1477
|
-
description: "受击时10%概率触发,消耗当前「光影之刃」层数的一半(向下取整),并回复(消耗层数×10)点能量"
|
|
1478
|
-
}
|
|
1479
|
-
};
|
|
1480
|
-
|
|
1481
|
-
// src/wish.ts
|
|
1482
|
-
var wishConfig = {
|
|
1483
|
-
// 普通祈愿(总概率 5 * 19=95%)
|
|
1484
|
-
common: [
|
|
1485
|
-
{
|
|
1486
|
-
name: "蚱蜢优购",
|
|
1487
|
-
effect: "下一次购买武器(非传奇)享有20%的折扣"
|
|
1488
|
-
},
|
|
1489
|
-
{
|
|
1490
|
-
name: "灵狐升运",
|
|
1491
|
-
effect: "下一次升级武器享有20%的折扣"
|
|
1492
|
-
},
|
|
1493
|
-
{
|
|
1494
|
-
name: "王权增幅",
|
|
1495
|
-
effect: "攻击伤害+10%"
|
|
1496
|
-
},
|
|
1497
|
-
{
|
|
1498
|
-
name: "金柚赐福",
|
|
1499
|
-
effect: "立即获得250枚金币"
|
|
1500
|
-
},
|
|
1501
|
-
{
|
|
1502
|
-
name: "夜市赠礼",
|
|
1503
|
-
effect: "立即获得5枚咕咕币"
|
|
1504
|
-
}
|
|
1505
|
-
],
|
|
1506
|
-
// 稀有祈愿(总概率 5 * 1=5%)
|
|
1507
|
-
rare: [
|
|
1508
|
-
{
|
|
1509
|
-
name: "悲鸣之锋",
|
|
1510
|
-
effect: "攻击伤害+10% (武器等级0),每级武器等级额外+10%"
|
|
1511
|
-
},
|
|
1512
|
-
{
|
|
1513
|
-
name: "精灵双倍",
|
|
1514
|
-
effect: "下一次击败主宰时可获得双倍的金币和咕咕币奖励"
|
|
1515
|
-
},
|
|
1516
|
-
{
|
|
1517
|
-
name: "喵喵财源",
|
|
1518
|
-
effect: "签到获得双倍的金币和咕咕币"
|
|
1519
|
-
},
|
|
1520
|
-
{
|
|
1521
|
-
name: "暴击韵律",
|
|
1522
|
-
effect: "攻击暴击率+20%"
|
|
1523
|
-
},
|
|
1524
|
-
{
|
|
1525
|
-
name: "酥手空空",
|
|
1526
|
-
effect: "立即失去50枚金币"
|
|
1527
|
-
}
|
|
1528
|
-
]
|
|
1529
|
-
};
|
|
1530
|
-
|
|
1531
|
-
// src/boss/damagecalculation.ts
|
|
1532
|
-
async function calculateTotalDamage(ctx, session, config, equippedWeapon, targetBoss, options) {
|
|
1533
|
-
let effectMessage = [];
|
|
1534
|
-
const finalTags = options?.customTags || targetBoss.tags || [];
|
|
1535
|
-
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
1536
|
-
const { regionId, realmId, profileId } = profile;
|
|
1537
|
-
const handle = `${regionId}-S2-${realmId}-${profileId}`;
|
|
1538
|
-
const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
|
|
1539
|
-
const [weaponName, weaponData] = weaponConfigEntry;
|
|
1540
|
-
const baseDamage = weaponData.damage * (1 + 0.1 * equippedWeapon.level);
|
|
1541
|
-
const levelBonusPercent = (0.1 * equippedWeapon.level * 100).toFixed(0);
|
|
1542
|
-
effectMessage.push(`🔫 ${weaponName}Lv.${equippedWeapon.level}:基础伤害+${levelBonusPercent}%`);
|
|
1543
|
-
let totalAdditive = 0;
|
|
1544
|
-
const tagAdditive = await calculateTagMultiplier(weaponData, finalTags, equippedWeapon);
|
|
1545
|
-
totalAdditive += tagAdditive;
|
|
1546
|
-
const { totalModAdd, hasCrit, modMessages } = calculateModifiers(
|
|
1547
|
-
equippedWeapon,
|
|
1548
|
-
weaponName,
|
|
1549
|
-
await checkCritRhythm(ctx, handle)
|
|
1550
|
-
);
|
|
1551
|
-
totalAdditive += totalModAdd;
|
|
1552
|
-
effectMessage.push(...modMessages);
|
|
1553
|
-
const careerBonus = await calculateCareerAdditive(ctx, handle, weaponData.type, weaponData.id);
|
|
1554
|
-
totalAdditive += careerBonus.value;
|
|
1555
|
-
if (careerBonus.message) effectMessage.push(careerBonus.message);
|
|
1556
|
-
const wishAdditive = await calculateWishAdditive(ctx, handle, equippedWeapon);
|
|
1557
|
-
totalAdditive += wishAdditive.value;
|
|
1558
|
-
if (wishAdditive.message) effectMessage.push(wishAdditive.message);
|
|
1559
|
-
const [rankRecord] = await ctx.database.get("ggcevo_rank", { handle, rankseason: config.rankseason });
|
|
1560
|
-
const rankAddResult = calculateRankAdditive(rankRecord);
|
|
1561
|
-
totalAdditive += rankAddResult.value;
|
|
1562
|
-
if (rankAddResult.message) {
|
|
1563
|
-
effectMessage.push(rankAddResult.message);
|
|
1564
|
-
}
|
|
1565
|
-
let finalDamage = baseDamage * (1 + totalAdditive);
|
|
1566
|
-
if (finalDamage < 1) {
|
|
1567
|
-
finalDamage = 1;
|
|
1568
|
-
}
|
|
1569
|
-
return {
|
|
1570
|
-
damage: Math.round(finalDamage),
|
|
1571
|
-
hasCrit,
|
|
1572
|
-
effectMessage
|
|
1573
|
-
};
|
|
1574
|
-
}
|
|
1575
|
-
__name(calculateTotalDamage, "calculateTotalDamage");
|
|
1576
|
-
async function checkCritRhythm(ctx, handle) {
|
|
1577
|
-
const [record] = await ctx.database.get("ggcevo_wish", {
|
|
1578
|
-
handle,
|
|
1579
|
-
wishname: "暴击韵律",
|
|
1580
|
-
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
1581
|
-
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
1582
|
-
});
|
|
1583
|
-
return !!record;
|
|
1584
|
-
}
|
|
1585
|
-
__name(checkCritRhythm, "checkCritRhythm");
|
|
1586
|
-
async function calculateTagMultiplier(weaponData, tags, equippedWeapon) {
|
|
1587
|
-
const MOD_EFFECTS = [
|
|
1588
|
-
{ mod: "裂甲核心", tag: "重甲", value: 1.5 },
|
|
1589
|
-
{ mod: "助燃核心", tag: "惧热", value: 3 },
|
|
1590
|
-
{ mod: "助燃核心", tag: "生物", value: 2 },
|
|
1591
|
-
{ mod: "金刚石瞄准镜", tag: "重甲", value: 0.8 },
|
|
1592
|
-
{ mod: "护盾崩解核心", tag: "护盾", value: 0.8 }
|
|
1593
|
-
];
|
|
1594
|
-
let totalAdditive = 0;
|
|
1595
|
-
for (const tag of tags) {
|
|
1596
|
-
const activeMod = MOD_EFFECTS.find(
|
|
1597
|
-
(me) => me.tag === tag && equippedWeapon.installedMods?.includes(me.mod)
|
|
1598
|
-
);
|
|
1599
|
-
const effectValue = activeMod ? activeMod.value : weaponData.tagEffects?.[tag] ?? 1;
|
|
1600
|
-
totalAdditive += effectValue - 1;
|
|
1601
|
-
}
|
|
1602
|
-
return totalAdditive;
|
|
1603
|
-
}
|
|
1604
|
-
__name(calculateTagMultiplier, "calculateTagMultiplier");
|
|
1605
|
-
function calculateModifiers(equippedWeapon, weaponName, hasCritRhythm) {
|
|
1606
|
-
let totalModAdd = 0;
|
|
1607
|
-
let hasCrit = false;
|
|
1608
|
-
const modMessages = [];
|
|
1609
|
-
let crystalCrit = 0;
|
|
1610
|
-
let overloadCrit = 0;
|
|
1611
|
-
let rhythmCrit = 0;
|
|
1612
|
-
let weaponCrit = 0;
|
|
1613
|
-
if (weaponName === "MK-4激光步枪") {
|
|
1614
|
-
weaponCrit = 80;
|
|
1615
|
-
modMessages.push(`🔫 【MK-4激光步枪】武器效果:暴击率+${weaponCrit}%`);
|
|
1616
|
-
}
|
|
1617
|
-
equippedWeapon.installedMods.forEach((mod) => {
|
|
1618
|
-
if (mod === "动能增幅") {
|
|
1619
|
-
totalModAdd += 0.2;
|
|
1620
|
-
modMessages.push(`🛠️ 【动能增幅】生效:攻击伤害+20%`);
|
|
1621
|
-
}
|
|
1622
|
-
if (mod === "裂甲核心" && weaponName === modConfig[mod].exclusiveTo) {
|
|
1623
|
-
totalModAdd += 0.4;
|
|
1624
|
-
modMessages.push(`🛠️ 【裂甲核心】生效:攻击伤害+40%`);
|
|
1625
|
-
}
|
|
1626
|
-
if (mod === "棱镜水晶") {
|
|
1627
|
-
crystalCrit = 20;
|
|
1628
|
-
modMessages.push(`🛠️ 【棱镜水晶】生效:暴击率+20%`);
|
|
1629
|
-
}
|
|
1630
|
-
if (mod === "棱镜超载核心" && weaponName === modConfig[mod].exclusiveTo) {
|
|
1631
|
-
overloadCrit = 80;
|
|
1632
|
-
modMessages.push(`🛠️ 【棱镜超载核心】生效:暴击率+80%`);
|
|
1633
|
-
}
|
|
1634
|
-
});
|
|
1635
|
-
rhythmCrit = hasCritRhythm ? 20 : 0;
|
|
1636
|
-
if (hasCritRhythm) {
|
|
1637
|
-
modMessages.push(`🎵 暴击韵律祈愿:暴击率+20%`);
|
|
1638
|
-
}
|
|
1639
|
-
const totalCritRate = Math.min(
|
|
1640
|
-
crystalCrit + overloadCrit + rhythmCrit + weaponCrit,
|
|
1641
|
-
// 包含武器专属暴击
|
|
1642
|
-
100
|
|
1643
|
-
);
|
|
1644
|
-
if (totalCritRate > 0) {
|
|
1645
|
-
}
|
|
1646
|
-
if (totalCritRate > 0) {
|
|
1647
|
-
const roll = Math.random() * 100;
|
|
1648
|
-
if (roll <= totalCritRate) {
|
|
1649
|
-
hasCrit = true;
|
|
1650
|
-
totalModAdd += 1;
|
|
1651
|
-
}
|
|
1652
|
-
}
|
|
1653
|
-
return {
|
|
1654
|
-
totalModAdd,
|
|
1655
|
-
hasCrit,
|
|
1656
|
-
modMessages
|
|
1657
|
-
// 返回模块消息数组
|
|
1658
|
-
};
|
|
1659
|
-
}
|
|
1660
|
-
__name(calculateModifiers, "calculateModifiers");
|
|
1661
|
-
async function calculateCareerAdditive(ctx, handle, weaponType, weaponId) {
|
|
1662
|
-
const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
|
|
1663
|
-
let value = 0;
|
|
1664
|
-
let message = "";
|
|
1665
|
-
if (careerData?.career === "警卫长") {
|
|
1666
|
-
value += 0.05;
|
|
1667
|
-
message = "⚔️ 警卫长职业:攻击伤害+5%";
|
|
1668
|
-
}
|
|
1669
|
-
if (careerData?.career === "武器中士") {
|
|
1670
|
-
value += 0.15;
|
|
1671
|
-
message = "⚔️ 武器中士职业:攻击伤害+15%";
|
|
1672
|
-
}
|
|
1673
|
-
if (careerData?.career === "能量武器专家") {
|
|
1674
|
-
if (weaponType === "能量武器") {
|
|
1675
|
-
value += 0.2;
|
|
1676
|
-
message = "⚔️ 能量武器专家职业:能量武器攻击伤害+20%";
|
|
1677
|
-
}
|
|
1678
|
-
}
|
|
1679
|
-
if (careerData?.career === "纵火狂") {
|
|
1680
|
-
if (weaponType === "热能武器") {
|
|
1681
|
-
value += 0.2;
|
|
1682
|
-
message = "⚔️ 纵火狂职业:热能武器攻击伤害+20%";
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
if (careerData?.career === "猩红杀手") {
|
|
1686
|
-
if (weaponId === 7) {
|
|
1687
|
-
value += 0.15;
|
|
1688
|
-
message = "⚔️ 猩红杀手职业:侦察步枪攻击伤害+15%";
|
|
1689
|
-
}
|
|
1690
|
-
}
|
|
1691
|
-
return { value, message };
|
|
1692
|
-
}
|
|
1693
|
-
__name(calculateCareerAdditive, "calculateCareerAdditive");
|
|
1694
|
-
async function calculateWishAdditive(ctx, handle, weapon) {
|
|
1695
|
-
let value = 0;
|
|
1696
|
-
const messages = [];
|
|
1697
|
-
const [sovereign] = await ctx.database.get("ggcevo_wish", {
|
|
1698
|
-
handle,
|
|
1699
|
-
wishname: "王权增幅",
|
|
1700
|
-
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
1701
|
-
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
1702
|
-
});
|
|
1703
|
-
if (sovereign) {
|
|
1704
|
-
value += 0.1;
|
|
1705
|
-
messages.push("👑 王权增幅祈愿:攻击伤害+10%");
|
|
1706
|
-
}
|
|
1707
|
-
const [lament] = await ctx.database.get("ggcevo_wish", {
|
|
1708
|
-
handle,
|
|
1709
|
-
wishname: "悲鸣之锋",
|
|
1710
|
-
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
1711
|
-
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
1712
|
-
});
|
|
1713
|
-
if (lament) {
|
|
1714
|
-
const levelBonus = 0.1 * (weapon.level + 1);
|
|
1715
|
-
value += levelBonus;
|
|
1716
|
-
messages.push(`🗡️ 悲鸣之锋祈愿:攻击伤害+${Math.round(levelBonus * 100)}%`);
|
|
1717
|
-
}
|
|
1718
|
-
const [critRhythm] = await ctx.database.get("ggcevo_wish", {
|
|
1719
|
-
handle,
|
|
1720
|
-
wishname: "暴击韵律",
|
|
1721
|
-
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
1722
|
-
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
1723
|
-
});
|
|
1724
|
-
if (critRhythm) {
|
|
1725
|
-
messages.push("🎵 暴击韵律祈愿:攻击暴击率+20%");
|
|
1726
|
-
}
|
|
1727
|
-
return {
|
|
1728
|
-
value,
|
|
1729
|
-
message: messages.join(",")
|
|
1730
|
-
};
|
|
1731
|
-
}
|
|
1732
|
-
__name(calculateWishAdditive, "calculateWishAdditive");
|
|
1733
|
-
function calculateRankAdditive(rankRecord) {
|
|
1734
|
-
if (!rankRecord || rankRecord.rank <= 0) return { value: 0, message: "" };
|
|
1735
|
-
const baseValue = Math.floor(rankRecord.rank / 300) * 0.01;
|
|
1736
|
-
const cappedValue = Math.min(baseValue, 1);
|
|
1737
|
-
if (cappedValue > 0) {
|
|
1738
|
-
const percentage = Math.round(cappedValue * 100);
|
|
1739
|
-
return {
|
|
1740
|
-
value: cappedValue,
|
|
1741
|
-
message: `🏆 胜点榜积分加成:攻击伤害+${percentage}%`
|
|
1742
|
-
};
|
|
1743
|
-
}
|
|
1744
|
-
return { value: 0, message: "" };
|
|
1745
|
-
}
|
|
1746
|
-
__name(calculateRankAdditive, "calculateRankAdditive");
|
|
1747
|
-
|
|
1748
|
-
// src/utils.ts
|
|
1749
|
-
async function gachaWithPity(ctx, handle) {
|
|
1750
|
-
const [record] = await ctx.database.get("ggcevo_records", { handle });
|
|
1751
|
-
const currentPity = record?.pityCounter ?? 0;
|
|
1752
|
-
if (currentPity >= 89) {
|
|
1753
|
-
await updatePityCounter(ctx, handle, true);
|
|
1754
|
-
await ctx.database.upsert("ggcevo_records", [{
|
|
1755
|
-
handle,
|
|
1756
|
-
fullPityCount: (record?.fullPityCount || 0) + 1
|
|
1757
|
-
}], ["handle"]);
|
|
1758
|
-
return true;
|
|
1759
|
-
}
|
|
1760
|
-
const isWin = simpleDraw();
|
|
1761
|
-
await updatePityCounter(ctx, handle, isWin);
|
|
1762
|
-
return isWin;
|
|
1763
|
-
}
|
|
1764
|
-
__name(gachaWithPity, "gachaWithPity");
|
|
1765
|
-
async function gachaWithHiddenAward(ctx, handle) {
|
|
1766
|
-
const backpackItems = await ctx.database.get("ggcevo_backpack", {
|
|
1767
|
-
handle,
|
|
1768
|
-
itemId: { $in: [2, 3] }
|
|
1769
|
-
});
|
|
1770
|
-
const itemMap = new Map(backpackItems.map((item) => [item.itemId, item]));
|
|
1771
|
-
const isWin = HiddenAward();
|
|
1772
|
-
if (isWin) {
|
|
1773
|
-
const updates = [
|
|
1774
|
-
{
|
|
1775
|
-
itemId: 2,
|
|
1776
|
-
addAmount: 1
|
|
1777
|
-
},
|
|
1778
|
-
{
|
|
1779
|
-
itemId: 3,
|
|
1780
|
-
addAmount: 1
|
|
1781
|
-
}
|
|
1782
|
-
].map(({ itemId, addAmount }) => ({
|
|
1783
|
-
handle,
|
|
1784
|
-
itemId,
|
|
1785
|
-
quantity: (itemMap.get(itemId)?.quantity || 0) + addAmount
|
|
1786
|
-
}));
|
|
1787
|
-
await ctx.database.upsert("ggcevo_backpack", updates, ["handle", "itemId"]);
|
|
1788
|
-
const [record] = await ctx.database.get("ggcevo_records", { handle });
|
|
1789
|
-
await ctx.database.upsert("ggcevo_records", [{
|
|
1790
|
-
handle,
|
|
1791
|
-
hiddenawards: (record?.hiddenawards || 0) + 1
|
|
1792
|
-
}], ["handle"]);
|
|
1793
|
-
}
|
|
1794
|
-
return isWin;
|
|
1795
|
-
}
|
|
1796
|
-
__name(gachaWithHiddenAward, "gachaWithHiddenAward");
|
|
1797
|
-
async function updatePityCounter(ctx, handle, isWin) {
|
|
1798
|
-
const [record] = await ctx.database.get("ggcevo_records", { handle });
|
|
1799
|
-
const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 2 });
|
|
1800
|
-
await ctx.database.upsert("ggcevo_records", [{
|
|
1801
|
-
handle,
|
|
1802
|
-
totalPulls: (record?.totalPulls || 0) + 1,
|
|
1803
|
-
pityCounter: isWin ? 0 : (record?.pityCounter || 0) + 1
|
|
1804
|
-
}], ["handle"]);
|
|
1805
|
-
if (isWin) {
|
|
1806
|
-
await ctx.database.upsert("ggcevo_backpack", [{
|
|
1807
|
-
handle,
|
|
1808
|
-
itemId: 2,
|
|
1809
|
-
quantity: (backpack?.quantity || 0) + 1
|
|
1810
|
-
}]);
|
|
1811
|
-
}
|
|
1812
|
-
}
|
|
1813
|
-
__name(updatePityCounter, "updatePityCounter");
|
|
1814
|
-
async function checkSensitiveWord(ctx, content) {
|
|
1815
|
-
try {
|
|
1816
|
-
const response = await ctx.http("get", `https://v.api.aa1.cn/api/api-mgc/index.php?msg=${encodeURIComponent(content)}`);
|
|
1817
|
-
return response.data.num !== "1";
|
|
1818
|
-
} catch (error) {
|
|
1819
|
-
console.error("敏感词查询失败:", error);
|
|
1820
|
-
return false;
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1823
|
-
__name(checkSensitiveWord, "checkSensitiveWord");
|
|
1824
|
-
function simpleDraw() {
|
|
1825
|
-
return Math.floor(Math.random() * 1e4) < 50;
|
|
1826
|
-
}
|
|
1827
|
-
__name(simpleDraw, "simpleDraw");
|
|
1828
|
-
function HiddenAward() {
|
|
1829
|
-
return Math.floor(Math.random() * 1e4) < 1;
|
|
1830
|
-
}
|
|
1831
|
-
__name(HiddenAward, "HiddenAward");
|
|
1832
|
-
function getRandomInt(min, max) {
|
|
1833
|
-
const actualMin = Math.min(min, max);
|
|
1834
|
-
const actualMax = Math.max(min, max);
|
|
1835
|
-
return Math.floor(Math.random() * (actualMax - actualMin + 1)) + actualMin;
|
|
1836
|
-
}
|
|
1837
|
-
__name(getRandomInt, "getRandomInt");
|
|
1838
|
-
function PetCapsuleToy() {
|
|
1839
|
-
const num = Math.floor(Math.random() * 1e4);
|
|
1840
|
-
if (num < 4e3) return "t3级宠物扭蛋";
|
|
1841
|
-
if (num < 7e3) return "t2级宠物扭蛋";
|
|
1842
|
-
if (num < 9e3) return "t1级宠物扭蛋";
|
|
1843
|
-
return "t0级宠物扭蛋";
|
|
1844
|
-
}
|
|
1845
|
-
__name(PetCapsuleToy, "PetCapsuleToy");
|
|
1846
|
-
function isSameDate(a, b) {
|
|
1847
|
-
return a.getUTCFullYear() === b.getUTCFullYear() && a.getUTCMonth() === b.getUTCMonth() && a.getUTCDate() === b.getUTCDate();
|
|
1848
|
-
}
|
|
1849
|
-
__name(isSameDate, "isSameDate");
|
|
1850
|
-
function isSameHalfDay(a, b) {
|
|
1851
|
-
if (!isSameDate(a, b)) {
|
|
1852
|
-
return false;
|
|
1853
|
-
}
|
|
1854
|
-
const hour1 = a.getUTCHours();
|
|
1855
|
-
const hour2 = b.getUTCHours();
|
|
1856
|
-
return hour1 < 12 && hour2 < 12 || hour1 >= 12 && hour2 >= 12;
|
|
1857
|
-
}
|
|
1858
|
-
__name(isSameHalfDay, "isSameHalfDay");
|
|
1859
|
-
function convertUTCtoChinaTime(input) {
|
|
1860
|
-
const utcDate = new Date(input);
|
|
1861
|
-
if (isNaN(utcDate.getTime())) {
|
|
1862
|
-
throw new Error("Invalid date input");
|
|
1863
|
-
}
|
|
1864
|
-
const chinaTimestamp = utcDate.getTime() + 8 * 60 * 60 * 1e3;
|
|
1865
|
-
return new Date(chinaTimestamp);
|
|
1866
|
-
}
|
|
1867
|
-
__name(convertUTCtoChinaTime, "convertUTCtoChinaTime");
|
|
1868
|
-
function formatDate(d) {
|
|
1869
|
-
return d.toLocaleString("zh-CN", {
|
|
1870
|
-
timeZone: "Asia/Shanghai",
|
|
1871
|
-
year: "numeric",
|
|
1872
|
-
month: "2-digit",
|
|
1873
|
-
day: "2-digit",
|
|
1874
|
-
hour: "2-digit",
|
|
1875
|
-
minute: "2-digit"
|
|
1876
|
-
});
|
|
1877
|
-
}
|
|
1878
|
-
__name(formatDate, "formatDate");
|
|
1879
|
-
function createHpBar(current, max) {
|
|
1880
|
-
const ratio = current / max;
|
|
1881
|
-
const filled = Math.floor(ratio * 20);
|
|
1882
|
-
return "▰".repeat(filled) + "▱".repeat(20 - filled);
|
|
1883
|
-
}
|
|
1884
|
-
__name(createHpBar, "createHpBar");
|
|
1885
|
-
async function activateNextBossGroup(ctx, currentBossId = null) {
|
|
1886
|
-
let availableIndices = [];
|
|
1887
|
-
bossPool.forEach((bossGroup, index) => {
|
|
1888
|
-
if (currentBossId === null || bossGroup.id !== currentBossId) {
|
|
1889
|
-
availableIndices.push(index);
|
|
1890
|
-
}
|
|
1891
|
-
});
|
|
1892
|
-
if (availableIndices.length === 0) {
|
|
1893
|
-
availableIndices = Array.from({ length: bossPool.length }, (_, i) => i);
|
|
1894
|
-
}
|
|
1895
|
-
const randomIndex = availableIndices[Math.floor(Math.random() * availableIndices.length)];
|
|
1896
|
-
const nextBossGroup = bossPool[randomIndex];
|
|
1897
|
-
const mainBoss = await ctx.database.create("ggcevo_boss", {
|
|
1898
|
-
name: nextBossGroup.main.name,
|
|
1899
|
-
type: nextBossGroup.main.type,
|
|
1900
|
-
HP: nextBossGroup.main.maxHP,
|
|
1901
|
-
tags: nextBossGroup.main.tags,
|
|
1902
|
-
// 新增标签字段
|
|
1903
|
-
skills: [...nextBossGroup.main.passive],
|
|
1904
|
-
energy: nextBossGroup.main.maxEnergy,
|
|
1905
|
-
groupId: nextBossGroup.id,
|
|
1906
|
-
isActive: true,
|
|
1907
|
-
respawnTime: /* @__PURE__ */ new Date()
|
|
1908
|
-
});
|
|
1909
|
-
for (const minion of nextBossGroup.minions) {
|
|
1910
|
-
await ctx.database.create("ggcevo_boss", {
|
|
1911
|
-
name: minion.name,
|
|
1912
|
-
type: minion.type,
|
|
1913
|
-
HP: minion.maxHP,
|
|
1914
|
-
tags: minion.tags,
|
|
1915
|
-
// 新增标签字段
|
|
1916
|
-
skills: [...minion.passive],
|
|
1917
|
-
energy: minion.maxEnergy,
|
|
1918
|
-
groupId: nextBossGroup.id,
|
|
1919
|
-
isActive: true,
|
|
1920
|
-
respawnTime: /* @__PURE__ */ new Date()
|
|
1921
|
-
});
|
|
1922
|
-
}
|
|
1923
|
-
return mainBoss;
|
|
1924
|
-
}
|
|
1925
|
-
__name(activateNextBossGroup, "activateNextBossGroup");
|
|
1926
|
-
var weaponConfigById = {};
|
|
1927
|
-
for (const key in weaponConfig) {
|
|
1928
|
-
weaponConfigById[weaponConfig[key].id] = weaponConfig[key];
|
|
1929
|
-
}
|
|
1930
|
-
async function calculateTotalPower(ctx, config, handle) {
|
|
1931
|
-
const [rankData] = await ctx.database.get("ggcevo_rank", {
|
|
1932
|
-
handle,
|
|
1933
|
-
rankseason: config.rankseason
|
|
1934
|
-
});
|
|
1935
|
-
const baseRank = rankData?.rank || 0;
|
|
1936
|
-
let total = baseRank;
|
|
1937
|
-
const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
|
|
1938
|
-
const career = careerData?.career;
|
|
1939
|
-
if (career) {
|
|
1940
|
-
if (career === "联盟新兵") total += 1e3;
|
|
1941
|
-
else if (career === "辛迪加炮灰新兵") total += 2e3;
|
|
1942
|
-
else if (["深空矿工", "医疗专家", "情报副官", "总工程师", "舰长", "机械化专家"].includes(career)) total += 2500;
|
|
1943
|
-
else if (["清洁工", "辛迪加财务经理", "计算机专家", "指挥官", "装甲兵", "破坏者", "征募官"].includes(career)) total += 3e3;
|
|
1944
|
-
else if (["警卫员下士", "警卫长", "武器中士"].includes(career)) total += 3500;
|
|
1945
|
-
else if (["能量武器专家", "枪手", "猩红杀手", "纵火狂"].includes(career)) total += 4e3;
|
|
1946
|
-
}
|
|
1947
|
-
const weapons = await ctx.database.get("ggcevo_weapons", { handle });
|
|
1948
|
-
for (const { weaponId, level, installedMods } of weapons) {
|
|
1949
|
-
const weapon = weaponConfigById[weaponId];
|
|
1950
|
-
if (!weapon) continue;
|
|
1951
|
-
total += weapon.damage * 100;
|
|
1952
|
-
total += level * (level + 1) / 2 * 1e3;
|
|
1953
|
-
for (const modName of installedMods || []) {
|
|
1954
|
-
const mod = modConfig[modName];
|
|
1955
|
-
if (mod) {
|
|
1956
|
-
if (mod.isExclusive) {
|
|
1957
|
-
total += 4e3;
|
|
1958
|
-
} else {
|
|
1959
|
-
total += 2e3;
|
|
1960
|
-
}
|
|
1961
|
-
}
|
|
1962
|
-
}
|
|
1963
|
-
}
|
|
1964
|
-
return total;
|
|
1965
|
-
}
|
|
1966
|
-
__name(calculateTotalPower, "calculateTotalPower");
|
|
1967
|
-
async function applyItemEffect(ctx, session, handle, itemConfig2, target) {
|
|
1968
|
-
try {
|
|
1969
|
-
const itemName = Object.entries(SyndicatedItems).find(
|
|
1970
|
-
([_, item]) => item.id === itemConfig2.id
|
|
1971
|
-
)?.[0] || "未知物品";
|
|
1972
|
-
if (itemConfig2.id === 1) {
|
|
1973
|
-
const activeSentry = await ctx.database.get("ggcevo_boss", {
|
|
1974
|
-
name: "空间站哨枪塔",
|
|
1975
|
-
isActive: true
|
|
1976
|
-
});
|
|
1977
|
-
if (!activeSentry.length) return {
|
|
1978
|
-
success: false,
|
|
1979
|
-
message: "⚠️ 目标「空间站哨枪塔」未存活"
|
|
1980
|
-
};
|
|
1981
|
-
const [SentryTower] = await ctx.database.get("ggcevo_boss", {
|
|
1982
|
-
name: "空间站哨枪塔",
|
|
1983
|
-
isActive: true
|
|
1984
|
-
});
|
|
1985
|
-
const damageValue = SentryTower.HP;
|
|
1986
|
-
await ctx.database.set(
|
|
1987
|
-
"ggcevo_boss",
|
|
1988
|
-
{ name: "空间站哨枪塔" },
|
|
1989
|
-
{ isActive: false, HP: 0 }
|
|
1990
|
-
);
|
|
1991
|
-
await ctx.database.withTransaction(async () => {
|
|
1992
|
-
const signRecords = await ctx.database.get("ggcevo_sign", { handle });
|
|
1993
|
-
await ctx.database.upsert("ggcevo_sign", [{
|
|
1994
|
-
handle,
|
|
1995
|
-
totalRewards: (signRecords[0]?.totalRewards || 0) + damageValue
|
|
1996
|
-
}], ["handle"]);
|
|
1997
|
-
const [damageRecords] = await ctx.database.get("ggcevo_boss_damage", { handle });
|
|
1998
|
-
await ctx.database.upsert("ggcevo_boss_damage", [{
|
|
1999
|
-
handle,
|
|
2000
|
-
playerName: session.username,
|
|
2001
|
-
totalDamage: (damageRecords?.totalDamage || 0) + damageValue,
|
|
2002
|
-
attackCount: damageRecords?.attackCount || 0,
|
|
2003
|
-
bossGroupId: 4
|
|
2004
|
-
}], ["handle"]);
|
|
2005
|
-
});
|
|
2006
|
-
return {
|
|
2007
|
-
success: true,
|
|
2008
|
-
message: `成功引爆${itemName},对空间站哨枪塔造成${damageValue}点伤害,获得等额金币。`
|
|
2009
|
-
};
|
|
2010
|
-
}
|
|
2011
|
-
if (itemConfig2.id === 2) {
|
|
2012
|
-
if (!target) return {
|
|
2013
|
-
success: false,
|
|
2014
|
-
message: "您未选择合适的目标。"
|
|
2015
|
-
};
|
|
2016
|
-
const [targetboss] = await ctx.database.get("ggcevo_boss", {
|
|
2017
|
-
name: target,
|
|
2018
|
-
isActive: true
|
|
2019
|
-
});
|
|
2020
|
-
if (!targetboss) return {
|
|
2021
|
-
success: false,
|
|
2022
|
-
message: "无法找到指定的目标。"
|
|
2023
|
-
};
|
|
2024
|
-
if (targetboss.tags.includes("建筑") || targetboss.tags.includes("重型")) {
|
|
2025
|
-
return {
|
|
2026
|
-
success: false,
|
|
2027
|
-
message: `目标${target}拥有"${targetboss.tags.includes("建筑") ? "建筑" : "重型"}"标签,无法使用此物品。`
|
|
2028
|
-
};
|
|
2029
|
-
}
|
|
2030
|
-
const currentCount = targetboss?.skillStacks || 0;
|
|
2031
|
-
if (currentCount <= 0) {
|
|
2032
|
-
return {
|
|
2033
|
-
success: false,
|
|
2034
|
-
message: `目标${target}的技能层数已为0,无需使用此物品。`
|
|
2035
|
-
};
|
|
2036
|
-
}
|
|
2037
|
-
const newCount = Math.max(0, currentCount - 10);
|
|
2038
|
-
const reducedAmount = currentCount - newCount;
|
|
2039
|
-
await ctx.database.set(
|
|
2040
|
-
"ggcevo_boss",
|
|
2041
|
-
{ name: target },
|
|
2042
|
-
{ skillStacks: newCount }
|
|
2043
|
-
);
|
|
2044
|
-
return {
|
|
2045
|
-
success: true,
|
|
2046
|
-
message: `成功使用${itemName},使${target}的技能层数减少10层`
|
|
2047
|
-
};
|
|
2048
|
-
}
|
|
2049
|
-
if (itemConfig2.id === 4) {
|
|
2050
|
-
if (!target) return {
|
|
2051
|
-
success: false,
|
|
2052
|
-
message: "您未选择合适的目标。"
|
|
2053
|
-
};
|
|
2054
|
-
const [targetboss] = await ctx.database.get("ggcevo_boss", {
|
|
2055
|
-
name: target,
|
|
2056
|
-
isActive: true
|
|
2057
|
-
});
|
|
2058
|
-
if (!targetboss || targetboss?.energy === 0) return {
|
|
2059
|
-
success: false,
|
|
2060
|
-
message: "您无法对没有能量的目标使用。"
|
|
2061
|
-
};
|
|
2062
|
-
await ctx.database.set(
|
|
2063
|
-
"ggcevo_boss",
|
|
2064
|
-
{ name: target },
|
|
2065
|
-
{ energy: Math.max(targetboss.energy - 500, 0) }
|
|
2066
|
-
// 确保不低于0
|
|
2067
|
-
);
|
|
2068
|
-
return {
|
|
2069
|
-
success: true,
|
|
2070
|
-
message: `成功使用${itemName},消耗${target}500点能量`
|
|
2071
|
-
};
|
|
2072
|
-
}
|
|
2073
|
-
return {
|
|
2074
|
-
success: false,
|
|
2075
|
-
message: `${itemName} 无法使用。`
|
|
2076
|
-
};
|
|
2077
|
-
} catch (error) {
|
|
2078
|
-
console.error("物品效果处理失败:", error);
|
|
2079
|
-
return {
|
|
2080
|
-
success: false,
|
|
2081
|
-
message: "⚠️ 物品效果处理异常,已回滚操作。"
|
|
2082
|
-
};
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
__name(applyItemEffect, "applyItemEffect");
|
|
2086
|
-
async function handleTechUpgrade(ctx, handle, target) {
|
|
2087
|
-
const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
|
|
2088
|
-
if (!careerData || careerData.group !== "人类联盟") {
|
|
2089
|
-
return "🚫 该功能需要【人类联盟】阵营权限";
|
|
2090
|
-
}
|
|
2091
|
-
const tech = Spacestationtechnology.find(
|
|
2092
|
-
(t) => t.techname === target
|
|
2093
|
-
);
|
|
2094
|
-
const [techEntry] = await ctx.database.get("ggcevo_tech", { handle, techId: tech.techId });
|
|
2095
|
-
const currentLevel = techEntry?.level || 0;
|
|
2096
|
-
if (currentLevel >= tech.maxLevel) return `❌ ${tech.techname}已达最高等级`;
|
|
2097
|
-
const nextLevel = currentLevel + 1;
|
|
2098
|
-
const levelData = tech.levels.find((l) => l.level === nextLevel);
|
|
2099
|
-
let originalCost = levelData.cost;
|
|
2100
|
-
let actualCost = originalCost;
|
|
2101
|
-
let discountApplied = false;
|
|
2102
|
-
let discountDetails = [];
|
|
2103
|
-
if (careerData.career === "情报副官") {
|
|
2104
|
-
discountApplied = true;
|
|
2105
|
-
actualCost = Math.floor(originalCost * 0.9);
|
|
2106
|
-
discountDetails.push("🎖️ 情报副官职业:10%折扣");
|
|
2107
|
-
}
|
|
2108
|
-
const [signInfo] = await ctx.database.get("ggcevo_sign", { handle });
|
|
2109
|
-
if (signInfo?.totalRewards < actualCost) {
|
|
2110
|
-
const priceHint = discountApplied ? ` (原价${originalCost}金币)` : "";
|
|
2111
|
-
return `❌ 金币不足!需要${actualCost}金币${priceHint},您当前拥有:${signInfo?.totalRewards || 0}金币`;
|
|
2112
|
-
}
|
|
2113
|
-
let permissionGrantInfo = null;
|
|
2114
|
-
if (tech.techname === "武器系统" && currentLevel === 4 && nextLevel === 5) {
|
|
2115
|
-
permissionGrantInfo = {
|
|
2116
|
-
type: "武器系统",
|
|
2117
|
-
field: "legendarypermissions",
|
|
2118
|
-
amount: 1,
|
|
2119
|
-
message: "🎉 解锁传奇武器购买权限1次!"
|
|
2120
|
-
};
|
|
2121
|
-
}
|
|
2122
|
-
if (tech.techname === "安防系统" && currentLevel === 4 && nextLevel === 5) {
|
|
2123
|
-
permissionGrantInfo = {
|
|
2124
|
-
type: "安防系统",
|
|
2125
|
-
field: "explosiondoorauthority",
|
|
2126
|
-
amount: 1,
|
|
2127
|
-
message: "🔓 解锁安全军械库防爆门权限1次!"
|
|
2128
|
-
};
|
|
2129
|
-
}
|
|
2130
|
-
await ctx.database.withTransaction(async () => {
|
|
2131
|
-
await ctx.database.set("ggcevo_sign", { handle }, {
|
|
2132
|
-
totalRewards: signInfo.totalRewards - actualCost
|
|
2133
|
-
});
|
|
2134
|
-
await ctx.database.upsert("ggcevo_tech", [{
|
|
2135
|
-
handle,
|
|
2136
|
-
techId: tech.techId,
|
|
2137
|
-
level: nextLevel
|
|
2138
|
-
}], ["handle", "techId"]);
|
|
2139
|
-
if (permissionGrantInfo) {
|
|
2140
|
-
const [permissionRecord] = await ctx.database.get("ggcevo_permissions", { handle });
|
|
2141
|
-
const currentValue = permissionRecord?.[permissionGrantInfo.field] || 0;
|
|
2142
|
-
await ctx.database.upsert("ggcevo_permissions", [{
|
|
2143
|
-
handle,
|
|
2144
|
-
[permissionGrantInfo.field]: currentValue + permissionGrantInfo.amount
|
|
2145
|
-
}], ["handle"]);
|
|
2146
|
-
}
|
|
2147
|
-
});
|
|
2148
|
-
let discountInfo = [];
|
|
2149
|
-
if (discountApplied) {
|
|
2150
|
-
discountInfo = [
|
|
2151
|
-
"💰 折扣明细:",
|
|
2152
|
-
...discountDetails.map((detail) => `▸ ${detail}`)
|
|
2153
|
-
];
|
|
2154
|
-
}
|
|
2155
|
-
const costInfo = discountApplied ? `💸 花费金币:${actualCost} (原价${originalCost})` : `💸 花费金币:${actualCost}`;
|
|
2156
|
-
let permissionMessage = [];
|
|
2157
|
-
if (permissionGrantInfo) {
|
|
2158
|
-
const [permissionRecord] = await ctx.database.get("ggcevo_permissions", { handle });
|
|
2159
|
-
const newValue = permissionRecord?.[permissionGrantInfo.field] || permissionGrantInfo.amount;
|
|
2160
|
-
permissionMessage.push(
|
|
2161
|
-
permissionGrantInfo.message
|
|
2162
|
-
);
|
|
2163
|
-
}
|
|
2164
|
-
return [
|
|
2165
|
-
`✅ ${tech.techname} 升级至 Lv.${nextLevel}`,
|
|
2166
|
-
costInfo,
|
|
2167
|
-
...discountInfo,
|
|
2168
|
-
// 折扣信息
|
|
2169
|
-
`📝 基础效果:${levelData.description}`,
|
|
2170
|
-
`💼 职业效果:${levelData.careerBonus}`,
|
|
2171
|
-
...permissionMessage
|
|
2172
|
-
// 权限解锁信息
|
|
2173
|
-
].filter(Boolean).join("\n");
|
|
2174
|
-
}
|
|
2175
|
-
__name(handleTechUpgrade, "handleTechUpgrade");
|
|
2176
|
-
async function handleWeaponUpgrade(ctx, handle, target) {
|
|
2177
|
-
const weaponData = weaponConfig[target];
|
|
2178
|
-
const [equipment] = await ctx.database.get("ggcevo_weapons", {
|
|
2179
|
-
handle,
|
|
2180
|
-
weaponId: weaponData.id
|
|
2181
|
-
});
|
|
2182
|
-
const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
|
|
2183
|
-
if (!equipment) return "❌ 您尚未获得该武器";
|
|
2184
|
-
const maxLevel = careerData?.career === "枪手" ? 7 : 6;
|
|
2185
|
-
if (equipment.level >= maxLevel) return `❌ 该武器已达最高等级(Lv.${maxLevel})`;
|
|
2186
|
-
const BASE_COST = [1050, 1450, 1850, 2250, 2650, 3050, 3450];
|
|
2187
|
-
const baseCost = BASE_COST[equipment.level];
|
|
2188
|
-
const weaponTechConfig = Spacestationtechnology.find((t) => t.techId === 2);
|
|
2189
|
-
let techLevel = 0;
|
|
2190
|
-
let totalDiscount = 0;
|
|
2191
|
-
const discountDetails = [];
|
|
2192
|
-
const isGunslinger = careerData?.career === "枪手";
|
|
2193
|
-
if (isGunslinger) {
|
|
2194
|
-
totalDiscount += 10;
|
|
2195
|
-
discountDetails.push("🔫 枪手职业:10%折扣");
|
|
2196
|
-
}
|
|
2197
|
-
if (careerData?.group === "人类联盟") {
|
|
2198
|
-
const [weaponTech] = await ctx.database.get("ggcevo_tech", { handle, techId: 2 }).catch(() => [{ level: 0 }]);
|
|
2199
|
-
techLevel = Math.min(Math.max(weaponTech?.level || 0, 0), 5);
|
|
2200
|
-
const isCareerMatch = weaponTechConfig?.careerNames.includes(careerData?.career);
|
|
2201
|
-
const BASE_DISCOUNTS = [5, 10, 15, 20, 25];
|
|
2202
|
-
const CAREER_DISCOUNTS = [10, 20, 30, 40, 50];
|
|
2203
|
-
const baseDiscount = techLevel > 0 ? BASE_DISCOUNTS[techLevel - 1] : 0;
|
|
2204
|
-
const careerDiscount = isCareerMatch && techLevel > 0 ? CAREER_DISCOUNTS[techLevel - 1] : 0;
|
|
2205
|
-
const weaponDiscount = Math.max(baseDiscount, careerDiscount);
|
|
2206
|
-
if (weaponDiscount > 0) {
|
|
2207
|
-
totalDiscount += weaponDiscount;
|
|
2208
|
-
discountDetails.push(
|
|
2209
|
-
`⚙️ 武器系统Lv.${techLevel}:${weaponDiscount}%折扣`
|
|
2210
|
-
);
|
|
2211
|
-
}
|
|
2212
|
-
}
|
|
2213
|
-
const activeWish = await checkFoxBlessing(ctx, handle);
|
|
2214
|
-
if (activeWish) {
|
|
2215
|
-
totalDiscount += 20;
|
|
2216
|
-
discountDetails.push("🦊 灵狐升运祈愿:20%折扣");
|
|
2217
|
-
}
|
|
2218
|
-
totalDiscount = Math.min(totalDiscount, 100);
|
|
2219
|
-
const discountedCost = baseCost * (100 - totalDiscount) / 100;
|
|
2220
|
-
const actualCost = Math.floor(discountedCost);
|
|
2221
|
-
const [signInfo] = await ctx.database.get("ggcevo_sign", { handle });
|
|
2222
|
-
if (signInfo?.totalRewards < actualCost) {
|
|
2223
|
-
const priceInfo2 = totalDiscount > 0 ? `需要${actualCost}金币(原价${baseCost}金币)` : `需要${actualCost}金币`;
|
|
2224
|
-
return `❌ ${priceInfo2},您当前拥有:${signInfo?.totalRewards || 0}金币`;
|
|
2225
|
-
}
|
|
2226
|
-
const newLevel = equipment.level + 1;
|
|
2227
|
-
const newModSlots = Math.floor(newLevel / 3) + 1;
|
|
2228
|
-
await ctx.database.withTransaction(async () => {
|
|
2229
|
-
await ctx.database.set("ggcevo_sign", { handle }, {
|
|
2230
|
-
totalRewards: signInfo.totalRewards - actualCost
|
|
2231
|
-
});
|
|
2232
|
-
await ctx.database.set(
|
|
2233
|
-
"ggcevo_weapons",
|
|
2234
|
-
{ handle, weaponId: weaponData.id },
|
|
2235
|
-
{
|
|
2236
|
-
level: newLevel,
|
|
2237
|
-
modificationSlots: newModSlots
|
|
2238
|
-
}
|
|
2239
|
-
);
|
|
2240
|
-
if (activeWish) {
|
|
2241
|
-
await ctx.database.set(
|
|
2242
|
-
"ggcevo_wish",
|
|
2243
|
-
{ id: activeWish.id },
|
|
2244
|
-
{ isused: true }
|
|
2245
|
-
);
|
|
2246
|
-
}
|
|
2247
|
-
});
|
|
2248
|
-
const damage = (weaponData.damage * (1 + 0.1 * newLevel)).toFixed(1);
|
|
2249
|
-
let msg = `${target} 升级成功!Lv.${newLevel}`;
|
|
2250
|
-
const priceInfo = totalDiscount > 0 ? `
|
|
2251
|
-
💸 花费:${actualCost}金币 (原价${baseCost}金币)` : `
|
|
2252
|
-
💸 花费:${actualCost}金币`;
|
|
2253
|
-
msg += priceInfo;
|
|
2254
|
-
if (discountDetails.length > 0) {
|
|
2255
|
-
msg += `
|
|
2256
|
-
💰 折扣明细:
|
|
2257
|
-
▸ ${discountDetails.join("\n▸ ")}`;
|
|
2258
|
-
}
|
|
2259
|
-
msg += `
|
|
2260
|
-
💥 伤害:${damage}`;
|
|
2261
|
-
msg += `
|
|
2262
|
-
🔧 改装槽:${newModSlots}个`;
|
|
2263
|
-
return msg;
|
|
2264
|
-
}
|
|
2265
|
-
__name(handleWeaponUpgrade, "handleWeaponUpgrade");
|
|
2266
|
-
async function checkFoxBlessing(ctx, handle) {
|
|
2267
|
-
return ctx.database.get("ggcevo_wish", {
|
|
2268
|
-
handle,
|
|
2269
|
-
wishname: "灵狐升运",
|
|
2270
|
-
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
2271
|
-
endTime: { $gte: /* @__PURE__ */ new Date() },
|
|
2272
|
-
isused: false
|
|
2273
|
-
}).then((records) => records[0]);
|
|
2274
|
-
}
|
|
2275
|
-
__name(checkFoxBlessing, "checkFoxBlessing");
|
|
2276
|
-
async function generateUpgradePriceList(ctx, handle) {
|
|
2277
|
-
const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
|
|
2278
|
-
const isGunslinger = careerData?.career === "枪手";
|
|
2279
|
-
const isAlliance = careerData?.group === "人类联盟";
|
|
2280
|
-
let techLevel = 0;
|
|
2281
|
-
let techDiscountRate = 0;
|
|
2282
|
-
let hasTechDiscount = false;
|
|
2283
|
-
if (isAlliance) {
|
|
2284
|
-
const [techData] = await ctx.database.get("ggcevo_tech", { handle, techId: 2 }).catch(() => [{ level: 0 }]);
|
|
2285
|
-
const weaponTechConfig = Spacestationtechnology.find((t) => t.techId === 2);
|
|
2286
|
-
techLevel = Math.min(techData?.level || 0, 5);
|
|
2287
|
-
const isCareerMatch = weaponTechConfig?.careerNames.includes(careerData?.career);
|
|
2288
|
-
const BASE_DISCOUNTS = [5, 10, 15, 20, 25];
|
|
2289
|
-
const CAREER_DISCOUNTS = [10, 20, 30, 40, 50];
|
|
2290
|
-
const baseDiscount = techLevel > 0 ? BASE_DISCOUNTS[techLevel - 1] : 0;
|
|
2291
|
-
const careerDiscount = isCareerMatch ? CAREER_DISCOUNTS[techLevel - 1] : 0;
|
|
2292
|
-
techDiscountRate = Math.max(baseDiscount, careerDiscount);
|
|
2293
|
-
hasTechDiscount = techDiscountRate > 0;
|
|
2294
|
-
}
|
|
2295
|
-
const foxBlessing = await checkFoxBlessing(ctx, handle);
|
|
2296
|
-
const foxDiscount = foxBlessing ? 20 : 0;
|
|
2297
|
-
const hasFoxDiscount = foxDiscount > 0;
|
|
2298
|
-
const gunslingerDiscount = isGunslinger ? 10 : 0;
|
|
2299
|
-
const hasGunslingerDiscount = isGunslinger;
|
|
2300
|
-
const BASE_COST = [1050, 1450, 1850, 2250, 2650, 3050, 3450];
|
|
2301
|
-
const maxLevel = isGunslinger ? 7 : 6;
|
|
2302
|
-
const priceDetails = [];
|
|
2303
|
-
for (let i = 0; i < maxLevel; i++) {
|
|
2304
|
-
const level = `${i}→${i + 1}`;
|
|
2305
|
-
let baseCost = BASE_COST[i];
|
|
2306
|
-
let finalPrice = baseCost;
|
|
2307
|
-
let discountsApplied = [];
|
|
2308
|
-
let totalDiscount = 0;
|
|
2309
|
-
if (isGunslinger) {
|
|
2310
|
-
totalDiscount += gunslingerDiscount;
|
|
2311
|
-
discountsApplied.push(`${gunslingerDiscount}% (枪手)`);
|
|
2312
|
-
}
|
|
2313
|
-
if (isAlliance && hasTechDiscount) {
|
|
2314
|
-
totalDiscount += techDiscountRate;
|
|
2315
|
-
discountsApplied.push(`${techDiscountRate}% (科技)`);
|
|
2316
|
-
}
|
|
2317
|
-
if (hasFoxDiscount) {
|
|
2318
|
-
totalDiscount += foxDiscount;
|
|
2319
|
-
discountsApplied.push(`${foxDiscount}% (灵狐)`);
|
|
2320
|
-
}
|
|
2321
|
-
if (totalDiscount > 0) {
|
|
2322
|
-
totalDiscount = Math.min(totalDiscount, 100);
|
|
2323
|
-
finalPrice = Math.floor(baseCost * (100 - totalDiscount) / 100);
|
|
2324
|
-
}
|
|
2325
|
-
const showOriginal = finalPrice < baseCost;
|
|
2326
|
-
const levelInfo = `等级 ${level.padEnd(5)}`;
|
|
2327
|
-
const priceInfo = `▸ 价格: ${finalPrice.toString().padStart(4)}${showOriginal ? ` (原价${baseCost})` : ""}`;
|
|
2328
|
-
let discountDetail = "";
|
|
2329
|
-
if (discountsApplied.length > 0) {
|
|
2330
|
-
discountDetail = ` - 折扣总计: ${totalDiscount}% [${discountsApplied.join(", ")}]`;
|
|
2331
|
-
}
|
|
2332
|
-
priceDetails.push(`${levelInfo}
|
|
2333
|
-
${priceInfo}`);
|
|
2334
|
-
}
|
|
2335
|
-
const discountNotice = [];
|
|
2336
|
-
if (hasTechDiscount || hasFoxDiscount || hasGunslingerDiscount) {
|
|
2337
|
-
discountNotice.push("💰 当前折扣:");
|
|
2338
|
-
}
|
|
2339
|
-
if (isGunslinger) {
|
|
2340
|
-
discountNotice.push(`▸ 🔫 枪手职业:10%折扣`);
|
|
2341
|
-
}
|
|
2342
|
-
if (isAlliance && hasTechDiscount) {
|
|
2343
|
-
discountNotice.push(`▸ ⚙️ 武器系统Lv.${techLevel}:${techDiscountRate}%折扣`);
|
|
2344
|
-
}
|
|
2345
|
-
if (hasFoxDiscount) {
|
|
2346
|
-
discountNotice.push(`▸ 🦊 灵狐升运祈愿:20%折扣`);
|
|
2347
|
-
}
|
|
2348
|
-
if (!hasTechDiscount && !hasFoxDiscount && !hasGunslingerDiscount) {
|
|
2349
|
-
if (isAlliance) {
|
|
2350
|
-
discountNotice.push("💡 提示:升级武器系统科技可获得折扣");
|
|
2351
|
-
} else if (careerData?.group === "辛迪加海盗") {
|
|
2352
|
-
discountNotice.push("💡 提示:转职为枪手职业可获得折扣");
|
|
2353
|
-
} else {
|
|
2354
|
-
discountNotice.push("💡 提示:加入人类联盟或辛迪加海盗可获得折扣");
|
|
2355
|
-
}
|
|
2356
|
-
}
|
|
2357
|
-
if (isGunslinger) {
|
|
2358
|
-
discountNotice.push("▸ 🔝 枪手职业:武器等级上限提升至7级");
|
|
2359
|
-
}
|
|
2360
|
-
return [
|
|
2361
|
-
"⚡ 武器升级价格表 ⚡",
|
|
2362
|
-
`武器等级上限: ${maxLevel}级${isGunslinger ? " (枪手职业)" : ""}`,
|
|
2363
|
-
"使用「升级 武器名称」对武器进行等级升级",
|
|
2364
|
-
...discountNotice,
|
|
2365
|
-
"====================",
|
|
2366
|
-
...priceDetails,
|
|
2367
|
-
"===================="
|
|
2368
|
-
].join("\n");
|
|
2369
|
-
}
|
|
2370
|
-
__name(generateUpgradePriceList, "generateUpgradePriceList");
|
|
2371
|
-
async function getRankInfo(ctx, config, handle) {
|
|
2372
|
-
const [user] = await ctx.database.get("ggcevo_rank", {
|
|
2373
|
-
handle,
|
|
2374
|
-
rankseason: config.rankseason
|
|
2375
|
-
});
|
|
2376
|
-
if (!user) return "暂未找到排名信息。";
|
|
2377
|
-
if (user.Blacklist) return "❌ 该用户已被禁止参加本赛季胜点榜。";
|
|
2378
|
-
const allRanks = await ctx.database.select("ggcevo_rank").where({ Blacklist: false, rankseason: config.rankseason }).orderBy("rank", "desc").execute();
|
|
2379
|
-
const userRank = allRanks.findIndex((u) => u.handle === handle) + 1;
|
|
2380
|
-
const isSafe = await checkSensitiveWord(ctx, user.name);
|
|
2381
|
-
const displayName = isSafe ? user.name : (user.name[0] || "") + "***";
|
|
2382
|
-
return `🎮 咕咕排名信息 🎮
|
|
2383
|
-
------------------------------
|
|
2384
|
-
昵称:${displayName}
|
|
2385
|
-
句柄:${user.handle}
|
|
2386
|
-
当前积分:${user.rank}
|
|
2387
|
-
参赛次数:${user.matches} 次
|
|
2388
|
-
胜率:${user.matches === 0 ? "0.00%" : (user.wins / user.matches * 100).toFixed(2) + "%"}
|
|
2389
|
-
全服排名:第 ${userRank} 名
|
|
2390
|
-
------------------------------`;
|
|
2391
|
-
}
|
|
2392
|
-
__name(getRankInfo, "getRankInfo");
|
|
2393
|
-
function isWithinProtection(protections) {
|
|
2394
|
-
const now = /* @__PURE__ */ new Date();
|
|
2395
|
-
return protections.some(
|
|
2396
|
-
(p) => p.status === "active" && now >= p.startTime && now <= p.endTime
|
|
2397
|
-
);
|
|
2398
|
-
}
|
|
2399
|
-
__name(isWithinProtection, "isWithinProtection");
|
|
2400
|
-
function formatTime(date) {
|
|
2401
|
-
return date.toLocaleString("zh-CN", {
|
|
2402
|
-
year: "numeric",
|
|
2403
|
-
month: "2-digit",
|
|
2404
|
-
day: "2-digit"
|
|
2405
|
-
});
|
|
2406
|
-
}
|
|
2407
|
-
__name(formatTime, "formatTime");
|
|
2408
|
-
|
|
2409
1273
|
// src/boss/BattleEffectProcessor.ts
|
|
2410
1274
|
var battleStatsMap = {};
|
|
2411
1275
|
function updateStatsByName(name2, updates) {
|
|
@@ -2445,6 +1309,9 @@ function updateStatsByName(name2, updates) {
|
|
|
2445
1309
|
}
|
|
2446
1310
|
__name(updateStatsByName, "updateStatsByName");
|
|
2447
1311
|
function getMaxHPByName(bossName) {
|
|
1312
|
+
if (bossName === "测试假人") {
|
|
1313
|
+
return 1e6;
|
|
1314
|
+
}
|
|
2448
1315
|
for (const boss of bossPool) {
|
|
2449
1316
|
if (boss.main.name === bossName) {
|
|
2450
1317
|
return boss.main.maxHP;
|
|
@@ -2459,6 +1326,9 @@ function getMaxHPByName(bossName) {
|
|
|
2459
1326
|
}
|
|
2460
1327
|
__name(getMaxHPByName, "getMaxHPByName");
|
|
2461
1328
|
function getMaxEnergyByName(bossName) {
|
|
1329
|
+
if (bossName === "测试假人") {
|
|
1330
|
+
return 1e3;
|
|
1331
|
+
}
|
|
2462
1332
|
for (const boss of bossPool) {
|
|
2463
1333
|
if (boss.main.name === bossName) {
|
|
2464
1334
|
return boss.main.maxEnergy;
|
|
@@ -2499,7 +1369,7 @@ var BattleEffectProcessor = {
|
|
|
2499
1369
|
}, "handleAlienShell"),
|
|
2500
1370
|
// 孤立无援处理(活跃Boss中仅自己时增伤20%)
|
|
2501
1371
|
handleIsolated: /* @__PURE__ */ __name(function(targetBoss, activeBosses, tempMark) {
|
|
2502
|
-
if (tempMark) {
|
|
1372
|
+
if (tempMark || targetBoss.name === "测试假人") {
|
|
2503
1373
|
return null;
|
|
2504
1374
|
}
|
|
2505
1375
|
const isIsolated = activeBosses.length === 1 && // 活跃Boss仅1个
|
|
@@ -2516,13 +1386,13 @@ var BattleEffectProcessor = {
|
|
|
2516
1386
|
}
|
|
2517
1387
|
return null;
|
|
2518
1388
|
}, "handleIsolated"),
|
|
2519
|
-
handleFrostRegeneration: /* @__PURE__ */ __name(function(targetBoss, activeBosses) {
|
|
1389
|
+
handleFrostRegeneration: /* @__PURE__ */ __name(function(targetBoss, activeBosses, maxStatsMap) {
|
|
2520
1390
|
const messages = [];
|
|
2521
1391
|
const otherUpdates = [];
|
|
2522
1392
|
if (!targetBoss.skills.includes("冰霜回复")) {
|
|
2523
1393
|
return null;
|
|
2524
1394
|
}
|
|
2525
|
-
const targetMaxHP =
|
|
1395
|
+
const targetMaxHP = maxStatsMap[targetBoss.name].maxHP;
|
|
2526
1396
|
const currentHP = targetBoss.HP;
|
|
2527
1397
|
if (currentHP > targetMaxHP * 0.3) {
|
|
2528
1398
|
return null;
|
|
@@ -2540,7 +1410,7 @@ var BattleEffectProcessor = {
|
|
|
2540
1410
|
);
|
|
2541
1411
|
otherSurvivingBosses.forEach((otherBoss) => {
|
|
2542
1412
|
const otherName = otherBoss.name;
|
|
2543
|
-
const otherMaxHP =
|
|
1413
|
+
const otherMaxHP = maxStatsMap[otherBoss.name].maxHP;
|
|
2544
1414
|
const otherHealAmount = Math.round(otherMaxHP * 0.1);
|
|
2545
1415
|
otherUpdates.push({
|
|
2546
1416
|
name: otherName,
|
|
@@ -3476,807 +2346,1954 @@ var BattleEffectProcessor = {
|
|
|
3476
2346
|
messages.push(`🎭 【伪装】生效:记录新武器「${weaponName}」`);
|
|
3477
2347
|
}
|
|
3478
2348
|
return {
|
|
3479
|
-
nerfMultiplier,
|
|
2349
|
+
nerfMultiplier,
|
|
2350
|
+
messages,
|
|
2351
|
+
targetUpdates
|
|
2352
|
+
};
|
|
2353
|
+
}, "handleDisguise"),
|
|
2354
|
+
// 致命一击处理(概率免疫伤害)
|
|
2355
|
+
handleDeadlyHit: /* @__PURE__ */ __name(function(targetBoss) {
|
|
2356
|
+
const messages = [];
|
|
2357
|
+
let isImmune = false;
|
|
2358
|
+
if (!targetBoss.skills.includes("致命一击")) {
|
|
2359
|
+
return null;
|
|
2360
|
+
}
|
|
2361
|
+
if (Math.random() < 0.05) {
|
|
2362
|
+
isImmune = true;
|
|
2363
|
+
messages.push(`💀 【致命一击】生效:5%概率免疫伤害`);
|
|
2364
|
+
}
|
|
2365
|
+
return { isImmune, messages };
|
|
2366
|
+
}, "handleDeadlyHit"),
|
|
2367
|
+
/** 星界之风处理(概率群体回复)- 修正版 */
|
|
2368
|
+
handleAstralWind: /* @__PURE__ */ __name(function(targetBoss, activeBosses, doubleChance) {
|
|
2369
|
+
const messages = [];
|
|
2370
|
+
const otherUpdates = [];
|
|
2371
|
+
const baseHealAmount = 200;
|
|
2372
|
+
if (!targetBoss.skills.includes("星界之风")) {
|
|
2373
|
+
return null;
|
|
2374
|
+
}
|
|
2375
|
+
const triggerProbability = doubleChance ? 0.1 : 0.05;
|
|
2376
|
+
if (Math.random() >= triggerProbability) {
|
|
2377
|
+
return null;
|
|
2378
|
+
}
|
|
2379
|
+
const survivingBosses = activeBosses.filter((boss) => boss.isActive);
|
|
2380
|
+
survivingBosses.forEach((boss) => {
|
|
2381
|
+
const bossName = boss.name;
|
|
2382
|
+
if (baseHealAmount > 0) {
|
|
2383
|
+
otherUpdates.push({
|
|
2384
|
+
name: bossName,
|
|
2385
|
+
updates: { hpChange: baseHealAmount }
|
|
2386
|
+
});
|
|
2387
|
+
}
|
|
2388
|
+
messages.push(`🌬️ 【星界之风】触发:为「${bossName}」回复${baseHealAmount}点生命值`);
|
|
2389
|
+
});
|
|
2390
|
+
return {
|
|
2391
|
+
messages,
|
|
2392
|
+
otherUpdates
|
|
2393
|
+
};
|
|
2394
|
+
}, "handleAstralWind"),
|
|
2395
|
+
/** 心灵狂热处理(低生命减伤和概率强化)- 修正版 */
|
|
2396
|
+
handleMindFrenzy: /* @__PURE__ */ __name(function(targetBoss) {
|
|
2397
|
+
const messages = [];
|
|
2398
|
+
let nerfMultiplier = 0;
|
|
2399
|
+
let doubleAstralWind = false;
|
|
2400
|
+
if (!targetBoss.skills.includes("心灵狂热")) {
|
|
2401
|
+
return null;
|
|
2402
|
+
}
|
|
2403
|
+
const maxHP = getMaxHPByName(targetBoss.name);
|
|
2404
|
+
const hpPercent = targetBoss.HP / maxHP;
|
|
2405
|
+
if (hpPercent <= 0.5) {
|
|
2406
|
+
nerfMultiplier = 0.2;
|
|
2407
|
+
doubleAstralWind = true;
|
|
2408
|
+
messages.push(`🧠 【心灵狂热】生效:生命值≤50%,受到的伤害-20%,「星界之风」触发概率翻倍`);
|
|
2409
|
+
}
|
|
2410
|
+
return { nerfMultiplier, doubleAstralWind, messages };
|
|
2411
|
+
}, "handleMindFrenzy"),
|
|
2412
|
+
//宇宙能量
|
|
2413
|
+
handleCosmicEnergy: /* @__PURE__ */ __name(function(targetBoss, damage) {
|
|
2414
|
+
if (!targetBoss.skills.includes("宇宙能量")) {
|
|
2415
|
+
return null;
|
|
2416
|
+
}
|
|
2417
|
+
const maxEnergy = getMaxEnergyByName(targetBoss.name);
|
|
2418
|
+
const currentEnergy = targetBoss.energy || 0;
|
|
2419
|
+
const energyToAdd = damage;
|
|
2420
|
+
if (energyToAdd <= 0) {
|
|
2421
|
+
return null;
|
|
2422
|
+
}
|
|
2423
|
+
let energyGained = 0;
|
|
2424
|
+
let overflowHeal = 0;
|
|
2425
|
+
if (currentEnergy + energyToAdd <= maxEnergy) {
|
|
2426
|
+
energyGained = energyToAdd;
|
|
2427
|
+
} else {
|
|
2428
|
+
energyGained = maxEnergy - currentEnergy;
|
|
2429
|
+
overflowHeal = currentEnergy + energyToAdd - maxEnergy;
|
|
2430
|
+
}
|
|
2431
|
+
if (energyGained <= 0 && overflowHeal <= 0) {
|
|
2432
|
+
return null;
|
|
2433
|
+
}
|
|
2434
|
+
const messages = [];
|
|
2435
|
+
const updates = {};
|
|
2436
|
+
let messageParts = [];
|
|
2437
|
+
if (energyGained > 0) {
|
|
2438
|
+
messageParts.push(`获得${energyGained}点能量`);
|
|
2439
|
+
updates.energyChange = energyGained;
|
|
2440
|
+
}
|
|
2441
|
+
if (overflowHeal > 0) {
|
|
2442
|
+
messageParts.push(`${overflowHeal}点溢出伤害转为生命回复`);
|
|
2443
|
+
updates.hpChange = overflowHeal;
|
|
2444
|
+
}
|
|
2445
|
+
if (messageParts.length > 0) {
|
|
2446
|
+
messages.push(`🌌 【宇宙能量】生效:${messageParts.join(",")}`);
|
|
2447
|
+
}
|
|
2448
|
+
return {
|
|
2449
|
+
messages,
|
|
2450
|
+
targetUpdates: {
|
|
2451
|
+
name: targetBoss.name,
|
|
2452
|
+
updates
|
|
2453
|
+
}
|
|
2454
|
+
};
|
|
2455
|
+
}, "handleCosmicEnergy"),
|
|
2456
|
+
// 复苏 (修改后)
|
|
2457
|
+
handleRevival: /* @__PURE__ */ __name(function(targetBoss, damageAmount) {
|
|
2458
|
+
const messages = [];
|
|
2459
|
+
if (!targetBoss.skills.includes("复苏")) {
|
|
2460
|
+
return null;
|
|
2461
|
+
}
|
|
2462
|
+
const isLethal = damageAmount >= targetBoss.HP;
|
|
2463
|
+
if (!isLethal) {
|
|
2464
|
+
return null;
|
|
2465
|
+
}
|
|
2466
|
+
const maxHP = getMaxHPByName(targetBoss.name);
|
|
2467
|
+
const maxEnergy = getMaxEnergyByName(targetBoss.name);
|
|
2468
|
+
const healAmount = Math.round(maxHP * 0.6);
|
|
2469
|
+
const energyGain = maxEnergy;
|
|
2470
|
+
const targetUpdates = {
|
|
2471
|
+
name: targetBoss.name,
|
|
2472
|
+
updates: {
|
|
2473
|
+
hpChange: healAmount,
|
|
2474
|
+
// 回复60%最大生命值
|
|
2475
|
+
energyChange: energyGain,
|
|
2476
|
+
// 回复100%能量
|
|
2477
|
+
skillsRemoved: ["复苏"],
|
|
2478
|
+
// 移除复苏技能
|
|
2479
|
+
skillsAdded: ["灵能构造炉"]
|
|
2480
|
+
// 添加新技能
|
|
2481
|
+
}
|
|
2482
|
+
};
|
|
2483
|
+
messages.push(`🔥 【复苏】生效:承受致命伤害时免疫死亡,回复${healAmount}点生命值和${energyGain}点能量,获得「灵能构造炉」技能`);
|
|
2484
|
+
messages.push(`🔥 【复苏】技能移除`);
|
|
2485
|
+
return {
|
|
2486
|
+
messages,
|
|
2487
|
+
targetUpdates
|
|
2488
|
+
};
|
|
2489
|
+
}, "handleRevival"),
|
|
2490
|
+
/** 光影之刃处理(层数叠加) */
|
|
2491
|
+
handleBladeOfLight: /* @__PURE__ */ __name(function(targetBoss) {
|
|
2492
|
+
const messages = [];
|
|
2493
|
+
let targetUpdates = null;
|
|
2494
|
+
const maxStacks = 50;
|
|
2495
|
+
if (!targetBoss.skills.includes("光影之刃")) {
|
|
2496
|
+
return null;
|
|
2497
|
+
}
|
|
2498
|
+
const currentStacks = targetBoss.skillStacks || 0;
|
|
2499
|
+
if (currentStacks >= maxStacks) {
|
|
2500
|
+
return null;
|
|
2501
|
+
}
|
|
2502
|
+
targetUpdates = {
|
|
2503
|
+
name: targetBoss.name,
|
|
2504
|
+
updates: {
|
|
2505
|
+
skillStacksChanged: 1
|
|
2506
|
+
}
|
|
2507
|
+
};
|
|
2508
|
+
const newStacks = currentStacks + 1;
|
|
2509
|
+
messages.push(`✨ 【光影之刃】生效:获得1层「光影之刃」`);
|
|
2510
|
+
return {
|
|
2511
|
+
messages,
|
|
2512
|
+
targetUpdates
|
|
2513
|
+
};
|
|
2514
|
+
}, "handleBladeOfLight"),
|
|
2515
|
+
/** 远古预兆处理(概率免疫能量伤害)- 增加boost参数 */
|
|
2516
|
+
handleAncientOmen: /* @__PURE__ */ __name(function(targetBoss, weaponData) {
|
|
2517
|
+
const messages = [];
|
|
2518
|
+
let isImmune = false;
|
|
2519
|
+
let targetUpdates = null;
|
|
2520
|
+
if (!targetBoss.skills.includes("远古预兆")) {
|
|
2521
|
+
return null;
|
|
2522
|
+
}
|
|
2523
|
+
if (weaponData.type === "热能武器") {
|
|
2524
|
+
return null;
|
|
2525
|
+
}
|
|
2526
|
+
const lightBladeStacks = targetBoss.skillStacks || 0;
|
|
2527
|
+
const boostPerStack = 5e-3;
|
|
2528
|
+
const totalBoost = lightBladeStacks * boostPerStack;
|
|
2529
|
+
const baseProbability = 0.01;
|
|
2530
|
+
const actualProbability = Math.min(baseProbability + totalBoost, 1);
|
|
2531
|
+
if (Math.random() >= actualProbability) {
|
|
2532
|
+
return null;
|
|
2533
|
+
}
|
|
2534
|
+
isImmune = true;
|
|
2535
|
+
const energyGained = 100;
|
|
2536
|
+
targetUpdates = {
|
|
2537
|
+
name: targetBoss.name,
|
|
2538
|
+
updates: {
|
|
2539
|
+
energyChange: energyGained
|
|
2540
|
+
// 回复100点能量
|
|
2541
|
+
}
|
|
2542
|
+
};
|
|
2543
|
+
messages.push(`🔮 【远古预兆】触发:${(actualProbability * 100).toFixed(2)}%概率免疫非热能武器伤害,并回复${energyGained}点能量`);
|
|
2544
|
+
return {
|
|
2545
|
+
isImmune,
|
|
2546
|
+
messages,
|
|
2547
|
+
targetUpdates
|
|
2548
|
+
};
|
|
2549
|
+
}, "handleAncientOmen"),
|
|
2550
|
+
/** 超视距穿梭处理(层数相关伤害调整) */
|
|
2551
|
+
handleHyperRangeShift: /* @__PURE__ */ __name(function(targetBoss) {
|
|
2552
|
+
const messages = [];
|
|
2553
|
+
let nerfMultiplier = 0;
|
|
2554
|
+
let buffMultiplier = 0;
|
|
2555
|
+
if (!targetBoss.skills.includes("超视距穿梭")) {
|
|
2556
|
+
return null;
|
|
2557
|
+
}
|
|
2558
|
+
const currentEnergy = targetBoss.energy || 0;
|
|
2559
|
+
const maxEnergy = getMaxEnergyByName(targetBoss.name);
|
|
2560
|
+
const energyPercent = currentEnergy / maxEnergy;
|
|
2561
|
+
if (energyPercent >= 0.6) {
|
|
2562
|
+
nerfMultiplier = targetBoss.skillStacks * 0.1;
|
|
2563
|
+
messages.push(`🚀 【超视距穿梭】生效:能量值≥60%,受到的伤害-${(nerfMultiplier * 100).toFixed(0)}%`);
|
|
2564
|
+
} else if (energyPercent >= 0.3) {
|
|
2565
|
+
nerfMultiplier = targetBoss.skillStacks * 0.05;
|
|
2566
|
+
messages.push(`🚀 【超视距穿梭】生效:能量值≥30%,受到的伤害-${(nerfMultiplier * 100).toFixed(0)}%`);
|
|
2567
|
+
} else if (energyPercent <= 0.1) {
|
|
2568
|
+
buffMultiplier = targetBoss.skillStacks * 0.05;
|
|
2569
|
+
messages.push(`🚀 【超视距穿梭】生效:能量值≤10%,受到的伤害+${(buffMultiplier * 100).toFixed(0)}%`);
|
|
2570
|
+
}
|
|
2571
|
+
return { nerfMultiplier, buffMultiplier, messages };
|
|
2572
|
+
}, "handleHyperRangeShift"),
|
|
2573
|
+
/** 灵能构造炉处理(随机获得技能)- 增加boost参数 */
|
|
2574
|
+
handlePsychicForge: /* @__PURE__ */ __name(function(targetBoss) {
|
|
2575
|
+
const messages = [];
|
|
2576
|
+
let newSkill = null;
|
|
2577
|
+
let targetUpdates = null;
|
|
2578
|
+
const possibleSkills = [
|
|
2579
|
+
"天启超载护盾",
|
|
2580
|
+
"塌缩脉冲",
|
|
2581
|
+
"地毯式轰炸",
|
|
2582
|
+
"轰炸引导"
|
|
2583
|
+
];
|
|
2584
|
+
if (!targetBoss.skills.includes("灵能构造炉")) {
|
|
2585
|
+
return null;
|
|
2586
|
+
}
|
|
2587
|
+
const baseProbability = 0.05;
|
|
2588
|
+
if (Math.random() >= baseProbability) {
|
|
2589
|
+
return null;
|
|
2590
|
+
}
|
|
2591
|
+
const availableSkills = possibleSkills.filter(
|
|
2592
|
+
(skill) => !targetBoss.skills.includes(skill)
|
|
2593
|
+
);
|
|
2594
|
+
if (availableSkills.length === 0) {
|
|
2595
|
+
return null;
|
|
2596
|
+
}
|
|
2597
|
+
newSkill = availableSkills[Math.floor(Math.random() * availableSkills.length)];
|
|
2598
|
+
targetUpdates = {
|
|
2599
|
+
name: targetBoss.name,
|
|
2600
|
+
updates: {
|
|
2601
|
+
skillsAdded: [newSkill]
|
|
2602
|
+
}
|
|
2603
|
+
};
|
|
2604
|
+
messages.push(`⚙️ 【灵能构造炉】触发:${(baseProbability * 100).toFixed(2)}%概率获得新技能「${newSkill}」`);
|
|
2605
|
+
return {
|
|
3480
2606
|
messages,
|
|
2607
|
+
newSkill,
|
|
3481
2608
|
targetUpdates
|
|
3482
2609
|
};
|
|
3483
|
-
}, "
|
|
3484
|
-
//
|
|
3485
|
-
|
|
2610
|
+
}, "handlePsychicForge"),
|
|
2611
|
+
// 修改后的天启超载护盾处理函数
|
|
2612
|
+
handleOverdriveShield: /* @__PURE__ */ __name(function(targetBoss, activeBosses) {
|
|
3486
2613
|
const messages = [];
|
|
3487
|
-
|
|
3488
|
-
if (!targetBoss.skills.includes("
|
|
2614
|
+
const otherUpdates = [];
|
|
2615
|
+
if (!targetBoss.skills.includes("天启超载护盾")) {
|
|
3489
2616
|
return null;
|
|
3490
2617
|
}
|
|
3491
|
-
if (Math.random()
|
|
3492
|
-
isImmune = true;
|
|
3493
|
-
messages.push(`💀 【致命一击】生效:5%概率免疫伤害`);
|
|
3494
|
-
}
|
|
3495
|
-
return { isImmune, messages };
|
|
3496
|
-
}, "handleDeadlyHit"),
|
|
3497
|
-
/** 星界之风处理(概率群体回复)- 修正版 */
|
|
3498
|
-
handleAstralWind: /* @__PURE__ */ __name(function(targetBoss, activeBosses, doubleChance) {
|
|
3499
|
-
const messages = [];
|
|
3500
|
-
const otherUpdates = [];
|
|
3501
|
-
const baseHealAmount = 200;
|
|
3502
|
-
if (!targetBoss.skills.includes("星界之风")) {
|
|
2618
|
+
if (Math.random() >= 0.1) {
|
|
3503
2619
|
return null;
|
|
3504
2620
|
}
|
|
3505
|
-
const
|
|
3506
|
-
|
|
2621
|
+
const currentStacks = targetBoss.skillStacks || 0;
|
|
2622
|
+
const consumedStacks = Math.floor(currentStacks / 2);
|
|
2623
|
+
if (consumedStacks <= 0) {
|
|
3507
2624
|
return null;
|
|
3508
2625
|
}
|
|
3509
2626
|
const survivingBosses = activeBosses.filter((boss) => boss.isActive);
|
|
2627
|
+
messages.push(`🛡️ 【天启超载护盾】触发:消耗${consumedStacks}层「光影之刃」`);
|
|
3510
2628
|
survivingBosses.forEach((boss) => {
|
|
3511
|
-
const
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
}
|
|
3518
|
-
messages.push(`🌬️ 【星界之风】触发:为「${bossName}」回复${baseHealAmount}点生命值`);
|
|
2629
|
+
const healAmount = consumedStacks * 10;
|
|
2630
|
+
otherUpdates.push({
|
|
2631
|
+
name: boss.name,
|
|
2632
|
+
updates: { hpChange: healAmount }
|
|
2633
|
+
});
|
|
2634
|
+
messages.push(`为「${boss.name}」回复${healAmount}点生命值`);
|
|
3519
2635
|
});
|
|
2636
|
+
const targetUpdates = {
|
|
2637
|
+
name: targetBoss.name,
|
|
2638
|
+
updates: {
|
|
2639
|
+
skillStacksChanged: -consumedStacks
|
|
2640
|
+
// 消耗层数
|
|
2641
|
+
}
|
|
2642
|
+
};
|
|
3520
2643
|
return {
|
|
3521
2644
|
messages,
|
|
2645
|
+
targetUpdates,
|
|
3522
2646
|
otherUpdates
|
|
3523
2647
|
};
|
|
3524
|
-
}, "
|
|
3525
|
-
/**
|
|
3526
|
-
|
|
2648
|
+
}, "handleOverdriveShield"),
|
|
2649
|
+
/** 塌缩脉冲处理(额外叠加层数) */
|
|
2650
|
+
handleCollapsingPulse: /* @__PURE__ */ __name(function(targetBoss) {
|
|
3527
2651
|
const messages = [];
|
|
3528
|
-
let
|
|
3529
|
-
|
|
3530
|
-
if (!targetBoss.skills.includes("
|
|
2652
|
+
let targetUpdates = null;
|
|
2653
|
+
const maxStacks = 49;
|
|
2654
|
+
if (!targetBoss.skills.includes("塌缩脉冲")) {
|
|
3531
2655
|
return null;
|
|
3532
2656
|
}
|
|
3533
|
-
const
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
nerfMultiplier = 0.2;
|
|
3537
|
-
doubleAstralWind = true;
|
|
3538
|
-
messages.push(`🧠 【心灵狂热】生效:生命值≤50%,受到的伤害-20%,「星界之风」触发概率翻倍`);
|
|
2657
|
+
const currentStacks = targetBoss.skillStacks || 0;
|
|
2658
|
+
if (currentStacks >= maxStacks) {
|
|
2659
|
+
return null;
|
|
3539
2660
|
}
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
2661
|
+
targetUpdates = {
|
|
2662
|
+
name: targetBoss.name,
|
|
2663
|
+
updates: {
|
|
2664
|
+
skillStacksChanged: 1
|
|
2665
|
+
}
|
|
2666
|
+
};
|
|
2667
|
+
const newStacks = currentStacks + 1;
|
|
2668
|
+
messages.push(`🌀 【塌缩脉冲】生效:额外获得1层「光影之刃」`);
|
|
2669
|
+
return {
|
|
2670
|
+
messages,
|
|
2671
|
+
targetUpdates
|
|
2672
|
+
};
|
|
2673
|
+
}, "handleCollapsingPulse"),
|
|
2674
|
+
/** 地毯式轰炸处理 */
|
|
2675
|
+
handleCarpetBombing: /* @__PURE__ */ __name(function(targetBoss) {
|
|
2676
|
+
const messages = [];
|
|
2677
|
+
let nerfMultiplier = 0;
|
|
2678
|
+
if (!targetBoss.skills.includes("地毯式轰炸")) {
|
|
3545
2679
|
return null;
|
|
3546
2680
|
}
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
2681
|
+
nerfMultiplier = 0.8;
|
|
2682
|
+
messages.push(`💣 【地毯式轰炸】生效:受到的伤害-80%`);
|
|
2683
|
+
return { nerfMultiplier, messages, tempMark: true };
|
|
2684
|
+
}, "handleCarpetBombing"),
|
|
2685
|
+
// 修改后的轰炸引导处理函数
|
|
2686
|
+
handleBombardmentGuide: /* @__PURE__ */ __name(function(targetBoss) {
|
|
2687
|
+
const messages = [];
|
|
2688
|
+
if (!targetBoss.skills.includes("轰炸引导")) {
|
|
3551
2689
|
return null;
|
|
3552
2690
|
}
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
if (currentEnergy + energyToAdd <= maxEnergy) {
|
|
3556
|
-
energyGained = energyToAdd;
|
|
3557
|
-
} else {
|
|
3558
|
-
energyGained = maxEnergy - currentEnergy;
|
|
3559
|
-
overflowHeal = currentEnergy + energyToAdd - maxEnergy;
|
|
2691
|
+
if (Math.random() >= 0.1) {
|
|
2692
|
+
return null;
|
|
3560
2693
|
}
|
|
3561
|
-
|
|
2694
|
+
const currentStacks = targetBoss.skillStacks || 0;
|
|
2695
|
+
const consumedStacks = Math.floor(currentStacks / 2);
|
|
2696
|
+
if (consumedStacks <= 0) {
|
|
3562
2697
|
return null;
|
|
3563
2698
|
}
|
|
2699
|
+
const energyGained = consumedStacks * 10;
|
|
2700
|
+
const targetUpdates = {
|
|
2701
|
+
name: targetBoss.name,
|
|
2702
|
+
updates: {
|
|
2703
|
+
skillStacksChanged: -consumedStacks,
|
|
2704
|
+
// 消耗层数
|
|
2705
|
+
energyChange: energyGained
|
|
2706
|
+
// 回复能量
|
|
2707
|
+
}
|
|
2708
|
+
};
|
|
2709
|
+
messages.push(`🎯 【轰炸引导】触发:消耗${consumedStacks}层「光影之刃」,获得${energyGained}点能量`);
|
|
2710
|
+
return {
|
|
2711
|
+
messages,
|
|
2712
|
+
targetUpdates
|
|
2713
|
+
};
|
|
2714
|
+
}, "handleBombardmentGuide"),
|
|
2715
|
+
// 统一的辐射效果处理函数
|
|
2716
|
+
handleRadiationEffect: /* @__PURE__ */ __name(function(targetBoss, weaponName) {
|
|
3564
2717
|
const messages = [];
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
2718
|
+
let layerAdded = false;
|
|
2719
|
+
const currentLayers = targetBoss.radiationLayers || 0;
|
|
2720
|
+
const effectiveLayers = Math.min(currentLayers, 20);
|
|
2721
|
+
const buffMultiplier = effectiveLayers * 0.025;
|
|
2722
|
+
if (effectiveLayers > 0) {
|
|
2723
|
+
messages.push(`☢️ 【辐射增伤】:当前${currentLayers}层,受到的伤害+${(effectiveLayers * 2.5).toFixed(1)}%`);
|
|
2724
|
+
if (currentLayers > 20) {
|
|
2725
|
+
}
|
|
3570
2726
|
}
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
2727
|
+
let targetUpdates = null;
|
|
2728
|
+
if (weaponName === "伽马枪" && // 使用伽马枪
|
|
2729
|
+
!targetBoss.tags.includes("机械") && // 非机械目标
|
|
2730
|
+
targetBoss.tags.includes("生物")) {
|
|
2731
|
+
targetUpdates = {
|
|
2732
|
+
name: targetBoss.name,
|
|
2733
|
+
updates: {
|
|
2734
|
+
radiationLayersChange: 1
|
|
2735
|
+
// 辐射层数增加1
|
|
2736
|
+
}
|
|
2737
|
+
};
|
|
2738
|
+
const newLayers = currentLayers + 1;
|
|
2739
|
+
messages.push(`☢️ 【伽马枪】武器效果:获得1层「辐射」`);
|
|
2740
|
+
layerAdded = true;
|
|
3574
2741
|
}
|
|
3575
|
-
|
|
3576
|
-
messages
|
|
2742
|
+
return {
|
|
2743
|
+
messages,
|
|
2744
|
+
targetUpdates,
|
|
2745
|
+
buffMultiplier,
|
|
2746
|
+
layerAdded
|
|
2747
|
+
// 返回层数增加标记
|
|
2748
|
+
};
|
|
2749
|
+
}, "handleRadiationEffect"),
|
|
2750
|
+
// 统一的寒冷效果处理函数
|
|
2751
|
+
handleColdEffect: /* @__PURE__ */ __name(function(targetBoss, weaponName) {
|
|
2752
|
+
const messages = [];
|
|
2753
|
+
let layerAdded = false;
|
|
2754
|
+
const currentLayers = targetBoss.coldLayers || 0;
|
|
2755
|
+
const effectiveLayers = Math.min(currentLayers, 20);
|
|
2756
|
+
const buffMultiplier = effectiveLayers * 0.025;
|
|
2757
|
+
if (effectiveLayers > 0) {
|
|
2758
|
+
messages.push(`❄️ 【寒冷增伤】:当前${currentLayers}层,受到的伤害+${(effectiveLayers * 2.5).toFixed(1)}%`);
|
|
2759
|
+
if (currentLayers > 20) {
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
let targetUpdates = null;
|
|
2763
|
+
if (weaponName === "零度之下") {
|
|
2764
|
+
targetUpdates = {
|
|
2765
|
+
name: targetBoss.name,
|
|
2766
|
+
updates: {
|
|
2767
|
+
coldLayersChange: 1
|
|
2768
|
+
// 寒冷层数增加1
|
|
2769
|
+
}
|
|
2770
|
+
};
|
|
2771
|
+
const newLayers = currentLayers + 1;
|
|
2772
|
+
messages.push(`❄️【零度之下】武器效果: 获得1层「寒冷」`);
|
|
2773
|
+
layerAdded = true;
|
|
2774
|
+
}
|
|
2775
|
+
return {
|
|
2776
|
+
messages,
|
|
2777
|
+
targetUpdates,
|
|
2778
|
+
buffMultiplier,
|
|
2779
|
+
layerAdded
|
|
2780
|
+
// 返回层数增加标记
|
|
2781
|
+
};
|
|
2782
|
+
}, "handleColdEffect"),
|
|
2783
|
+
// 统一的武器能量消耗处理函数
|
|
2784
|
+
handleWeaponEnergyDrain: /* @__PURE__ */ __name(function(targetBoss, weaponName) {
|
|
2785
|
+
const weaponEnergyDrain = {
|
|
2786
|
+
"弧焊枪": 200,
|
|
2787
|
+
"DG-3电弧步枪": 500
|
|
2788
|
+
};
|
|
2789
|
+
const drainValue = weaponEnergyDrain[weaponName];
|
|
2790
|
+
if (!drainValue) {
|
|
2791
|
+
return null;
|
|
2792
|
+
}
|
|
2793
|
+
const messages = [];
|
|
2794
|
+
const success = drainValue > 0;
|
|
2795
|
+
let targetUpdates = null;
|
|
2796
|
+
if (success) {
|
|
2797
|
+
targetUpdates = {
|
|
2798
|
+
name: targetBoss.name,
|
|
2799
|
+
updates: {
|
|
2800
|
+
energyChange: -drainValue
|
|
2801
|
+
// 消耗能量(负值)
|
|
2802
|
+
}
|
|
2803
|
+
};
|
|
2804
|
+
}
|
|
2805
|
+
const weaponDisplayName = weaponName === "弧焊枪" ? "弧焊枪" : "DG-3电弧步枪";
|
|
2806
|
+
if (success) {
|
|
2807
|
+
messages.push(`⚡ 【${weaponDisplayName}】武器效果:消耗${drainValue}点能量`);
|
|
3577
2808
|
}
|
|
3578
2809
|
return {
|
|
3579
2810
|
messages,
|
|
3580
|
-
targetUpdates
|
|
3581
|
-
|
|
3582
|
-
updates
|
|
3583
|
-
}
|
|
2811
|
+
targetUpdates,
|
|
2812
|
+
success
|
|
3584
2813
|
};
|
|
3585
|
-
}, "
|
|
3586
|
-
//
|
|
3587
|
-
|
|
3588
|
-
const
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
}
|
|
3592
|
-
const
|
|
3593
|
-
if (!
|
|
2814
|
+
}, "handleWeaponEnergyDrain"),
|
|
2815
|
+
// 统一的武器层数减少处理函数
|
|
2816
|
+
handleWeaponLayerReduction: /* @__PURE__ */ __name(function(targetBoss, weaponName) {
|
|
2817
|
+
const weaponLayerReduction = {
|
|
2818
|
+
"脉冲扰乱枪": 2
|
|
2819
|
+
// 可以在这里添加其他武器及其减少层数
|
|
2820
|
+
};
|
|
2821
|
+
const reductionAmount = weaponLayerReduction[weaponName];
|
|
2822
|
+
if (!reductionAmount) {
|
|
3594
2823
|
return null;
|
|
3595
2824
|
}
|
|
3596
|
-
const maxHP = getMaxHPByName(targetBoss.name);
|
|
3597
|
-
const maxEnergy = getMaxEnergyByName(targetBoss.name);
|
|
3598
|
-
const healAmount = Math.round(maxHP * 0.6);
|
|
3599
|
-
const energyGain = maxEnergy;
|
|
3600
|
-
const targetUpdates = {
|
|
3601
|
-
name: targetBoss.name,
|
|
3602
|
-
updates: {
|
|
3603
|
-
hpChange: healAmount,
|
|
3604
|
-
// 回复60%最大生命值
|
|
3605
|
-
energyChange: energyGain,
|
|
3606
|
-
// 回复100%能量
|
|
3607
|
-
skillsRemoved: ["复苏"],
|
|
3608
|
-
// 移除复苏技能
|
|
3609
|
-
skillsAdded: ["灵能构造炉"]
|
|
3610
|
-
// 添加新技能
|
|
3611
|
-
}
|
|
3612
|
-
};
|
|
3613
|
-
messages.push(`🔥 【复苏】生效:承受致命伤害时免疫死亡,回复${healAmount}点生命值和${energyGain}点能量,获得「灵能构造炉」技能`);
|
|
3614
|
-
messages.push(`🔥 【复苏】技能移除`);
|
|
3615
|
-
return {
|
|
3616
|
-
messages,
|
|
3617
|
-
targetUpdates
|
|
3618
|
-
};
|
|
3619
|
-
}, "handleRevival"),
|
|
3620
|
-
/** 光影之刃处理(层数叠加) */
|
|
3621
|
-
handleBladeOfLight: /* @__PURE__ */ __name(function(targetBoss) {
|
|
3622
2825
|
const messages = [];
|
|
2826
|
+
const reductionSuccess = reductionAmount > 0;
|
|
3623
2827
|
let targetUpdates = null;
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
2828
|
+
if (reductionSuccess) {
|
|
2829
|
+
targetUpdates = {
|
|
2830
|
+
name: targetBoss.name,
|
|
2831
|
+
updates: {
|
|
2832
|
+
skillStacksChanged: -reductionAmount
|
|
2833
|
+
// 减少层数
|
|
2834
|
+
}
|
|
2835
|
+
};
|
|
3627
2836
|
}
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
return null;
|
|
2837
|
+
if (reductionSuccess) {
|
|
2838
|
+
messages.push(`⚡ 【${weaponName}】武器效果:技能层数减少${reductionAmount}层`);
|
|
3631
2839
|
}
|
|
3632
|
-
targetUpdates = {
|
|
3633
|
-
name: targetBoss.name,
|
|
3634
|
-
updates: {
|
|
3635
|
-
skillStacksChanged: 1
|
|
3636
|
-
}
|
|
3637
|
-
};
|
|
3638
|
-
const newStacks = currentStacks + 1;
|
|
3639
|
-
messages.push(`✨ 【光影之刃】生效:获得1层「光影之刃」`);
|
|
3640
2840
|
return {
|
|
3641
2841
|
messages,
|
|
3642
|
-
targetUpdates
|
|
2842
|
+
targetUpdates,
|
|
2843
|
+
reductionSuccess
|
|
3643
2844
|
};
|
|
3644
|
-
}, "
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
2845
|
+
}, "handleWeaponLayerReduction")
|
|
2846
|
+
};
|
|
2847
|
+
function applyPassiveEffects(targetBoss, activeBosses, weaponName, damage, ignoreRate) {
|
|
2848
|
+
const messages = [];
|
|
2849
|
+
let immune = false;
|
|
2850
|
+
let totalBuffMultiplier = 0;
|
|
2851
|
+
let totalNerfMultiplier = 0;
|
|
2852
|
+
let radiationLayerAdded = false;
|
|
2853
|
+
let coldLayerAdded = false;
|
|
2854
|
+
let energyDrained = false;
|
|
2855
|
+
let layerReduced = false;
|
|
2856
|
+
let bileDetonationTrigger = false;
|
|
2857
|
+
const weaponData = weaponConfig[weaponName] || { type: "" };
|
|
2858
|
+
let doubleAstralWind = false;
|
|
2859
|
+
let isolatedImmunityMark = false;
|
|
2860
|
+
const processEffect = /* @__PURE__ */ __name((effect, ...args) => {
|
|
2861
|
+
const result = effect(...args);
|
|
2862
|
+
if (!result) return null;
|
|
2863
|
+
messages.push(...result.messages || []);
|
|
2864
|
+
if (result.targetUpdates) {
|
|
2865
|
+
updateStatsByName(result.targetUpdates.name, result.targetUpdates.updates);
|
|
3652
2866
|
}
|
|
3653
|
-
if (
|
|
3654
|
-
|
|
2867
|
+
if (result.otherUpdates) {
|
|
2868
|
+
for (const update of result.otherUpdates) {
|
|
2869
|
+
updateStatsByName(update.name, update.updates);
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
return result;
|
|
2873
|
+
}, "processEffect");
|
|
2874
|
+
const maxStatsMap = {};
|
|
2875
|
+
const allBosses = [targetBoss, ...activeBosses];
|
|
2876
|
+
for (const boss of allBosses) {
|
|
2877
|
+
if (!maxStatsMap[boss.name]) {
|
|
2878
|
+
maxStatsMap[boss.name] = {
|
|
2879
|
+
maxHP: getMaxHPByName(boss.name) || 0,
|
|
2880
|
+
maxEnergy: getMaxEnergyByName(boss.name) || 0
|
|
2881
|
+
};
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
const maxStatsForTarget = maxStatsMap[targetBoss.name];
|
|
2885
|
+
const coldImmuneEffects = [
|
|
2886
|
+
{
|
|
2887
|
+
effect: BattleEffectProcessor.handleColdAdaptation,
|
|
2888
|
+
args: [targetBoss, weaponName]
|
|
2889
|
+
}
|
|
2890
|
+
];
|
|
2891
|
+
const fireImmuneEffects = [];
|
|
2892
|
+
const chanceImmuneEffects = [
|
|
2893
|
+
{
|
|
2894
|
+
effect: BattleEffectProcessor.handleDeadlyHit,
|
|
2895
|
+
args: [targetBoss]
|
|
2896
|
+
},
|
|
2897
|
+
{
|
|
2898
|
+
effect: BattleEffectProcessor.handleElectricField,
|
|
2899
|
+
args: [targetBoss, weaponData]
|
|
2900
|
+
},
|
|
2901
|
+
{
|
|
2902
|
+
effect: BattleEffectProcessor.handleAncientOmen,
|
|
2903
|
+
args: [targetBoss, weaponData]
|
|
2904
|
+
}
|
|
2905
|
+
];
|
|
2906
|
+
const allImmuneEffects = [...coldImmuneEffects, ...fireImmuneEffects, ...chanceImmuneEffects];
|
|
2907
|
+
for (const immuneEffect of allImmuneEffects) {
|
|
2908
|
+
const result = processEffect(immuneEffect.effect, ...immuneEffect.args);
|
|
2909
|
+
if (result?.isImmune) immune = true;
|
|
2910
|
+
}
|
|
2911
|
+
const solarFlareResult = BattleEffectProcessor.handleSolarFlare(targetBoss, weaponName, activeBosses);
|
|
2912
|
+
if (solarFlareResult) {
|
|
2913
|
+
isolatedImmunityMark = solarFlareResult.tempMark || false;
|
|
2914
|
+
if (solarFlareResult.isImmune) immune = true;
|
|
2915
|
+
messages.push(...solarFlareResult.messages);
|
|
2916
|
+
if (solarFlareResult.targetUpdates) {
|
|
2917
|
+
updateStatsByName(solarFlareResult.targetUpdates.name, solarFlareResult.targetUpdates.updates);
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
const carpetBombResult = BattleEffectProcessor.handleCarpetBombing(targetBoss);
|
|
2921
|
+
if (carpetBombResult) {
|
|
2922
|
+
isolatedImmunityMark = carpetBombResult.tempMark || false;
|
|
2923
|
+
if (carpetBombResult.nerfMultiplier) {
|
|
2924
|
+
totalNerfMultiplier += carpetBombResult.nerfMultiplier;
|
|
2925
|
+
}
|
|
2926
|
+
messages.push(...carpetBombResult.messages);
|
|
2927
|
+
}
|
|
2928
|
+
const damageAdjustEffects = [
|
|
2929
|
+
// 单参数效果
|
|
2930
|
+
{ effect: BattleEffectProcessor.handleWeakForm, args: [targetBoss] },
|
|
2931
|
+
{ effect: BattleEffectProcessor.handleAlienShell, args: [targetBoss] },
|
|
2932
|
+
{ effect: BattleEffectProcessor.handleFrostHell, args: [targetBoss] },
|
|
2933
|
+
{ effect: BattleEffectProcessor.handleStressShellI, args: [targetBoss] },
|
|
2934
|
+
{ effect: BattleEffectProcessor.handleStressShellII, args: [targetBoss] },
|
|
2935
|
+
{ effect: BattleEffectProcessor.handleVirusCloud, args: [targetBoss] },
|
|
2936
|
+
{ effect: BattleEffectProcessor.handleEnergyBlackhole, args: [targetBoss] },
|
|
2937
|
+
{ effect: BattleEffectProcessor.handleColossalRampage, args: [targetBoss] },
|
|
2938
|
+
{ effect: BattleEffectProcessor.handleVomit, args: [targetBoss] },
|
|
2939
|
+
{ effect: BattleEffectProcessor.handleRampage, args: [targetBoss] },
|
|
2940
|
+
{ effect: BattleEffectProcessor.handleHyperRangeShift, args: [targetBoss] },
|
|
2941
|
+
// 双参数效果
|
|
2942
|
+
{ effect: BattleEffectProcessor.handleStructuralArmor, args: [targetBoss, weaponData] },
|
|
2943
|
+
{ effect: BattleEffectProcessor.handleDisguise, args: [targetBoss, weaponName] },
|
|
2944
|
+
// 多参数效果
|
|
2945
|
+
{ effect: BattleEffectProcessor.handleIsolated, args: [targetBoss, activeBosses, isolatedImmunityMark] },
|
|
2946
|
+
{ effect: BattleEffectProcessor.handleInfectedSpaceStation, args: [targetBoss, activeBosses] },
|
|
2947
|
+
{ effect: BattleEffectProcessor.handleInfernalBomb, args: [targetBoss, activeBosses] },
|
|
2948
|
+
{ effect: BattleEffectProcessor.handleHunterAlien, args: [targetBoss, activeBosses, weaponName] }
|
|
2949
|
+
];
|
|
2950
|
+
for (const effectItem of damageAdjustEffects) {
|
|
2951
|
+
const result = processEffect(effectItem.effect, ...effectItem.args);
|
|
2952
|
+
if (result) {
|
|
2953
|
+
if (result.buffMultiplier !== void 0) totalBuffMultiplier += result.buffMultiplier;
|
|
2954
|
+
if (result.nerfMultiplier !== void 0) totalNerfMultiplier += result.nerfMultiplier;
|
|
2955
|
+
bileDetonationTrigger ||= result.bileDetonationTrigger === true;
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
const mindFrenzyResult = BattleEffectProcessor.handleMindFrenzy(targetBoss);
|
|
2959
|
+
if (mindFrenzyResult) {
|
|
2960
|
+
messages.push(...mindFrenzyResult.messages);
|
|
2961
|
+
if (mindFrenzyResult.nerfMultiplier) {
|
|
2962
|
+
totalNerfMultiplier += mindFrenzyResult.nerfMultiplier;
|
|
2963
|
+
}
|
|
2964
|
+
doubleAstralWind = mindFrenzyResult.doubleAstralWind || false;
|
|
2965
|
+
}
|
|
2966
|
+
const layerDependentEffects = [
|
|
2967
|
+
{ effect: BattleEffectProcessor.handleVampireSaliva, args: [targetBoss] },
|
|
2968
|
+
{ effect: BattleEffectProcessor.handleBloodlust, args: [targetBoss] },
|
|
2969
|
+
{ effect: BattleEffectProcessor.handleBladeOfLight, args: [targetBoss] },
|
|
2970
|
+
{ effect: BattleEffectProcessor.handleCollapsingPulse, args: [targetBoss] }
|
|
2971
|
+
];
|
|
2972
|
+
for (const effectItem of layerDependentEffects) {
|
|
2973
|
+
const result = processEffect(effectItem.effect, ...effectItem.args);
|
|
2974
|
+
if (result) {
|
|
2975
|
+
if (result.buffMultiplier !== void 0) totalBuffMultiplier += result.buffMultiplier;
|
|
2976
|
+
if (result.nerfMultiplier !== void 0) totalNerfMultiplier += result.nerfMultiplier;
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
const stateChangeEffects = [
|
|
2980
|
+
{ effect: BattleEffectProcessor.handleSuperconductor, args: [targetBoss] }
|
|
2981
|
+
];
|
|
2982
|
+
for (const effectItem of stateChangeEffects) {
|
|
2983
|
+
processEffect(effectItem.effect, ...effectItem.args);
|
|
2984
|
+
}
|
|
2985
|
+
const healingEffects = [
|
|
2986
|
+
{ effect: BattleEffectProcessor.handleFrostRegeneration, args: [targetBoss, activeBosses] },
|
|
2987
|
+
{ effect: BattleEffectProcessor.handleFrostAura, args: [targetBoss, activeBosses] },
|
|
2988
|
+
{ effect: BattleEffectProcessor.handleSentryGun, args: [targetBoss, activeBosses] },
|
|
2989
|
+
{ effect: BattleEffectProcessor.handleMoldGrowth, args: [targetBoss, activeBosses] },
|
|
2990
|
+
{ effect: BattleEffectProcessor.handleElectricShockwave, args: [targetBoss] },
|
|
2991
|
+
{ effect: BattleEffectProcessor.handlePulse, args: [targetBoss, activeBosses] },
|
|
2992
|
+
{ effect: BattleEffectProcessor.handleFeeding, args: [targetBoss] },
|
|
2993
|
+
{ effect: BattleEffectProcessor.handleBurningBurrow, args: [targetBoss] },
|
|
2994
|
+
{ effect: BattleEffectProcessor.handleBombardmentGuide, args: [targetBoss] },
|
|
2995
|
+
{ effect: BattleEffectProcessor.handleOverdriveShield, args: [targetBoss, activeBosses] }
|
|
2996
|
+
];
|
|
2997
|
+
for (const effectItem of healingEffects) {
|
|
2998
|
+
processEffect(effectItem.effect, ...effectItem.args);
|
|
2999
|
+
}
|
|
3000
|
+
const burningSlimeResult = BattleEffectProcessor.handleBurningSlime(targetBoss, weaponName);
|
|
3001
|
+
if (burningSlimeResult) {
|
|
3002
|
+
messages.push(...burningSlimeResult.messages);
|
|
3003
|
+
if (burningSlimeResult.targetUpdates) {
|
|
3004
|
+
updateStatsByName(burningSlimeResult.targetUpdates.name, burningSlimeResult.targetUpdates.updates);
|
|
3005
|
+
}
|
|
3006
|
+
bileDetonationTrigger = burningSlimeResult.isHighStackHeal || false;
|
|
3007
|
+
}
|
|
3008
|
+
const bileEffects = [
|
|
3009
|
+
{ effect: BattleEffectProcessor.handleCorrosiveBile, args: [targetBoss, activeBosses] },
|
|
3010
|
+
{ effect: BattleEffectProcessor.handleFlameBreath, args: [targetBoss, activeBosses] }
|
|
3011
|
+
];
|
|
3012
|
+
for (const effectItem of bileEffects) {
|
|
3013
|
+
processEffect(effectItem.effect, ...effectItem.args);
|
|
3014
|
+
}
|
|
3015
|
+
const astralWindResult = BattleEffectProcessor.handleAstralWind(
|
|
3016
|
+
targetBoss,
|
|
3017
|
+
activeBosses,
|
|
3018
|
+
doubleAstralWind
|
|
3019
|
+
);
|
|
3020
|
+
if (astralWindResult) {
|
|
3021
|
+
messages.push(...astralWindResult.messages);
|
|
3022
|
+
if (astralWindResult.otherUpdates) {
|
|
3023
|
+
for (const update of astralWindResult.otherUpdates) {
|
|
3024
|
+
updateStatsByName(update.name, update.updates);
|
|
3025
|
+
}
|
|
3655
3026
|
}
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3027
|
+
}
|
|
3028
|
+
const psychicForgeResult = BattleEffectProcessor.handlePsychicForge(
|
|
3029
|
+
targetBoss
|
|
3030
|
+
);
|
|
3031
|
+
if (psychicForgeResult) {
|
|
3032
|
+
messages.push(...psychicForgeResult.messages);
|
|
3033
|
+
if (psychicForgeResult.targetUpdates) {
|
|
3034
|
+
updateStatsByName(psychicForgeResult.targetUpdates.name, psychicForgeResult.targetUpdates.updates);
|
|
3663
3035
|
}
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
// 回复100点能量
|
|
3671
|
-
}
|
|
3672
|
-
};
|
|
3673
|
-
messages.push(`🔮 【远古预兆】触发:${(actualProbability * 100).toFixed(2)}%概率免疫非热能武器伤害,并回复${energyGained}点能量`);
|
|
3674
|
-
return {
|
|
3675
|
-
isImmune,
|
|
3676
|
-
messages,
|
|
3677
|
-
targetUpdates
|
|
3678
|
-
};
|
|
3679
|
-
}, "handleAncientOmen"),
|
|
3680
|
-
/** 超视距穿梭处理(层数相关伤害调整) */
|
|
3681
|
-
handleHyperRangeShift: /* @__PURE__ */ __name(function(targetBoss) {
|
|
3682
|
-
const messages = [];
|
|
3683
|
-
let nerfMultiplier = 0;
|
|
3684
|
-
let buffMultiplier = 0;
|
|
3685
|
-
if (!targetBoss.skills.includes("超视距穿梭")) {
|
|
3686
|
-
return null;
|
|
3036
|
+
}
|
|
3037
|
+
const radiationResult = BattleEffectProcessor.handleRadiationEffect(targetBoss, weaponName);
|
|
3038
|
+
if (radiationResult) {
|
|
3039
|
+
messages.push(...radiationResult.messages);
|
|
3040
|
+
if (radiationResult.buffMultiplier) {
|
|
3041
|
+
totalBuffMultiplier += radiationResult.buffMultiplier;
|
|
3687
3042
|
}
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
const energyPercent = currentEnergy / maxEnergy;
|
|
3691
|
-
if (energyPercent >= 0.6) {
|
|
3692
|
-
nerfMultiplier = targetBoss.skillStacks * 0.1;
|
|
3693
|
-
messages.push(`🚀 【超视距穿梭】生效:能量值≥60%,受到的伤害-${(nerfMultiplier * 100).toFixed(0)}%`);
|
|
3694
|
-
} else if (energyPercent >= 0.3) {
|
|
3695
|
-
nerfMultiplier = targetBoss.skillStacks * 0.05;
|
|
3696
|
-
messages.push(`🚀 【超视距穿梭】生效:能量值≥30%,受到的伤害-${(nerfMultiplier * 100).toFixed(0)}%`);
|
|
3697
|
-
} else if (energyPercent <= 0.1) {
|
|
3698
|
-
buffMultiplier = targetBoss.skillStacks * 0.05;
|
|
3699
|
-
messages.push(`🚀 【超视距穿梭】生效:能量值≤10%,受到的伤害+${(buffMultiplier * 100).toFixed(0)}%`);
|
|
3043
|
+
if (radiationResult.targetUpdates) {
|
|
3044
|
+
updateStatsByName(radiationResult.targetUpdates.name, radiationResult.targetUpdates.updates);
|
|
3700
3045
|
}
|
|
3701
|
-
|
|
3702
|
-
}
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
const possibleSkills = [
|
|
3709
|
-
"天启超载护盾",
|
|
3710
|
-
"塌缩脉冲",
|
|
3711
|
-
"地毯式轰炸",
|
|
3712
|
-
"轰炸引导"
|
|
3713
|
-
];
|
|
3714
|
-
if (!targetBoss.skills.includes("灵能构造炉")) {
|
|
3715
|
-
return null;
|
|
3046
|
+
radiationLayerAdded = radiationResult.layerAdded;
|
|
3047
|
+
}
|
|
3048
|
+
const coldResult = BattleEffectProcessor.handleColdEffect(targetBoss, weaponName);
|
|
3049
|
+
if (coldResult) {
|
|
3050
|
+
messages.push(...coldResult.messages);
|
|
3051
|
+
if (coldResult.buffMultiplier) {
|
|
3052
|
+
totalBuffMultiplier += coldResult.buffMultiplier;
|
|
3716
3053
|
}
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
return null;
|
|
3054
|
+
if (coldResult.targetUpdates) {
|
|
3055
|
+
updateStatsByName(coldResult.targetUpdates.name, coldResult.targetUpdates.updates);
|
|
3720
3056
|
}
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3057
|
+
coldLayerAdded = coldResult.layerAdded;
|
|
3058
|
+
}
|
|
3059
|
+
const energyDrainResult = BattleEffectProcessor.handleWeaponEnergyDrain(targetBoss, weaponName);
|
|
3060
|
+
if (energyDrainResult) {
|
|
3061
|
+
messages.push(...energyDrainResult.messages);
|
|
3062
|
+
if (energyDrainResult.targetUpdates) {
|
|
3063
|
+
updateStatsByName(energyDrainResult.targetUpdates.name, energyDrainResult.targetUpdates.updates);
|
|
3726
3064
|
}
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
messages.push(`⚙️ 【灵能构造炉】触发:${(baseProbability * 100).toFixed(2)}%概率获得新技能「${newSkill}」`);
|
|
3735
|
-
return {
|
|
3736
|
-
messages,
|
|
3737
|
-
newSkill,
|
|
3738
|
-
targetUpdates
|
|
3739
|
-
};
|
|
3740
|
-
}, "handlePsychicForge"),
|
|
3741
|
-
// 修改后的天启超载护盾处理函数
|
|
3742
|
-
handleOverdriveShield: /* @__PURE__ */ __name(function(targetBoss, activeBosses) {
|
|
3743
|
-
const messages = [];
|
|
3744
|
-
const otherUpdates = [];
|
|
3745
|
-
if (!targetBoss.skills.includes("天启超载护盾")) {
|
|
3746
|
-
return null;
|
|
3065
|
+
energyDrained = energyDrainResult.success || false;
|
|
3066
|
+
}
|
|
3067
|
+
const layerReduceResult = BattleEffectProcessor.handleWeaponLayerReduction(targetBoss, weaponName);
|
|
3068
|
+
if (layerReduceResult) {
|
|
3069
|
+
messages.push(...layerReduceResult.messages);
|
|
3070
|
+
if (layerReduceResult.targetUpdates) {
|
|
3071
|
+
updateStatsByName(layerReduceResult.targetUpdates.name, layerReduceResult.targetUpdates.updates);
|
|
3747
3072
|
}
|
|
3748
|
-
|
|
3749
|
-
|
|
3073
|
+
layerReduced = layerReduceResult.reductionSuccess || false;
|
|
3074
|
+
}
|
|
3075
|
+
let finalDamage = damage;
|
|
3076
|
+
let adjustedNerfMultiplier = totalNerfMultiplier * (1 - ignoreRate);
|
|
3077
|
+
const damageMultiplier = 1 + totalBuffMultiplier - adjustedNerfMultiplier;
|
|
3078
|
+
finalDamage = Math.max(1, Math.round(damage * damageMultiplier));
|
|
3079
|
+
const frostEvolutionResult = BattleEffectProcessor.handleFrostEvolution(
|
|
3080
|
+
targetBoss,
|
|
3081
|
+
weaponName,
|
|
3082
|
+
finalDamage
|
|
3083
|
+
// 使用最新计算的finalDamage
|
|
3084
|
+
);
|
|
3085
|
+
if (frostEvolutionResult) {
|
|
3086
|
+
messages.push(...frostEvolutionResult.messages);
|
|
3087
|
+
if (frostEvolutionResult.targetUpdates) {
|
|
3088
|
+
updateStatsByName(frostEvolutionResult.targetUpdates.name, frostEvolutionResult.targetUpdates.updates);
|
|
3750
3089
|
}
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
return null;
|
|
3090
|
+
if (frostEvolutionResult.isImmune) {
|
|
3091
|
+
immune = true;
|
|
3092
|
+
finalDamage = 0;
|
|
3755
3093
|
}
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
name: targetBoss.name,
|
|
3768
|
-
updates: {
|
|
3769
|
-
skillStacksChanged: -consumedStacks
|
|
3770
|
-
// 消耗层数
|
|
3771
|
-
}
|
|
3772
|
-
};
|
|
3773
|
-
return {
|
|
3774
|
-
messages,
|
|
3775
|
-
targetUpdates,
|
|
3776
|
-
otherUpdates
|
|
3777
|
-
};
|
|
3778
|
-
}, "handleOverdriveShield"),
|
|
3779
|
-
/** 塌缩脉冲处理(额外叠加层数) */
|
|
3780
|
-
handleCollapsingPulse: /* @__PURE__ */ __name(function(targetBoss) {
|
|
3781
|
-
const messages = [];
|
|
3782
|
-
let targetUpdates = null;
|
|
3783
|
-
const maxStacks = 49;
|
|
3784
|
-
if (!targetBoss.skills.includes("塌缩脉冲")) {
|
|
3785
|
-
return null;
|
|
3094
|
+
}
|
|
3095
|
+
const flameAlienResult = BattleEffectProcessor.handleFlameAlien(
|
|
3096
|
+
targetBoss,
|
|
3097
|
+
weaponName,
|
|
3098
|
+
finalDamage
|
|
3099
|
+
// 使用最新计算的finalDamage
|
|
3100
|
+
);
|
|
3101
|
+
if (flameAlienResult) {
|
|
3102
|
+
messages.push(...flameAlienResult.messages);
|
|
3103
|
+
if (flameAlienResult.targetUpdates) {
|
|
3104
|
+
updateStatsByName(flameAlienResult.targetUpdates.name, flameAlienResult.targetUpdates.updates);
|
|
3786
3105
|
}
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3106
|
+
if (flameAlienResult.isImmune) {
|
|
3107
|
+
immune = true;
|
|
3108
|
+
finalDamage = 0;
|
|
3790
3109
|
}
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
messages.push(
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
targetUpdates
|
|
3802
|
-
};
|
|
3803
|
-
}, "handleCollapsingPulse"),
|
|
3804
|
-
/** 地毯式轰炸处理 */
|
|
3805
|
-
handleCarpetBombing: /* @__PURE__ */ __name(function(targetBoss) {
|
|
3806
|
-
const messages = [];
|
|
3807
|
-
let nerfMultiplier = 0;
|
|
3808
|
-
if (!targetBoss.skills.includes("地毯式轰炸")) {
|
|
3809
|
-
return null;
|
|
3110
|
+
}
|
|
3111
|
+
const cosmicEnergyResult = BattleEffectProcessor.handleCosmicEnergy(
|
|
3112
|
+
targetBoss,
|
|
3113
|
+
finalDamage
|
|
3114
|
+
// 使用最新计算的finalDamage
|
|
3115
|
+
);
|
|
3116
|
+
if (cosmicEnergyResult) {
|
|
3117
|
+
messages.push(...cosmicEnergyResult.messages);
|
|
3118
|
+
if (cosmicEnergyResult.targetUpdates) {
|
|
3119
|
+
updateStatsByName(cosmicEnergyResult.targetUpdates.name, cosmicEnergyResult.targetUpdates.updates);
|
|
3810
3120
|
}
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
}
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3121
|
+
}
|
|
3122
|
+
if (immune) {
|
|
3123
|
+
finalDamage = 0;
|
|
3124
|
+
}
|
|
3125
|
+
const isLethal = finalDamage >= targetBoss.HP && finalDamage > 0;
|
|
3126
|
+
const survivalSkills = [
|
|
3127
|
+
{ func: BattleEffectProcessor.handleSurvivalInstinctI, name: "求生本能I" },
|
|
3128
|
+
{ func: BattleEffectProcessor.handleSurvivalInstinctII, name: "求生本能II" },
|
|
3129
|
+
{ func: BattleEffectProcessor.handleRevival, name: "复苏" }
|
|
3130
|
+
];
|
|
3131
|
+
let revivalTriggered = false;
|
|
3132
|
+
if (isLethal) {
|
|
3133
|
+
for (const skill of survivalSkills) {
|
|
3134
|
+
if (targetBoss.skills.includes(skill.name)) {
|
|
3135
|
+
const result = skill.func(targetBoss, finalDamage);
|
|
3136
|
+
if (result) {
|
|
3137
|
+
updateStatsByName(result.targetUpdates.name, result.targetUpdates.updates);
|
|
3138
|
+
messages.push(...result.messages);
|
|
3139
|
+
revivalTriggered = true;
|
|
3140
|
+
break;
|
|
3141
|
+
}
|
|
3142
|
+
}
|
|
3820
3143
|
}
|
|
3821
|
-
|
|
3822
|
-
|
|
3144
|
+
}
|
|
3145
|
+
if (!revivalTriggered && !immune && finalDamage > 0) {
|
|
3146
|
+
updateStatsByName(targetBoss.name, {
|
|
3147
|
+
hpChange: -finalDamage
|
|
3148
|
+
});
|
|
3149
|
+
}
|
|
3150
|
+
return {
|
|
3151
|
+
finalDamage,
|
|
3152
|
+
messages,
|
|
3153
|
+
radiationLayerAdded,
|
|
3154
|
+
coldLayerAdded,
|
|
3155
|
+
energyDrained,
|
|
3156
|
+
layerReduced,
|
|
3157
|
+
bileDetonationTrigger
|
|
3158
|
+
};
|
|
3159
|
+
}
|
|
3160
|
+
__name(applyPassiveEffects, "applyPassiveEffects");
|
|
3161
|
+
|
|
3162
|
+
// src/boss/passive.ts
|
|
3163
|
+
var passiveConfig = {
|
|
3164
|
+
"弱化形态": {
|
|
3165
|
+
type: "伤害增减(负面)",
|
|
3166
|
+
description: "子代防御脆弱,受到的伤害提高10%"
|
|
3167
|
+
},
|
|
3168
|
+
"异形甲壳": {
|
|
3169
|
+
type: "伤害增减(正面)",
|
|
3170
|
+
description: "受到的伤害降低20%"
|
|
3171
|
+
},
|
|
3172
|
+
"冰霜回复": {
|
|
3173
|
+
type: "生存强化(生命回复)",
|
|
3174
|
+
description: "生命值≤30%时,立即回复自身40%最大生命值,并为所有其他存活异形回复10%最大生命值(生效后移除)"
|
|
3175
|
+
},
|
|
3176
|
+
"冰霜进化": {
|
|
3177
|
+
type: "状态免疫(寒冷伤害免疫)",
|
|
3178
|
+
description: "免疫寒冷伤害,受到寒冷攻击时回复等量生命值"
|
|
3179
|
+
},
|
|
3180
|
+
"冰霜环绕": {
|
|
3181
|
+
type: "生存强化(生命回复+群体增益)",
|
|
3182
|
+
description: "生命值≤30%时,立即回复自身45%最大生命值,并使所有存活异形获得「寒霜地狱」技能(生效后移除)"
|
|
3183
|
+
},
|
|
3184
|
+
"寒霜地狱": {
|
|
3185
|
+
type: "伤害增减(正面)",
|
|
3186
|
+
description: "受到的伤害降低30%"
|
|
3187
|
+
},
|
|
3188
|
+
"应激甲壳I": {
|
|
3189
|
+
type: "伤害增减(正面)",
|
|
3190
|
+
description: "受到的伤害降低20%"
|
|
3191
|
+
},
|
|
3192
|
+
"应激甲壳II": {
|
|
3193
|
+
type: "伤害增减(正面)",
|
|
3194
|
+
description: "受到的伤害降低25%"
|
|
3195
|
+
},
|
|
3196
|
+
"求生本能I": {
|
|
3197
|
+
type: "生存强化(生命回复)",
|
|
3198
|
+
description: "濒死时立即回复自身30%最大生命值(生效后移除)"
|
|
3199
|
+
},
|
|
3200
|
+
"求生本能II": {
|
|
3201
|
+
type: "生存强化(生命回复)",
|
|
3202
|
+
description: "濒死时立即回复自身50%最大生命值(生效后移除)"
|
|
3203
|
+
},
|
|
3204
|
+
"冷适应": {
|
|
3205
|
+
type: "状态免疫(寒冷伤害免疫)",
|
|
3206
|
+
description: "累计承受10次寒冷伤害后,获得「惧热」标签并永久免疫寒冷伤害"
|
|
3207
|
+
},
|
|
3208
|
+
"感染空间站": {
|
|
3209
|
+
type: "伤害增减(正面)",
|
|
3210
|
+
description: "当空间站哨枪塔存活时,自身受到的伤害降低50%"
|
|
3211
|
+
},
|
|
3212
|
+
"病毒云": {
|
|
3213
|
+
type: "伤害增减(正面)",
|
|
3214
|
+
description: "受到的伤害降低10%"
|
|
3215
|
+
},
|
|
3216
|
+
"霉菌滋生": {
|
|
3217
|
+
type: "生存强化(生命回复)",
|
|
3218
|
+
description: "受击后,若空间站哨枪塔存活,为其回复1%最大生命值"
|
|
3219
|
+
},
|
|
3220
|
+
"岗哨机枪": {
|
|
3221
|
+
type: "生存强化(生命回复)",
|
|
3222
|
+
description: "每累计承受10次攻击,为所有其他存活异形回复10%最大生命值"
|
|
3223
|
+
},
|
|
3224
|
+
"结构装甲": {
|
|
3225
|
+
type: "伤害增减(正面)",
|
|
3226
|
+
description: "受实弹/能量武器伤害降低20%,受热能武器伤害降低40%"
|
|
3227
|
+
},
|
|
3228
|
+
"吸血唾液": {
|
|
3229
|
+
type: "伤害增减(正面)",
|
|
3230
|
+
description: "受击获得1层「吸血唾液」(上限20层),每层使受到的伤害降低5%"
|
|
3231
|
+
},
|
|
3232
|
+
"进食": {
|
|
3233
|
+
type: "生存强化(生命回复)",
|
|
3234
|
+
description: "「吸血唾液」≥20层时,下次受击消耗所有层数并回复自身20%最大生命值"
|
|
3235
|
+
},
|
|
3236
|
+
"嗜血狂暴": {
|
|
3237
|
+
type: "伤害增减(正面)",
|
|
3238
|
+
description: "生命值≤50%时,受击额外获得1层「吸血唾液」且受到的伤害降低20%"
|
|
3239
|
+
},
|
|
3240
|
+
"吐血": {
|
|
3241
|
+
type: "伤害增减(负面)",
|
|
3242
|
+
description: "无「吸血唾液」层数时,受到的伤害提高20%"
|
|
3243
|
+
},
|
|
3244
|
+
"超导体": {
|
|
3245
|
+
type: "状态转换(护盾→重甲)",
|
|
3246
|
+
description: "生命值≤10%时,护盾标签永久转换为重甲标签"
|
|
3247
|
+
},
|
|
3248
|
+
"能量虹吸": {
|
|
3249
|
+
type: "伤害增减(正面)",
|
|
3250
|
+
description: "生命值≥70%时伤害降低40%,30%-70%时伤害降低20%"
|
|
3251
|
+
},
|
|
3252
|
+
"能源虹吸": {
|
|
3253
|
+
type: "伤害增减(正面)",
|
|
3254
|
+
description: "能量值≥80%时伤害降低50%,50%-80%时伤害降低30%"
|
|
3255
|
+
},
|
|
3256
|
+
"电能立场": {
|
|
3257
|
+
type: "状态免疫(伤害免疫)",
|
|
3258
|
+
description: "能量值≥30%时,55%概率免疫非热能伤害(每层寒冷降低5%触发概率)"
|
|
3259
|
+
},
|
|
3260
|
+
"电能冲击波": {
|
|
3261
|
+
type: "生存强化(能量回复)",
|
|
3262
|
+
description: "受击后回复100点能量"
|
|
3263
|
+
},
|
|
3264
|
+
"脉冲": {
|
|
3265
|
+
type: "生存强化(生命回复)",
|
|
3266
|
+
description: "能量值≥30%时,60%概率为所有存活异形回复100点生命(每层寒冷降低5%触发概率)"
|
|
3267
|
+
},
|
|
3268
|
+
"能量黑洞": {
|
|
3269
|
+
type: "伤害增减(正面)",
|
|
3270
|
+
description: "存在能量黑洞时,受到的伤害降低20%"
|
|
3271
|
+
},
|
|
3272
|
+
"火焰异形": {
|
|
3273
|
+
type: "状态免疫(火焰伤害免疫)",
|
|
3274
|
+
description: "免疫火焰伤害,受到火焰攻击时回复等量生命值"
|
|
3275
|
+
},
|
|
3276
|
+
"庞兽狂暴": {
|
|
3277
|
+
type: "伤害增减(正面)",
|
|
3278
|
+
description: "生命值≤50%时,受到的伤害降低50%"
|
|
3279
|
+
},
|
|
3280
|
+
"灼烧粘液": {
|
|
3281
|
+
type: "生存强化(生命回复)",
|
|
3282
|
+
description: "受击获得1层「灼烧粘液」;受火焰攻击时消耗所有层数并回复(层数×10)点生命"
|
|
3283
|
+
},
|
|
3284
|
+
"腐蚀胆汁": {
|
|
3285
|
+
type: "生存强化(生命回复)",
|
|
3286
|
+
description: "「灼烧粘液」≥10层时,下次受击消耗所有层数并为所有存活异形回复1000点生命"
|
|
3287
|
+
},
|
|
3288
|
+
"火焰吐息": {
|
|
3289
|
+
type: "生存强化(生命回复)",
|
|
3290
|
+
description: "「灼烧粘液」≥20层时,下次攻击消耗所有层数并为所有存活异形回复20%最大生命值"
|
|
3291
|
+
},
|
|
3292
|
+
"太阳耀斑": {
|
|
3293
|
+
type: "状态移除+状态免疫(寒冷伤害免疫)",
|
|
3294
|
+
description: "所有子代阵亡后,移除惧寒标签和孤立无援状态,并永久免疫寒冷伤害"
|
|
3295
|
+
},
|
|
3296
|
+
"燃烧潜地": {
|
|
3297
|
+
type: "生存强化(生命回复)",
|
|
3298
|
+
description: "生命值≤10%时立即回复50%最大生命值(生效后移除)"
|
|
3299
|
+
},
|
|
3300
|
+
"炼狱爆弹": {
|
|
3301
|
+
type: "伤害增减(正面)",
|
|
3302
|
+
description: "每层「灼烧粘液」使受到的伤害降低5%,存活子代存在时每层额外降低5%"
|
|
3303
|
+
},
|
|
3304
|
+
"猎手异形": {
|
|
3305
|
+
type: "伤害增减(条件性)+状态免疫(火焰/寒冷伤害免疫)",
|
|
3306
|
+
description: "存在其他存活异形时伤害降低20%,无其他存活异形时伤害提高20%;免疫火焰及寒冷伤害"
|
|
3307
|
+
},
|
|
3308
|
+
"狂暴": {
|
|
3309
|
+
type: "伤害增减(正面)",
|
|
3310
|
+
description: "生命值≤50%时,受到的伤害降低50%"
|
|
3311
|
+
},
|
|
3312
|
+
"伪装": {
|
|
3313
|
+
type: "伤害增减(正面)",
|
|
3314
|
+
description: "受击记录伤害来源武器名称,下次被同名武器攻击时伤害降低80%"
|
|
3315
|
+
},
|
|
3316
|
+
"致命一击": {
|
|
3317
|
+
type: "状态免疫(伤害免疫)",
|
|
3318
|
+
description: "受击时5%概率免疫该次伤害"
|
|
3319
|
+
},
|
|
3320
|
+
"星界之风": {
|
|
3321
|
+
type: "生存强化(生命回复)",
|
|
3322
|
+
description: "受击时5%概率为所有存活异形回复200点生命"
|
|
3323
|
+
},
|
|
3324
|
+
"心灵狂热": {
|
|
3325
|
+
type: "伤害增减(正面)",
|
|
3326
|
+
description: "生命值<50%时伤害降低20%且「星界之风」触发概率翻倍"
|
|
3327
|
+
},
|
|
3328
|
+
"宇宙能量": {
|
|
3329
|
+
type: "生存强化(能量/生命回复)",
|
|
3330
|
+
description: "受击回复等量能量值,能量溢出时转换为生命回复"
|
|
3331
|
+
},
|
|
3332
|
+
"复苏": {
|
|
3333
|
+
type: "生存强化(生命/能量回复)",
|
|
3334
|
+
description: "免疫致命伤害,回复60%最大生命与100%能量值,并获得「灵能构造炉」技能(生效后移除)"
|
|
3335
|
+
},
|
|
3336
|
+
"光影之刃": {
|
|
3337
|
+
type: "状态叠加(层数叠加)",
|
|
3338
|
+
description: "受击获得1层「光影之刃」(上限50层)"
|
|
3339
|
+
},
|
|
3340
|
+
"远古预兆": {
|
|
3341
|
+
type: "状态免疫(伤害免疫)+状态增强(触发概率提升)",
|
|
3342
|
+
description: "受击时1%概率免疫非热能伤害并回复100点能量,每层「光影之刃」使触发概率提升0.5%"
|
|
3343
|
+
},
|
|
3344
|
+
"超视距穿梭": {
|
|
3345
|
+
type: "伤害增减(条件性)",
|
|
3346
|
+
description: "能量≥60%时每层「光影之刃」使伤害降低10%,30%-60%时每层降低5%,能量≤10%时每层提高5%"
|
|
3347
|
+
},
|
|
3348
|
+
"灵能构造炉": {
|
|
3349
|
+
type: "状态获得(技能获得)",
|
|
3350
|
+
description: "受击时5%概率随机获得以下技能之一:天启超载护盾/塌缩脉冲/地毯式轰炸/轰炸引导"
|
|
3351
|
+
},
|
|
3352
|
+
"天启超载护盾": {
|
|
3353
|
+
type: "生存强化(生命回复)",
|
|
3354
|
+
description: "受击时10%概率触发,消耗当前「光影之刃」层数的一半(向下取整),并为所有存活异形回复(消耗层数×10)点生命"
|
|
3355
|
+
},
|
|
3356
|
+
"塌缩脉冲": {
|
|
3357
|
+
type: "状态叠加(层数叠加)",
|
|
3358
|
+
description: "受击后额外获得1层「光影之刃」"
|
|
3359
|
+
},
|
|
3360
|
+
"地毯式轰炸": {
|
|
3361
|
+
type: "状态移除+伤害增减(正面)",
|
|
3362
|
+
description: "移除孤立无援状态,受到的伤害降低80%"
|
|
3363
|
+
},
|
|
3364
|
+
"轰炸引导": {
|
|
3365
|
+
type: "生存强化(能量回复)",
|
|
3366
|
+
description: "受击时10%概率触发,消耗当前「光影之刃」层数的一半(向下取整),并回复(消耗层数×10)点能量"
|
|
3367
|
+
}
|
|
3368
|
+
};
|
|
3369
|
+
|
|
3370
|
+
// src/wish.ts
|
|
3371
|
+
var wishConfig = {
|
|
3372
|
+
// 普通祈愿(总概率 5 * 19=95%)
|
|
3373
|
+
common: [
|
|
3374
|
+
{
|
|
3375
|
+
name: "蚱蜢优购",
|
|
3376
|
+
effect: "下一次购买武器(非传奇)享有20%的折扣"
|
|
3377
|
+
},
|
|
3378
|
+
{
|
|
3379
|
+
name: "灵狐升运",
|
|
3380
|
+
effect: "下一次升级武器享有20%的折扣"
|
|
3381
|
+
},
|
|
3382
|
+
{
|
|
3383
|
+
name: "王权增幅",
|
|
3384
|
+
effect: "攻击伤害+10%"
|
|
3385
|
+
},
|
|
3386
|
+
{
|
|
3387
|
+
name: "金柚赐福",
|
|
3388
|
+
effect: "立即获得250枚金币"
|
|
3389
|
+
},
|
|
3390
|
+
{
|
|
3391
|
+
name: "夜市赠礼",
|
|
3392
|
+
effect: "立即获得5枚咕咕币"
|
|
3823
3393
|
}
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3394
|
+
],
|
|
3395
|
+
// 稀有祈愿(总概率 5 * 1=5%)
|
|
3396
|
+
rare: [
|
|
3397
|
+
{
|
|
3398
|
+
name: "悲鸣之锋",
|
|
3399
|
+
effect: "攻击伤害+10% (武器等级0),每级武器等级额外+10%"
|
|
3400
|
+
},
|
|
3401
|
+
{
|
|
3402
|
+
name: "精灵双倍",
|
|
3403
|
+
effect: "下一次击败主宰时可获得双倍的金币和咕咕币奖励"
|
|
3404
|
+
},
|
|
3405
|
+
{
|
|
3406
|
+
name: "喵喵财源",
|
|
3407
|
+
effect: "签到获得双倍的金币和咕咕币"
|
|
3408
|
+
},
|
|
3409
|
+
{
|
|
3410
|
+
name: "暴击韵律",
|
|
3411
|
+
effect: "攻击暴击率+20%"
|
|
3412
|
+
},
|
|
3413
|
+
{
|
|
3414
|
+
name: "酥手空空",
|
|
3415
|
+
effect: "立即失去50枚金币"
|
|
3828
3416
|
}
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3417
|
+
]
|
|
3418
|
+
};
|
|
3419
|
+
|
|
3420
|
+
// src/utils.ts
|
|
3421
|
+
async function gachaWithPity(ctx, handle) {
|
|
3422
|
+
const [record] = await ctx.database.get("ggcevo_records", { handle });
|
|
3423
|
+
const currentPity = record?.pityCounter ?? 0;
|
|
3424
|
+
if (currentPity >= 89) {
|
|
3425
|
+
await updatePityCounter(ctx, handle, true);
|
|
3426
|
+
await ctx.database.upsert("ggcevo_records", [{
|
|
3427
|
+
handle,
|
|
3428
|
+
fullPityCount: (record?.fullPityCount || 0) + 1
|
|
3429
|
+
}], ["handle"]);
|
|
3430
|
+
return true;
|
|
3431
|
+
}
|
|
3432
|
+
const isWin = simpleDraw();
|
|
3433
|
+
await updatePityCounter(ctx, handle, isWin);
|
|
3434
|
+
return isWin;
|
|
3435
|
+
}
|
|
3436
|
+
__name(gachaWithPity, "gachaWithPity");
|
|
3437
|
+
async function gachaWithHiddenAward(ctx, handle) {
|
|
3438
|
+
const backpackItems = await ctx.database.get("ggcevo_backpack", {
|
|
3439
|
+
handle,
|
|
3440
|
+
itemId: { $in: [2, 3] }
|
|
3441
|
+
});
|
|
3442
|
+
const itemMap = new Map(backpackItems.map((item) => [item.itemId, item]));
|
|
3443
|
+
const isWin = HiddenAward();
|
|
3444
|
+
if (isWin) {
|
|
3445
|
+
const updates = [
|
|
3446
|
+
{
|
|
3447
|
+
itemId: 2,
|
|
3448
|
+
addAmount: 1
|
|
3449
|
+
},
|
|
3450
|
+
{
|
|
3451
|
+
itemId: 3,
|
|
3452
|
+
addAmount: 1
|
|
3837
3453
|
}
|
|
3838
|
-
}
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3454
|
+
].map(({ itemId, addAmount }) => ({
|
|
3455
|
+
handle,
|
|
3456
|
+
itemId,
|
|
3457
|
+
quantity: (itemMap.get(itemId)?.quantity || 0) + addAmount
|
|
3458
|
+
}));
|
|
3459
|
+
await ctx.database.upsert("ggcevo_backpack", updates, ["handle", "itemId"]);
|
|
3460
|
+
const [record] = await ctx.database.get("ggcevo_records", { handle });
|
|
3461
|
+
await ctx.database.upsert("ggcevo_records", [{
|
|
3462
|
+
handle,
|
|
3463
|
+
hiddenawards: (record?.hiddenawards || 0) + 1
|
|
3464
|
+
}], ["handle"]);
|
|
3465
|
+
}
|
|
3466
|
+
return isWin;
|
|
3467
|
+
}
|
|
3468
|
+
__name(gachaWithHiddenAward, "gachaWithHiddenAward");
|
|
3469
|
+
async function updatePityCounter(ctx, handle, isWin) {
|
|
3470
|
+
const [record] = await ctx.database.get("ggcevo_records", { handle });
|
|
3471
|
+
const [backpack] = await ctx.database.get("ggcevo_backpack", { handle, itemId: 2 });
|
|
3472
|
+
await ctx.database.upsert("ggcevo_records", [{
|
|
3473
|
+
handle,
|
|
3474
|
+
totalPulls: (record?.totalPulls || 0) + 1,
|
|
3475
|
+
pityCounter: isWin ? 0 : (record?.pityCounter || 0) + 1
|
|
3476
|
+
}], ["handle"]);
|
|
3477
|
+
if (isWin) {
|
|
3478
|
+
await ctx.database.upsert("ggcevo_backpack", [{
|
|
3479
|
+
handle,
|
|
3480
|
+
itemId: 2,
|
|
3481
|
+
quantity: (backpack?.quantity || 0) + 1
|
|
3482
|
+
}]);
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
__name(updatePityCounter, "updatePityCounter");
|
|
3486
|
+
async function checkSensitiveWord(ctx, content) {
|
|
3487
|
+
try {
|
|
3488
|
+
const response = await ctx.http("get", `https://v.api.aa1.cn/api/api-mgc/index.php?msg=${encodeURIComponent(content)}`);
|
|
3489
|
+
return response.data.num !== "1";
|
|
3490
|
+
} catch (error) {
|
|
3491
|
+
console.error("敏感词查询失败:", error);
|
|
3492
|
+
return false;
|
|
3493
|
+
}
|
|
3494
|
+
}
|
|
3495
|
+
__name(checkSensitiveWord, "checkSensitiveWord");
|
|
3496
|
+
function simpleDraw() {
|
|
3497
|
+
return Math.floor(Math.random() * 1e4) < 50;
|
|
3498
|
+
}
|
|
3499
|
+
__name(simpleDraw, "simpleDraw");
|
|
3500
|
+
function HiddenAward() {
|
|
3501
|
+
return Math.floor(Math.random() * 1e4) < 1;
|
|
3502
|
+
}
|
|
3503
|
+
__name(HiddenAward, "HiddenAward");
|
|
3504
|
+
function getRandomInt(min, max) {
|
|
3505
|
+
const actualMin = Math.min(min, max);
|
|
3506
|
+
const actualMax = Math.max(min, max);
|
|
3507
|
+
return Math.floor(Math.random() * (actualMax - actualMin + 1)) + actualMin;
|
|
3508
|
+
}
|
|
3509
|
+
__name(getRandomInt, "getRandomInt");
|
|
3510
|
+
function PetCapsuleToy() {
|
|
3511
|
+
const num = Math.floor(Math.random() * 1e4);
|
|
3512
|
+
if (num < 4e3) return "t3级宠物扭蛋";
|
|
3513
|
+
if (num < 7e3) return "t2级宠物扭蛋";
|
|
3514
|
+
if (num < 9e3) return "t1级宠物扭蛋";
|
|
3515
|
+
return "t0级宠物扭蛋";
|
|
3516
|
+
}
|
|
3517
|
+
__name(PetCapsuleToy, "PetCapsuleToy");
|
|
3518
|
+
function isSameDate(a, b) {
|
|
3519
|
+
return a.getUTCFullYear() === b.getUTCFullYear() && a.getUTCMonth() === b.getUTCMonth() && a.getUTCDate() === b.getUTCDate();
|
|
3520
|
+
}
|
|
3521
|
+
__name(isSameDate, "isSameDate");
|
|
3522
|
+
function isSameHalfDay(a, b) {
|
|
3523
|
+
if (!isSameDate(a, b)) {
|
|
3524
|
+
return false;
|
|
3525
|
+
}
|
|
3526
|
+
const hour1 = a.getUTCHours();
|
|
3527
|
+
const hour2 = b.getUTCHours();
|
|
3528
|
+
return hour1 < 12 && hour2 < 12 || hour1 >= 12 && hour2 >= 12;
|
|
3529
|
+
}
|
|
3530
|
+
__name(isSameHalfDay, "isSameHalfDay");
|
|
3531
|
+
function convertUTCtoChinaTime(input) {
|
|
3532
|
+
const utcDate = new Date(input);
|
|
3533
|
+
if (isNaN(utcDate.getTime())) {
|
|
3534
|
+
throw new Error("Invalid date input");
|
|
3535
|
+
}
|
|
3536
|
+
const chinaTimestamp = utcDate.getTime() + 8 * 60 * 60 * 1e3;
|
|
3537
|
+
return new Date(chinaTimestamp);
|
|
3538
|
+
}
|
|
3539
|
+
__name(convertUTCtoChinaTime, "convertUTCtoChinaTime");
|
|
3540
|
+
function formatDate(d) {
|
|
3541
|
+
return d.toLocaleString("zh-CN", {
|
|
3542
|
+
timeZone: "Asia/Shanghai",
|
|
3543
|
+
year: "numeric",
|
|
3544
|
+
month: "2-digit",
|
|
3545
|
+
day: "2-digit",
|
|
3546
|
+
hour: "2-digit",
|
|
3547
|
+
minute: "2-digit"
|
|
3548
|
+
});
|
|
3549
|
+
}
|
|
3550
|
+
__name(formatDate, "formatDate");
|
|
3551
|
+
function createHpBar(current, max) {
|
|
3552
|
+
const ratio = current / max;
|
|
3553
|
+
const filled = Math.floor(ratio * 20);
|
|
3554
|
+
return "▰".repeat(filled) + "▱".repeat(20 - filled);
|
|
3555
|
+
}
|
|
3556
|
+
__name(createHpBar, "createHpBar");
|
|
3557
|
+
async function activateNextBossGroup(ctx, currentBossId = null) {
|
|
3558
|
+
let availableIndices = [];
|
|
3559
|
+
bossPool.forEach((bossGroup, index) => {
|
|
3560
|
+
if (currentBossId === null || bossGroup.id !== currentBossId) {
|
|
3561
|
+
availableIndices.push(index);
|
|
3562
|
+
}
|
|
3563
|
+
});
|
|
3564
|
+
if (availableIndices.length === 0) {
|
|
3565
|
+
availableIndices = Array.from({ length: bossPool.length }, (_, i) => i);
|
|
3566
|
+
}
|
|
3567
|
+
const randomIndex = availableIndices[Math.floor(Math.random() * availableIndices.length)];
|
|
3568
|
+
const nextBossGroup = bossPool[randomIndex];
|
|
3569
|
+
const mainBoss = await ctx.database.create("ggcevo_boss", {
|
|
3570
|
+
name: nextBossGroup.main.name,
|
|
3571
|
+
type: nextBossGroup.main.type,
|
|
3572
|
+
HP: nextBossGroup.main.maxHP,
|
|
3573
|
+
tags: nextBossGroup.main.tags,
|
|
3574
|
+
// 新增标签字段
|
|
3575
|
+
skills: [...nextBossGroup.main.passive],
|
|
3576
|
+
energy: nextBossGroup.main.maxEnergy,
|
|
3577
|
+
groupId: nextBossGroup.id,
|
|
3578
|
+
isActive: true,
|
|
3579
|
+
respawnTime: /* @__PURE__ */ new Date()
|
|
3580
|
+
});
|
|
3581
|
+
for (const minion of nextBossGroup.minions) {
|
|
3582
|
+
await ctx.database.create("ggcevo_boss", {
|
|
3583
|
+
name: minion.name,
|
|
3584
|
+
type: minion.type,
|
|
3585
|
+
HP: minion.maxHP,
|
|
3586
|
+
tags: minion.tags,
|
|
3587
|
+
// 新增标签字段
|
|
3588
|
+
skills: [...minion.passive],
|
|
3589
|
+
energy: minion.maxEnergy,
|
|
3590
|
+
groupId: nextBossGroup.id,
|
|
3591
|
+
isActive: true,
|
|
3592
|
+
respawnTime: /* @__PURE__ */ new Date()
|
|
3593
|
+
});
|
|
3594
|
+
}
|
|
3595
|
+
return mainBoss;
|
|
3596
|
+
}
|
|
3597
|
+
__name(activateNextBossGroup, "activateNextBossGroup");
|
|
3598
|
+
var weaponConfigById = {};
|
|
3599
|
+
for (const key in weaponConfig) {
|
|
3600
|
+
weaponConfigById[weaponConfig[key].id] = weaponConfig[key];
|
|
3601
|
+
}
|
|
3602
|
+
async function calculateTotalPower(ctx, config, handle) {
|
|
3603
|
+
const [rankData] = await ctx.database.get("ggcevo_rank", {
|
|
3604
|
+
handle,
|
|
3605
|
+
rankseason: config.rankseason
|
|
3606
|
+
});
|
|
3607
|
+
const baseRank = rankData?.rank || 0;
|
|
3608
|
+
let total = baseRank;
|
|
3609
|
+
const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
|
|
3610
|
+
const career = careerData?.career;
|
|
3611
|
+
if (career) {
|
|
3612
|
+
if (career === "联盟新兵") total += 1e3;
|
|
3613
|
+
else if (career === "辛迪加炮灰新兵") total += 2e3;
|
|
3614
|
+
else if (["深空矿工", "医疗专家", "情报副官", "总工程师", "舰长", "机械化专家"].includes(career)) total += 2500;
|
|
3615
|
+
else if (["清洁工", "辛迪加财务经理", "计算机专家", "指挥官", "装甲兵", "破坏者", "征募官"].includes(career)) total += 3e3;
|
|
3616
|
+
else if (["警卫员下士", "警卫长", "武器中士"].includes(career)) total += 3500;
|
|
3617
|
+
else if (["能量武器专家", "枪手", "猩红杀手", "纵火狂"].includes(career)) total += 4e3;
|
|
3618
|
+
}
|
|
3619
|
+
const weapons = await ctx.database.get("ggcevo_weapons", { handle });
|
|
3620
|
+
for (const { weaponId, level, installedMods } of weapons) {
|
|
3621
|
+
const weapon = weaponConfigById[weaponId];
|
|
3622
|
+
if (!weapon) continue;
|
|
3623
|
+
total += weapon.damage * 100;
|
|
3624
|
+
total += level * (level + 1) / 2 * 1e3;
|
|
3625
|
+
for (const modName of installedMods || []) {
|
|
3626
|
+
const mod = modConfig[modName];
|
|
3627
|
+
if (mod) {
|
|
3628
|
+
if (mod.isExclusive) {
|
|
3629
|
+
total += 4e3;
|
|
3630
|
+
} else {
|
|
3631
|
+
total += 2e3;
|
|
3632
|
+
}
|
|
3855
3633
|
}
|
|
3856
3634
|
}
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3635
|
+
}
|
|
3636
|
+
return total;
|
|
3637
|
+
}
|
|
3638
|
+
__name(calculateTotalPower, "calculateTotalPower");
|
|
3639
|
+
async function applyItemEffect(ctx, session, handle, itemConfig2, target) {
|
|
3640
|
+
try {
|
|
3641
|
+
const itemName = Object.entries(SyndicatedItems).find(
|
|
3642
|
+
([_, item]) => item.id === itemConfig2.id
|
|
3643
|
+
)?.[0] || "未知物品";
|
|
3644
|
+
if (itemConfig2.id === 1) {
|
|
3645
|
+
const activeSentry = await ctx.database.get("ggcevo_boss", {
|
|
3646
|
+
name: "空间站哨枪塔",
|
|
3647
|
+
isActive: true
|
|
3648
|
+
});
|
|
3649
|
+
if (!activeSentry.length) return {
|
|
3650
|
+
success: false,
|
|
3651
|
+
message: "⚠️ 目标「空间站哨枪塔」未存活"
|
|
3652
|
+
};
|
|
3653
|
+
const [SentryTower] = await ctx.database.get("ggcevo_boss", {
|
|
3654
|
+
name: "空间站哨枪塔",
|
|
3655
|
+
isActive: true
|
|
3656
|
+
});
|
|
3657
|
+
const damageValue = SentryTower.HP;
|
|
3658
|
+
await ctx.database.set(
|
|
3659
|
+
"ggcevo_boss",
|
|
3660
|
+
{ name: "空间站哨枪塔" },
|
|
3661
|
+
{ isActive: false, HP: 0 }
|
|
3662
|
+
);
|
|
3663
|
+
await ctx.database.withTransaction(async () => {
|
|
3664
|
+
const signRecords = await ctx.database.get("ggcevo_sign", { handle });
|
|
3665
|
+
await ctx.database.upsert("ggcevo_sign", [{
|
|
3666
|
+
handle,
|
|
3667
|
+
totalRewards: (signRecords[0]?.totalRewards || 0) + damageValue
|
|
3668
|
+
}], ["handle"]);
|
|
3669
|
+
const [damageRecords] = await ctx.database.get("ggcevo_boss_damage", { handle });
|
|
3670
|
+
await ctx.database.upsert("ggcevo_boss_damage", [{
|
|
3671
|
+
handle,
|
|
3672
|
+
playerName: session.username,
|
|
3673
|
+
totalDamage: (damageRecords?.totalDamage || 0) + damageValue,
|
|
3674
|
+
attackCount: damageRecords?.attackCount || 0,
|
|
3675
|
+
bossGroupId: 4
|
|
3676
|
+
}], ["handle"]);
|
|
3677
|
+
});
|
|
3678
|
+
return {
|
|
3679
|
+
success: true,
|
|
3680
|
+
message: `成功引爆${itemName},对空间站哨枪塔造成${damageValue}点伤害,获得等额金币。`
|
|
3867
3681
|
};
|
|
3868
|
-
const newLayers = currentLayers + 1;
|
|
3869
|
-
messages.push(`☢️ 【伽马枪】武器效果:获得1层「辐射」`);
|
|
3870
|
-
layerAdded = true;
|
|
3871
3682
|
}
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3683
|
+
if (itemConfig2.id === 2) {
|
|
3684
|
+
if (!target) return {
|
|
3685
|
+
success: false,
|
|
3686
|
+
message: "您未选择合适的目标。"
|
|
3687
|
+
};
|
|
3688
|
+
const [targetboss] = await ctx.database.get("ggcevo_boss", {
|
|
3689
|
+
name: target,
|
|
3690
|
+
isActive: true
|
|
3691
|
+
});
|
|
3692
|
+
if (!targetboss) return {
|
|
3693
|
+
success: false,
|
|
3694
|
+
message: "无法找到指定的目标。"
|
|
3695
|
+
};
|
|
3696
|
+
if (targetboss.tags.includes("建筑") || targetboss.tags.includes("重型")) {
|
|
3697
|
+
return {
|
|
3698
|
+
success: false,
|
|
3699
|
+
message: `目标${target}拥有"${targetboss.tags.includes("建筑") ? "建筑" : "重型"}"标签,无法使用此物品。`
|
|
3700
|
+
};
|
|
3890
3701
|
}
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3702
|
+
const currentCount = targetboss?.skillStacks || 0;
|
|
3703
|
+
if (currentCount <= 0) {
|
|
3704
|
+
return {
|
|
3705
|
+
success: false,
|
|
3706
|
+
message: `目标${target}的技能层数已为0,无需使用此物品。`
|
|
3707
|
+
};
|
|
3708
|
+
}
|
|
3709
|
+
const newCount = Math.max(0, currentCount - 10);
|
|
3710
|
+
const reducedAmount = currentCount - newCount;
|
|
3711
|
+
await ctx.database.set(
|
|
3712
|
+
"ggcevo_boss",
|
|
3713
|
+
{ name: target },
|
|
3714
|
+
{ skillStacks: newCount }
|
|
3715
|
+
);
|
|
3716
|
+
return {
|
|
3717
|
+
success: true,
|
|
3718
|
+
message: `成功使用${itemName},使${target}的技能层数减少10层`
|
|
3900
3719
|
};
|
|
3901
|
-
const newLayers = currentLayers + 1;
|
|
3902
|
-
messages.push(`❄️【零度之下】武器效果: 获得1层「寒冷」`);
|
|
3903
|
-
layerAdded = true;
|
|
3904
|
-
}
|
|
3905
|
-
return {
|
|
3906
|
-
messages,
|
|
3907
|
-
targetUpdates,
|
|
3908
|
-
buffMultiplier,
|
|
3909
|
-
layerAdded
|
|
3910
|
-
// 返回层数增加标记
|
|
3911
|
-
};
|
|
3912
|
-
}, "handleColdEffect"),
|
|
3913
|
-
// 统一的武器能量消耗处理函数
|
|
3914
|
-
handleWeaponEnergyDrain: /* @__PURE__ */ __name(function(targetBoss, weaponName) {
|
|
3915
|
-
const weaponEnergyDrain = {
|
|
3916
|
-
"弧焊枪": 200,
|
|
3917
|
-
"DG-3电弧步枪": 500
|
|
3918
|
-
};
|
|
3919
|
-
const drainValue = weaponEnergyDrain[weaponName];
|
|
3920
|
-
if (!drainValue) {
|
|
3921
|
-
return null;
|
|
3922
3720
|
}
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3721
|
+
if (itemConfig2.id === 4) {
|
|
3722
|
+
if (!target) return {
|
|
3723
|
+
success: false,
|
|
3724
|
+
message: "您未选择合适的目标。"
|
|
3725
|
+
};
|
|
3726
|
+
const [targetboss] = await ctx.database.get("ggcevo_boss", {
|
|
3727
|
+
name: target,
|
|
3728
|
+
isActive: true
|
|
3729
|
+
});
|
|
3730
|
+
if (!targetboss || targetboss?.energy === 0) return {
|
|
3731
|
+
success: false,
|
|
3732
|
+
message: "您无法对没有能量的目标使用。"
|
|
3733
|
+
};
|
|
3734
|
+
await ctx.database.set(
|
|
3735
|
+
"ggcevo_boss",
|
|
3736
|
+
{ name: target },
|
|
3737
|
+
{ energy: Math.max(targetboss.energy - 500, 0) }
|
|
3738
|
+
// 确保不低于0
|
|
3739
|
+
);
|
|
3740
|
+
return {
|
|
3741
|
+
success: true,
|
|
3742
|
+
message: `成功使用${itemName},消耗${target}500点能量`
|
|
3933
3743
|
};
|
|
3934
|
-
}
|
|
3935
|
-
const weaponDisplayName = weaponName === "弧焊枪" ? "弧焊枪" : "DG-3电弧步枪";
|
|
3936
|
-
if (success) {
|
|
3937
|
-
messages.push(`⚡ 【${weaponDisplayName}】武器效果:消耗${drainValue}点能量`);
|
|
3938
3744
|
}
|
|
3939
3745
|
return {
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
success
|
|
3943
|
-
};
|
|
3944
|
-
}, "handleWeaponEnergyDrain"),
|
|
3945
|
-
// 统一的武器层数减少处理函数
|
|
3946
|
-
handleWeaponLayerReduction: /* @__PURE__ */ __name(function(targetBoss, weaponName) {
|
|
3947
|
-
const weaponLayerReduction = {
|
|
3948
|
-
"脉冲扰乱枪": 2
|
|
3949
|
-
// 可以在这里添加其他武器及其减少层数
|
|
3746
|
+
success: false,
|
|
3747
|
+
message: `${itemName} 无法使用。`
|
|
3950
3748
|
};
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
return null;
|
|
3954
|
-
}
|
|
3955
|
-
const messages = [];
|
|
3956
|
-
const reductionSuccess = reductionAmount > 0;
|
|
3957
|
-
let targetUpdates = null;
|
|
3958
|
-
if (reductionSuccess) {
|
|
3959
|
-
targetUpdates = {
|
|
3960
|
-
name: targetBoss.name,
|
|
3961
|
-
updates: {
|
|
3962
|
-
skillStacksChanged: -reductionAmount
|
|
3963
|
-
// 减少层数
|
|
3964
|
-
}
|
|
3965
|
-
};
|
|
3966
|
-
}
|
|
3967
|
-
if (reductionSuccess) {
|
|
3968
|
-
messages.push(`⚡ 【${weaponName}】武器效果:技能层数减少${reductionAmount}层`);
|
|
3969
|
-
}
|
|
3749
|
+
} catch (error) {
|
|
3750
|
+
console.error("物品效果处理失败:", error);
|
|
3970
3751
|
return {
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3752
|
+
success: false,
|
|
3753
|
+
message: "⚠️ 物品效果处理异常,已回滚操作。"
|
|
3754
|
+
};
|
|
3755
|
+
}
|
|
3756
|
+
}
|
|
3757
|
+
__name(applyItemEffect, "applyItemEffect");
|
|
3758
|
+
async function handleTechUpgrade(ctx, handle, target) {
|
|
3759
|
+
const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
|
|
3760
|
+
if (!careerData || careerData.group !== "人类联盟") {
|
|
3761
|
+
return "🚫 该功能需要【人类联盟】阵营权限";
|
|
3762
|
+
}
|
|
3763
|
+
const tech = Spacestationtechnology.find(
|
|
3764
|
+
(t) => t.techname === target
|
|
3765
|
+
);
|
|
3766
|
+
const [techEntry] = await ctx.database.get("ggcevo_tech", { handle, techId: tech.techId });
|
|
3767
|
+
const currentLevel = techEntry?.level || 0;
|
|
3768
|
+
if (currentLevel >= tech.maxLevel) return `❌ ${tech.techname}已达最高等级`;
|
|
3769
|
+
const nextLevel = currentLevel + 1;
|
|
3770
|
+
const levelData = tech.levels.find((l) => l.level === nextLevel);
|
|
3771
|
+
let originalCost = levelData.cost;
|
|
3772
|
+
let actualCost = originalCost;
|
|
3773
|
+
let discountApplied = false;
|
|
3774
|
+
let discountDetails = [];
|
|
3775
|
+
if (careerData.career === "情报副官") {
|
|
3776
|
+
discountApplied = true;
|
|
3777
|
+
actualCost = Math.floor(originalCost * 0.9);
|
|
3778
|
+
discountDetails.push("🎖️ 情报副官职业:10%折扣");
|
|
3779
|
+
}
|
|
3780
|
+
const [signInfo] = await ctx.database.get("ggcevo_sign", { handle });
|
|
3781
|
+
if (signInfo?.totalRewards < actualCost) {
|
|
3782
|
+
const priceHint = discountApplied ? ` (原价${originalCost}金币)` : "";
|
|
3783
|
+
return `❌ 金币不足!需要${actualCost}金币${priceHint},您当前拥有:${signInfo?.totalRewards || 0}金币`;
|
|
3784
|
+
}
|
|
3785
|
+
let permissionGrantInfo = null;
|
|
3786
|
+
if (tech.techname === "武器系统" && currentLevel === 4 && nextLevel === 5) {
|
|
3787
|
+
permissionGrantInfo = {
|
|
3788
|
+
type: "武器系统",
|
|
3789
|
+
field: "legendarypermissions",
|
|
3790
|
+
amount: 1,
|
|
3791
|
+
message: "🎉 解锁传奇武器购买权限1次!"
|
|
3974
3792
|
};
|
|
3975
|
-
}
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
}
|
|
3793
|
+
}
|
|
3794
|
+
if (tech.techname === "安防系统" && currentLevel === 4 && nextLevel === 5) {
|
|
3795
|
+
permissionGrantInfo = {
|
|
3796
|
+
type: "安防系统",
|
|
3797
|
+
field: "explosiondoorauthority",
|
|
3798
|
+
amount: 1,
|
|
3799
|
+
message: "🔓 解锁安全军械库防爆门权限1次!"
|
|
3800
|
+
};
|
|
3801
|
+
}
|
|
3802
|
+
await ctx.database.withTransaction(async () => {
|
|
3803
|
+
await ctx.database.set("ggcevo_sign", { handle }, {
|
|
3804
|
+
totalRewards: signInfo.totalRewards - actualCost
|
|
3805
|
+
});
|
|
3806
|
+
await ctx.database.upsert("ggcevo_tech", [{
|
|
3807
|
+
handle,
|
|
3808
|
+
techId: tech.techId,
|
|
3809
|
+
level: nextLevel
|
|
3810
|
+
}], ["handle", "techId"]);
|
|
3811
|
+
if (permissionGrantInfo) {
|
|
3812
|
+
const [permissionRecord] = await ctx.database.get("ggcevo_permissions", { handle });
|
|
3813
|
+
const currentValue = permissionRecord?.[permissionGrantInfo.field] || 0;
|
|
3814
|
+
await ctx.database.upsert("ggcevo_permissions", [{
|
|
3815
|
+
handle,
|
|
3816
|
+
[permissionGrantInfo.field]: currentValue + permissionGrantInfo.amount
|
|
3817
|
+
}], ["handle"]);
|
|
4001
3818
|
}
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
3819
|
+
});
|
|
3820
|
+
let discountInfo = [];
|
|
3821
|
+
if (discountApplied) {
|
|
3822
|
+
discountInfo = [
|
|
3823
|
+
"💰 折扣明细:",
|
|
3824
|
+
...discountDetails.map((detail) => `▸ ${detail}`)
|
|
3825
|
+
];
|
|
3826
|
+
}
|
|
3827
|
+
const costInfo = discountApplied ? `💸 花费金币:${actualCost} (原价${originalCost})` : `💸 花费金币:${actualCost}`;
|
|
3828
|
+
let permissionMessage = [];
|
|
3829
|
+
if (permissionGrantInfo) {
|
|
3830
|
+
const [permissionRecord] = await ctx.database.get("ggcevo_permissions", { handle });
|
|
3831
|
+
const newValue = permissionRecord?.[permissionGrantInfo.field] || permissionGrantInfo.amount;
|
|
3832
|
+
permissionMessage.push(
|
|
3833
|
+
permissionGrantInfo.message
|
|
3834
|
+
);
|
|
3835
|
+
}
|
|
3836
|
+
return [
|
|
3837
|
+
`✅ ${tech.techname} 升级至 Lv.${nextLevel}`,
|
|
3838
|
+
costInfo,
|
|
3839
|
+
...discountInfo,
|
|
3840
|
+
// 折扣信息
|
|
3841
|
+
`📝 基础效果:${levelData.description}`,
|
|
3842
|
+
`💼 职业效果:${levelData.careerBonus}`,
|
|
3843
|
+
...permissionMessage
|
|
3844
|
+
// 权限解锁信息
|
|
3845
|
+
].filter(Boolean).join("\n");
|
|
3846
|
+
}
|
|
3847
|
+
__name(handleTechUpgrade, "handleTechUpgrade");
|
|
3848
|
+
async function handleWeaponUpgrade(ctx, handle, target) {
|
|
3849
|
+
const weaponData = weaponConfig[target];
|
|
3850
|
+
const [equipment] = await ctx.database.get("ggcevo_weapons", {
|
|
3851
|
+
handle,
|
|
3852
|
+
weaponId: weaponData.id
|
|
3853
|
+
});
|
|
3854
|
+
const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
|
|
3855
|
+
if (!equipment) return "❌ 您尚未获得该武器";
|
|
3856
|
+
const maxLevel = careerData?.career === "枪手" ? 7 : 6;
|
|
3857
|
+
if (equipment.level >= maxLevel) return `❌ 该武器已达最高等级(Lv.${maxLevel})`;
|
|
3858
|
+
const BASE_COST = [1050, 1450, 1850, 2250, 2650, 3050, 3450];
|
|
3859
|
+
const baseCost = BASE_COST[equipment.level];
|
|
3860
|
+
const weaponTechConfig = Spacestationtechnology.find((t) => t.techId === 2);
|
|
3861
|
+
let techLevel = 0;
|
|
3862
|
+
let totalDiscount = 0;
|
|
3863
|
+
const discountDetails = [];
|
|
3864
|
+
const isGunslinger = careerData?.career === "枪手";
|
|
3865
|
+
if (isGunslinger) {
|
|
3866
|
+
totalDiscount += 10;
|
|
3867
|
+
discountDetails.push("🔫 枪手职业:10%折扣");
|
|
3868
|
+
}
|
|
3869
|
+
if (careerData?.group === "人类联盟") {
|
|
3870
|
+
const [weaponTech] = await ctx.database.get("ggcevo_tech", { handle, techId: 2 }).catch(() => [{ level: 0 }]);
|
|
3871
|
+
techLevel = Math.min(Math.max(weaponTech?.level || 0, 0), 5);
|
|
3872
|
+
const isCareerMatch = weaponTechConfig?.careerNames.includes(careerData?.career);
|
|
3873
|
+
const BASE_DISCOUNTS = [5, 10, 15, 20, 25];
|
|
3874
|
+
const CAREER_DISCOUNTS = [10, 20, 30, 40, 50];
|
|
3875
|
+
const baseDiscount = techLevel > 0 ? BASE_DISCOUNTS[techLevel - 1] : 0;
|
|
3876
|
+
const careerDiscount = isCareerMatch && techLevel > 0 ? CAREER_DISCOUNTS[techLevel - 1] : 0;
|
|
3877
|
+
const weaponDiscount = Math.max(baseDiscount, careerDiscount);
|
|
3878
|
+
if (weaponDiscount > 0) {
|
|
3879
|
+
totalDiscount += weaponDiscount;
|
|
3880
|
+
discountDetails.push(
|
|
3881
|
+
`⚙️ 武器系统Lv.${techLevel}:${weaponDiscount}%折扣`
|
|
3882
|
+
);
|
|
4008
3883
|
}
|
|
4009
|
-
|
|
4010
|
-
const
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
{
|
|
4021
|
-
|
|
4022
|
-
|
|
3884
|
+
}
|
|
3885
|
+
const activeWish = await checkFoxBlessing(ctx, handle);
|
|
3886
|
+
if (activeWish) {
|
|
3887
|
+
totalDiscount += 20;
|
|
3888
|
+
discountDetails.push("🦊 灵狐升运祈愿:20%折扣");
|
|
3889
|
+
}
|
|
3890
|
+
totalDiscount = Math.min(totalDiscount, 100);
|
|
3891
|
+
const discountedCost = baseCost * (100 - totalDiscount) / 100;
|
|
3892
|
+
const actualCost = Math.floor(discountedCost);
|
|
3893
|
+
const [signInfo] = await ctx.database.get("ggcevo_sign", { handle });
|
|
3894
|
+
if (signInfo?.totalRewards < actualCost) {
|
|
3895
|
+
const priceInfo2 = totalDiscount > 0 ? `需要${actualCost}金币(原价${baseCost}金币)` : `需要${actualCost}金币`;
|
|
3896
|
+
return `❌ ${priceInfo2},您当前拥有:${signInfo?.totalRewards || 0}金币`;
|
|
3897
|
+
}
|
|
3898
|
+
const newLevel = equipment.level + 1;
|
|
3899
|
+
const newModSlots = Math.floor(newLevel / 3) + 1;
|
|
3900
|
+
await ctx.database.withTransaction(async () => {
|
|
3901
|
+
await ctx.database.set("ggcevo_sign", { handle }, {
|
|
3902
|
+
totalRewards: signInfo.totalRewards - actualCost
|
|
3903
|
+
});
|
|
3904
|
+
await ctx.database.set(
|
|
3905
|
+
"ggcevo_weapons",
|
|
3906
|
+
{ handle, weaponId: weaponData.id },
|
|
3907
|
+
{
|
|
3908
|
+
level: newLevel,
|
|
3909
|
+
modificationSlots: newModSlots
|
|
3910
|
+
}
|
|
3911
|
+
);
|
|
3912
|
+
if (activeWish) {
|
|
3913
|
+
await ctx.database.set(
|
|
3914
|
+
"ggcevo_wish",
|
|
3915
|
+
{ id: activeWish.id },
|
|
3916
|
+
{ isused: true }
|
|
3917
|
+
);
|
|
4023
3918
|
}
|
|
4024
|
-
|
|
4025
|
-
const
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
3919
|
+
});
|
|
3920
|
+
const damage = (weaponData.damage * (1 + 0.1 * newLevel)).toFixed(1);
|
|
3921
|
+
let msg = `${target} 升级成功!Lv.${newLevel}`;
|
|
3922
|
+
const priceInfo = totalDiscount > 0 ? `
|
|
3923
|
+
💸 花费:${actualCost}金币 (原价${baseCost}金币)` : `
|
|
3924
|
+
💸 花费:${actualCost}金币`;
|
|
3925
|
+
msg += priceInfo;
|
|
3926
|
+
if (discountDetails.length > 0) {
|
|
3927
|
+
msg += `
|
|
3928
|
+
💰 折扣明细:
|
|
3929
|
+
▸ ${discountDetails.join("\n▸ ")}`;
|
|
4029
3930
|
}
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
3931
|
+
msg += `
|
|
3932
|
+
💥 伤害:${damage}`;
|
|
3933
|
+
msg += `
|
|
3934
|
+
🔧 改装槽:${newModSlots}个`;
|
|
3935
|
+
return msg;
|
|
3936
|
+
}
|
|
3937
|
+
__name(handleWeaponUpgrade, "handleWeaponUpgrade");
|
|
3938
|
+
async function checkFoxBlessing(ctx, handle) {
|
|
3939
|
+
return ctx.database.get("ggcevo_wish", {
|
|
3940
|
+
handle,
|
|
3941
|
+
wishname: "灵狐升运",
|
|
3942
|
+
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
3943
|
+
endTime: { $gte: /* @__PURE__ */ new Date() },
|
|
3944
|
+
isused: false
|
|
3945
|
+
}).then((records) => records[0]);
|
|
3946
|
+
}
|
|
3947
|
+
__name(checkFoxBlessing, "checkFoxBlessing");
|
|
3948
|
+
async function generateUpgradePriceList(ctx, handle) {
|
|
3949
|
+
const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
|
|
3950
|
+
const isGunslinger = careerData?.career === "枪手";
|
|
3951
|
+
const isAlliance = careerData?.group === "人类联盟";
|
|
3952
|
+
let techLevel = 0;
|
|
3953
|
+
let techDiscountRate = 0;
|
|
3954
|
+
let hasTechDiscount = false;
|
|
3955
|
+
if (isAlliance) {
|
|
3956
|
+
const [techData] = await ctx.database.get("ggcevo_tech", { handle, techId: 2 }).catch(() => [{ level: 0 }]);
|
|
3957
|
+
const weaponTechConfig = Spacestationtechnology.find((t) => t.techId === 2);
|
|
3958
|
+
techLevel = Math.min(techData?.level || 0, 5);
|
|
3959
|
+
const isCareerMatch = weaponTechConfig?.careerNames.includes(careerData?.career);
|
|
3960
|
+
const BASE_DISCOUNTS = [5, 10, 15, 20, 25];
|
|
3961
|
+
const CAREER_DISCOUNTS = [10, 20, 30, 40, 50];
|
|
3962
|
+
const baseDiscount = techLevel > 0 ? BASE_DISCOUNTS[techLevel - 1] : 0;
|
|
3963
|
+
const careerDiscount = isCareerMatch ? CAREER_DISCOUNTS[techLevel - 1] : 0;
|
|
3964
|
+
techDiscountRate = Math.max(baseDiscount, careerDiscount);
|
|
3965
|
+
hasTechDiscount = techDiscountRate > 0;
|
|
3966
|
+
}
|
|
3967
|
+
const foxBlessing = await checkFoxBlessing(ctx, handle);
|
|
3968
|
+
const foxDiscount = foxBlessing ? 20 : 0;
|
|
3969
|
+
const hasFoxDiscount = foxDiscount > 0;
|
|
3970
|
+
const gunslingerDiscount = isGunslinger ? 10 : 0;
|
|
3971
|
+
const hasGunslingerDiscount = isGunslinger;
|
|
3972
|
+
const BASE_COST = [1050, 1450, 1850, 2250, 2650, 3050, 3450];
|
|
3973
|
+
const maxLevel = isGunslinger ? 7 : 6;
|
|
3974
|
+
const priceDetails = [];
|
|
3975
|
+
for (let i = 0; i < maxLevel; i++) {
|
|
3976
|
+
const level = `${i}→${i + 1}`;
|
|
3977
|
+
let baseCost = BASE_COST[i];
|
|
3978
|
+
let finalPrice = baseCost;
|
|
3979
|
+
let discountsApplied = [];
|
|
3980
|
+
let totalDiscount = 0;
|
|
3981
|
+
if (isGunslinger) {
|
|
3982
|
+
totalDiscount += gunslingerDiscount;
|
|
3983
|
+
discountsApplied.push(`${gunslingerDiscount}% (枪手)`);
|
|
3984
|
+
}
|
|
3985
|
+
if (isAlliance && hasTechDiscount) {
|
|
3986
|
+
totalDiscount += techDiscountRate;
|
|
3987
|
+
discountsApplied.push(`${techDiscountRate}% (科技)`);
|
|
4037
3988
|
}
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
isolatedImmunityMark = carpetBombResult.tempMark || false;
|
|
4042
|
-
if (carpetBombResult.nerfMultiplier) {
|
|
4043
|
-
totalNerfMultiplier += carpetBombResult.nerfMultiplier;
|
|
3989
|
+
if (hasFoxDiscount) {
|
|
3990
|
+
totalDiscount += foxDiscount;
|
|
3991
|
+
discountsApplied.push(`${foxDiscount}% (灵狐)`);
|
|
4044
3992
|
}
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
// 单参数效果
|
|
4049
|
-
{ effect: BattleEffectProcessor.handleWeakForm, args: [targetBoss] },
|
|
4050
|
-
{ effect: BattleEffectProcessor.handleAlienShell, args: [targetBoss] },
|
|
4051
|
-
{ effect: BattleEffectProcessor.handleFrostHell, args: [targetBoss] },
|
|
4052
|
-
{ effect: BattleEffectProcessor.handleStressShellI, args: [targetBoss] },
|
|
4053
|
-
{ effect: BattleEffectProcessor.handleStressShellII, args: [targetBoss] },
|
|
4054
|
-
{ effect: BattleEffectProcessor.handleVirusCloud, args: [targetBoss] },
|
|
4055
|
-
{ effect: BattleEffectProcessor.handleEnergyBlackhole, args: [targetBoss] },
|
|
4056
|
-
{ effect: BattleEffectProcessor.handleColossalRampage, args: [targetBoss] },
|
|
4057
|
-
{ effect: BattleEffectProcessor.handleVomit, args: [targetBoss] },
|
|
4058
|
-
{ effect: BattleEffectProcessor.handleRampage, args: [targetBoss] },
|
|
4059
|
-
{ effect: BattleEffectProcessor.handleHyperRangeShift, args: [targetBoss] },
|
|
4060
|
-
// 双参数效果
|
|
4061
|
-
{ effect: BattleEffectProcessor.handleStructuralArmor, args: [targetBoss, weaponData] },
|
|
4062
|
-
{ effect: BattleEffectProcessor.handleDisguise, args: [targetBoss, weaponName] },
|
|
4063
|
-
// 多参数效果
|
|
4064
|
-
{ effect: BattleEffectProcessor.handleIsolated, args: [targetBoss, activeBosses, isolatedImmunityMark] },
|
|
4065
|
-
{ effect: BattleEffectProcessor.handleInfectedSpaceStation, args: [targetBoss, activeBosses] },
|
|
4066
|
-
{ effect: BattleEffectProcessor.handleInfernalBomb, args: [targetBoss, activeBosses] },
|
|
4067
|
-
{ effect: BattleEffectProcessor.handleHunterAlien, args: [targetBoss, activeBosses, weaponName] }
|
|
4068
|
-
];
|
|
4069
|
-
for (const effectItem of damageAdjustEffects) {
|
|
4070
|
-
const result = processEffect(effectItem.effect, ...effectItem.args);
|
|
4071
|
-
if (result) {
|
|
4072
|
-
if (result.buffMultiplier !== void 0) totalBuffMultiplier += result.buffMultiplier;
|
|
4073
|
-
if (result.nerfMultiplier !== void 0) totalNerfMultiplier += result.nerfMultiplier;
|
|
4074
|
-
bileDetonationTrigger ||= result.bileDetonationTrigger === true;
|
|
3993
|
+
if (totalDiscount > 0) {
|
|
3994
|
+
totalDiscount = Math.min(totalDiscount, 100);
|
|
3995
|
+
finalPrice = Math.floor(baseCost * (100 - totalDiscount) / 100);
|
|
4075
3996
|
}
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
if (
|
|
4081
|
-
|
|
3997
|
+
const showOriginal = finalPrice < baseCost;
|
|
3998
|
+
const levelInfo = `等级 ${level.padEnd(5)}`;
|
|
3999
|
+
const priceInfo = `▸ 价格: ${finalPrice.toString().padStart(4)}${showOriginal ? ` (原价${baseCost})` : ""}`;
|
|
4000
|
+
let discountDetail = "";
|
|
4001
|
+
if (discountsApplied.length > 0) {
|
|
4002
|
+
discountDetail = ` - 折扣总计: ${totalDiscount}% [${discountsApplied.join(", ")}]`;
|
|
4082
4003
|
}
|
|
4083
|
-
|
|
4004
|
+
priceDetails.push(`${levelInfo}
|
|
4005
|
+
${priceInfo}`);
|
|
4084
4006
|
}
|
|
4085
|
-
const
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
{ effect: BattleEffectProcessor.handleBladeOfLight, args: [targetBoss] },
|
|
4089
|
-
{ effect: BattleEffectProcessor.handleCollapsingPulse, args: [targetBoss] }
|
|
4090
|
-
];
|
|
4091
|
-
for (const effectItem of layerDependentEffects) {
|
|
4092
|
-
const result = processEffect(effectItem.effect, ...effectItem.args);
|
|
4093
|
-
if (result) {
|
|
4094
|
-
if (result.buffMultiplier !== void 0) totalBuffMultiplier += result.buffMultiplier;
|
|
4095
|
-
if (result.nerfMultiplier !== void 0) totalNerfMultiplier += result.nerfMultiplier;
|
|
4096
|
-
}
|
|
4007
|
+
const discountNotice = [];
|
|
4008
|
+
if (hasTechDiscount || hasFoxDiscount || hasGunslingerDiscount) {
|
|
4009
|
+
discountNotice.push("💰 当前折扣:");
|
|
4097
4010
|
}
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
];
|
|
4101
|
-
for (const effectItem of stateChangeEffects) {
|
|
4102
|
-
processEffect(effectItem.effect, ...effectItem.args);
|
|
4011
|
+
if (isGunslinger) {
|
|
4012
|
+
discountNotice.push(`▸ 🔫 枪手职业:10%折扣`);
|
|
4103
4013
|
}
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
{ effect: BattleEffectProcessor.handleFrostAura, args: [targetBoss, activeBosses] },
|
|
4107
|
-
{ effect: BattleEffectProcessor.handleSentryGun, args: [targetBoss, activeBosses] },
|
|
4108
|
-
{ effect: BattleEffectProcessor.handleMoldGrowth, args: [targetBoss, activeBosses] },
|
|
4109
|
-
{ effect: BattleEffectProcessor.handleElectricShockwave, args: [targetBoss] },
|
|
4110
|
-
{ effect: BattleEffectProcessor.handlePulse, args: [targetBoss, activeBosses] },
|
|
4111
|
-
{ effect: BattleEffectProcessor.handleFeeding, args: [targetBoss] },
|
|
4112
|
-
{ effect: BattleEffectProcessor.handleBurningBurrow, args: [targetBoss] },
|
|
4113
|
-
{ effect: BattleEffectProcessor.handleBombardmentGuide, args: [targetBoss] },
|
|
4114
|
-
{ effect: BattleEffectProcessor.handleOverdriveShield, args: [targetBoss, activeBosses] }
|
|
4115
|
-
];
|
|
4116
|
-
for (const effectItem of healingEffects) {
|
|
4117
|
-
processEffect(effectItem.effect, ...effectItem.args);
|
|
4014
|
+
if (isAlliance && hasTechDiscount) {
|
|
4015
|
+
discountNotice.push(`▸ ⚙️ 武器系统Lv.${techLevel}:${techDiscountRate}%折扣`);
|
|
4118
4016
|
}
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4017
|
+
if (hasFoxDiscount) {
|
|
4018
|
+
discountNotice.push(`▸ 🦊 灵狐升运祈愿:20%折扣`);
|
|
4019
|
+
}
|
|
4020
|
+
if (!hasTechDiscount && !hasFoxDiscount && !hasGunslingerDiscount) {
|
|
4021
|
+
if (isAlliance) {
|
|
4022
|
+
discountNotice.push("💡 提示:升级武器系统科技可获得折扣");
|
|
4023
|
+
} else if (careerData?.group === "辛迪加海盗") {
|
|
4024
|
+
discountNotice.push("💡 提示:转职为枪手职业可获得折扣");
|
|
4025
|
+
} else {
|
|
4026
|
+
discountNotice.push("💡 提示:加入人类联盟或辛迪加海盗可获得折扣");
|
|
4124
4027
|
}
|
|
4125
|
-
bileDetonationTrigger = burningSlimeResult.isHighStackHeal || false;
|
|
4126
4028
|
}
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
{ effect: BattleEffectProcessor.handleFlameBreath, args: [targetBoss, activeBosses] }
|
|
4130
|
-
];
|
|
4131
|
-
for (const effectItem of bileEffects) {
|
|
4132
|
-
processEffect(effectItem.effect, ...effectItem.args);
|
|
4029
|
+
if (isGunslinger) {
|
|
4030
|
+
discountNotice.push("▸ 🔝 枪手职业:武器等级上限提升至7级");
|
|
4133
4031
|
}
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4032
|
+
return [
|
|
4033
|
+
"⚡ 武器升级价格表 ⚡",
|
|
4034
|
+
`武器等级上限: ${maxLevel}级${isGunslinger ? " (枪手职业)" : ""}`,
|
|
4035
|
+
"使用「升级 武器名称」对武器进行等级升级",
|
|
4036
|
+
...discountNotice,
|
|
4037
|
+
"====================",
|
|
4038
|
+
...priceDetails,
|
|
4039
|
+
"===================="
|
|
4040
|
+
].join("\n");
|
|
4041
|
+
}
|
|
4042
|
+
__name(generateUpgradePriceList, "generateUpgradePriceList");
|
|
4043
|
+
async function getRankInfo(ctx, config, handle) {
|
|
4044
|
+
const [user] = await ctx.database.get("ggcevo_rank", {
|
|
4045
|
+
handle,
|
|
4046
|
+
rankseason: config.rankseason
|
|
4047
|
+
});
|
|
4048
|
+
if (!user) return "暂未找到排名信息。";
|
|
4049
|
+
if (user.Blacklist) return "❌ 该用户已被禁止参加本赛季胜点榜。";
|
|
4050
|
+
const allRanks = await ctx.database.select("ggcevo_rank").where({ Blacklist: false, rankseason: config.rankseason }).orderBy("rank", "desc").execute();
|
|
4051
|
+
const userRank = allRanks.findIndex((u) => u.handle === handle) + 1;
|
|
4052
|
+
const isSafe = await checkSensitiveWord(ctx, user.name);
|
|
4053
|
+
const displayName = isSafe ? user.name : (user.name[0] || "") + "***";
|
|
4054
|
+
return `🎮 咕咕排名信息 🎮
|
|
4055
|
+
------------------------------
|
|
4056
|
+
昵称:${displayName}
|
|
4057
|
+
句柄:${user.handle}
|
|
4058
|
+
当前积分:${user.rank}
|
|
4059
|
+
参赛次数:${user.matches} 次
|
|
4060
|
+
胜率:${user.matches === 0 ? "0.00%" : (user.wins / user.matches * 100).toFixed(2) + "%"}
|
|
4061
|
+
全服排名:第 ${userRank} 名
|
|
4062
|
+
------------------------------`;
|
|
4063
|
+
}
|
|
4064
|
+
__name(getRankInfo, "getRankInfo");
|
|
4065
|
+
function isWithinProtection(protections) {
|
|
4066
|
+
const now = /* @__PURE__ */ new Date();
|
|
4067
|
+
return protections.some(
|
|
4068
|
+
(p) => p.status === "active" && now >= p.startTime && now <= p.endTime
|
|
4138
4069
|
);
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
}
|
|
4147
|
-
|
|
4148
|
-
|
|
4070
|
+
}
|
|
4071
|
+
__name(isWithinProtection, "isWithinProtection");
|
|
4072
|
+
function formatTime(date) {
|
|
4073
|
+
return date.toLocaleString("zh-CN", {
|
|
4074
|
+
year: "numeric",
|
|
4075
|
+
month: "2-digit",
|
|
4076
|
+
day: "2-digit"
|
|
4077
|
+
});
|
|
4078
|
+
}
|
|
4079
|
+
__name(formatTime, "formatTime");
|
|
4080
|
+
|
|
4081
|
+
// src/boss/damagecalculation.ts
|
|
4082
|
+
async function calculateTotalDamage(ctx, session, config, equippedWeapon, targetBoss) {
|
|
4083
|
+
let effectMessage = [];
|
|
4084
|
+
const finalTags = targetBoss.tags || [];
|
|
4085
|
+
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
4086
|
+
const { regionId, realmId, profileId } = profile;
|
|
4087
|
+
const handle = `${regionId}-S2-${realmId}-${profileId}`;
|
|
4088
|
+
const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
|
|
4089
|
+
const [weaponName, weaponData] = weaponConfigEntry;
|
|
4090
|
+
const baseDamage = weaponData.damage * (1 + 0.1 * equippedWeapon.level);
|
|
4091
|
+
const levelBonusPercent = (0.1 * equippedWeapon.level * 100).toFixed(0);
|
|
4092
|
+
effectMessage.push(`🔫 ${weaponName}Lv.${equippedWeapon.level}:基础伤害+${levelBonusPercent}%`);
|
|
4093
|
+
let totalAdditive = 0;
|
|
4094
|
+
const tagAdditive = await calculateTagMultiplier(weaponData, finalTags, equippedWeapon);
|
|
4095
|
+
totalAdditive += tagAdditive;
|
|
4096
|
+
const { totalModAdd, hasCrit, modMessages } = calculateModifiers(
|
|
4097
|
+
equippedWeapon,
|
|
4098
|
+
weaponName,
|
|
4099
|
+
await checkCritRhythm(ctx, handle)
|
|
4149
4100
|
);
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4101
|
+
totalAdditive += totalModAdd;
|
|
4102
|
+
effectMessage.push(...modMessages);
|
|
4103
|
+
const careerBonus = await calculateCareerAdditive(ctx, handle, weaponData.type, weaponData.id);
|
|
4104
|
+
totalAdditive += careerBonus.value;
|
|
4105
|
+
if (careerBonus.message) effectMessage.push(careerBonus.message);
|
|
4106
|
+
const wishAdditive = await calculateWishAdditive(ctx, handle, equippedWeapon);
|
|
4107
|
+
totalAdditive += wishAdditive.value;
|
|
4108
|
+
if (wishAdditive.message) effectMessage.push(wishAdditive.message);
|
|
4109
|
+
const [rankRecord] = await ctx.database.get("ggcevo_rank", { handle, rankseason: config.rankseason });
|
|
4110
|
+
const rankAddResult = calculateRankAdditive(rankRecord);
|
|
4111
|
+
totalAdditive += rankAddResult.value;
|
|
4112
|
+
if (rankAddResult.message) {
|
|
4113
|
+
effectMessage.push(rankAddResult.message);
|
|
4114
|
+
}
|
|
4115
|
+
let finalDamage = baseDamage * (1 + totalAdditive);
|
|
4116
|
+
if (finalDamage < 1) {
|
|
4117
|
+
finalDamage = 1;
|
|
4118
|
+
}
|
|
4119
|
+
return {
|
|
4120
|
+
damage: Math.round(finalDamage),
|
|
4121
|
+
hasCrit,
|
|
4122
|
+
effectMessage
|
|
4123
|
+
};
|
|
4124
|
+
}
|
|
4125
|
+
__name(calculateTotalDamage, "calculateTotalDamage");
|
|
4126
|
+
async function checkCritRhythm(ctx, handle) {
|
|
4127
|
+
const [record] = await ctx.database.get("ggcevo_wish", {
|
|
4128
|
+
handle,
|
|
4129
|
+
wishname: "暴击韵律",
|
|
4130
|
+
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
4131
|
+
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
4132
|
+
});
|
|
4133
|
+
return !!record;
|
|
4134
|
+
}
|
|
4135
|
+
__name(checkCritRhythm, "checkCritRhythm");
|
|
4136
|
+
async function calculateTagMultiplier(weaponData, tags, equippedWeapon) {
|
|
4137
|
+
const MOD_EFFECTS = [
|
|
4138
|
+
{ mod: "裂甲核心", tag: "重甲", value: 1.5 },
|
|
4139
|
+
{ mod: "助燃核心", tag: "惧热", value: 3 },
|
|
4140
|
+
{ mod: "助燃核心", tag: "生物", value: 2 },
|
|
4141
|
+
{ mod: "金刚石瞄准镜", tag: "重甲", value: 0.8 },
|
|
4142
|
+
{ mod: "护盾崩解核心", tag: "护盾", value: 0.8 }
|
|
4143
|
+
];
|
|
4144
|
+
let totalAdditive = 0;
|
|
4145
|
+
for (const tag of tags) {
|
|
4146
|
+
const activeMod = MOD_EFFECTS.find(
|
|
4147
|
+
(me) => me.tag === tag && equippedWeapon.installedMods?.includes(me.mod)
|
|
4148
|
+
);
|
|
4149
|
+
const effectValue = activeMod ? activeMod.value : weaponData.tagEffects?.[tag] ?? 1;
|
|
4150
|
+
totalAdditive += effectValue - 1;
|
|
4151
|
+
}
|
|
4152
|
+
return totalAdditive;
|
|
4153
|
+
}
|
|
4154
|
+
__name(calculateTagMultiplier, "calculateTagMultiplier");
|
|
4155
|
+
function calculateModifiers(equippedWeapon, weaponName, hasCritRhythm) {
|
|
4156
|
+
let totalModAdd = 0;
|
|
4157
|
+
let hasCrit = false;
|
|
4158
|
+
const modMessages = [];
|
|
4159
|
+
let crystalCrit = 0;
|
|
4160
|
+
let overloadCrit = 0;
|
|
4161
|
+
let rhythmCrit = 0;
|
|
4162
|
+
let weaponCrit = 0;
|
|
4163
|
+
if (weaponName === "MK-4激光步枪") {
|
|
4164
|
+
weaponCrit = 80;
|
|
4165
|
+
modMessages.push(`🔫 【MK-4激光步枪】武器效果:暴击率+${weaponCrit}%`);
|
|
4155
4166
|
}
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
totalBuffMultiplier += radiationResult.buffMultiplier;
|
|
4167
|
+
equippedWeapon.installedMods.forEach((mod) => {
|
|
4168
|
+
if (mod === "动能增幅") {
|
|
4169
|
+
totalModAdd += 0.2;
|
|
4170
|
+
modMessages.push(`🛠️ 【动能增幅】生效:攻击伤害+20%`);
|
|
4161
4171
|
}
|
|
4162
|
-
if (
|
|
4163
|
-
|
|
4172
|
+
if (mod === "裂甲核心" && weaponName === modConfig[mod].exclusiveTo) {
|
|
4173
|
+
totalModAdd += 0.4;
|
|
4174
|
+
modMessages.push(`🛠️ 【裂甲核心】生效:攻击伤害+40%`);
|
|
4164
4175
|
}
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
if (coldResult) {
|
|
4169
|
-
messages.push(...coldResult.messages);
|
|
4170
|
-
if (coldResult.buffMultiplier) {
|
|
4171
|
-
totalBuffMultiplier += coldResult.buffMultiplier;
|
|
4176
|
+
if (mod === "棱镜水晶") {
|
|
4177
|
+
crystalCrit = 20;
|
|
4178
|
+
modMessages.push(`🛠️ 【棱镜水晶】生效:暴击率+20%`);
|
|
4172
4179
|
}
|
|
4173
|
-
if (
|
|
4174
|
-
|
|
4180
|
+
if (mod === "棱镜超载核心" && weaponName === modConfig[mod].exclusiveTo) {
|
|
4181
|
+
overloadCrit = 80;
|
|
4182
|
+
modMessages.push(`🛠️ 【棱镜超载核心】生效:暴击率+80%`);
|
|
4175
4183
|
}
|
|
4176
|
-
|
|
4184
|
+
});
|
|
4185
|
+
rhythmCrit = hasCritRhythm ? 20 : 0;
|
|
4186
|
+
if (hasCritRhythm) {
|
|
4187
|
+
modMessages.push(`🎵 暴击韵律祈愿:暴击率+20%`);
|
|
4177
4188
|
}
|
|
4178
|
-
const
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
energyDrained = energyDrainResult.success || false;
|
|
4189
|
+
const totalCritRate = Math.min(
|
|
4190
|
+
crystalCrit + overloadCrit + rhythmCrit + weaponCrit,
|
|
4191
|
+
// 包含武器专属暴击
|
|
4192
|
+
100
|
|
4193
|
+
);
|
|
4194
|
+
if (totalCritRate > 0) {
|
|
4185
4195
|
}
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4196
|
+
if (totalCritRate > 0) {
|
|
4197
|
+
const roll = Math.random() * 100;
|
|
4198
|
+
if (roll <= totalCritRate) {
|
|
4199
|
+
hasCrit = true;
|
|
4200
|
+
totalModAdd += 1;
|
|
4191
4201
|
}
|
|
4192
|
-
layerReduced = layerReduceResult.reductionSuccess || false;
|
|
4193
4202
|
}
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
);
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
if (frostEvolutionResult.isImmune) {
|
|
4210
|
-
immune = true;
|
|
4211
|
-
finalDamage = 0;
|
|
4212
|
-
}
|
|
4203
|
+
return {
|
|
4204
|
+
totalModAdd,
|
|
4205
|
+
hasCrit,
|
|
4206
|
+
modMessages
|
|
4207
|
+
// 返回模块消息数组
|
|
4208
|
+
};
|
|
4209
|
+
}
|
|
4210
|
+
__name(calculateModifiers, "calculateModifiers");
|
|
4211
|
+
async function calculateCareerAdditive(ctx, handle, weaponType, weaponId) {
|
|
4212
|
+
const [careerData] = await ctx.database.get("ggcevo_careers", { handle });
|
|
4213
|
+
let value = 0;
|
|
4214
|
+
let message = "";
|
|
4215
|
+
if (careerData?.career === "警卫长") {
|
|
4216
|
+
value += 0.05;
|
|
4217
|
+
message = "⚔️ 警卫长职业:攻击伤害+5%";
|
|
4213
4218
|
}
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
if (flameAlienResult.targetUpdates) {
|
|
4223
|
-
updateStatsByName(flameAlienResult.targetUpdates.name, flameAlienResult.targetUpdates.updates);
|
|
4219
|
+
if (careerData?.career === "武器中士") {
|
|
4220
|
+
value += 0.15;
|
|
4221
|
+
message = "⚔️ 武器中士职业:攻击伤害+15%";
|
|
4222
|
+
}
|
|
4223
|
+
if (careerData?.career === "能量武器专家") {
|
|
4224
|
+
if (weaponType === "能量武器") {
|
|
4225
|
+
value += 0.2;
|
|
4226
|
+
message = "⚔️ 能量武器专家职业:能量武器攻击伤害+20%";
|
|
4224
4227
|
}
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
+
}
|
|
4229
|
+
if (careerData?.career === "纵火狂") {
|
|
4230
|
+
if (weaponType === "热能武器") {
|
|
4231
|
+
value += 0.2;
|
|
4232
|
+
message = "⚔️ 纵火狂职业:热能武器攻击伤害+20%";
|
|
4228
4233
|
}
|
|
4229
4234
|
}
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
);
|
|
4235
|
-
if (cosmicEnergyResult) {
|
|
4236
|
-
messages.push(...cosmicEnergyResult.messages);
|
|
4237
|
-
if (cosmicEnergyResult.targetUpdates) {
|
|
4238
|
-
updateStatsByName(cosmicEnergyResult.targetUpdates.name, cosmicEnergyResult.targetUpdates.updates);
|
|
4235
|
+
if (careerData?.career === "猩红杀手") {
|
|
4236
|
+
if (weaponId === 7) {
|
|
4237
|
+
value += 0.15;
|
|
4238
|
+
message = "⚔️ 猩红杀手职业:侦察步枪攻击伤害+15%";
|
|
4239
4239
|
}
|
|
4240
4240
|
}
|
|
4241
|
-
|
|
4242
|
-
|
|
4241
|
+
return { value, message };
|
|
4242
|
+
}
|
|
4243
|
+
__name(calculateCareerAdditive, "calculateCareerAdditive");
|
|
4244
|
+
async function calculateWishAdditive(ctx, handle, weapon) {
|
|
4245
|
+
let value = 0;
|
|
4246
|
+
const messages = [];
|
|
4247
|
+
const [sovereign] = await ctx.database.get("ggcevo_wish", {
|
|
4248
|
+
handle,
|
|
4249
|
+
wishname: "王权增幅",
|
|
4250
|
+
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
4251
|
+
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
4252
|
+
});
|
|
4253
|
+
if (sovereign) {
|
|
4254
|
+
value += 0.1;
|
|
4255
|
+
messages.push("👑 王权增幅祈愿:攻击伤害+10%");
|
|
4243
4256
|
}
|
|
4244
|
-
const
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
{
|
|
4248
|
-
{
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
const result = skill.func(targetBoss, finalDamage);
|
|
4255
|
-
if (result) {
|
|
4256
|
-
updateStatsByName(result.targetUpdates.name, result.targetUpdates.updates);
|
|
4257
|
-
messages.push(...result.messages);
|
|
4258
|
-
revivalTriggered = true;
|
|
4259
|
-
break;
|
|
4260
|
-
}
|
|
4261
|
-
}
|
|
4262
|
-
}
|
|
4257
|
+
const [lament] = await ctx.database.get("ggcevo_wish", {
|
|
4258
|
+
handle,
|
|
4259
|
+
wishname: "悲鸣之锋",
|
|
4260
|
+
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
4261
|
+
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
4262
|
+
});
|
|
4263
|
+
if (lament) {
|
|
4264
|
+
const levelBonus = 0.1 * (weapon.level + 1);
|
|
4265
|
+
value += levelBonus;
|
|
4266
|
+
messages.push(`🗡️ 悲鸣之锋祈愿:攻击伤害+${Math.round(levelBonus * 100)}%`);
|
|
4263
4267
|
}
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
}
|
|
4268
|
+
const [critRhythm] = await ctx.database.get("ggcevo_wish", {
|
|
4269
|
+
handle,
|
|
4270
|
+
wishname: "暴击韵律",
|
|
4271
|
+
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
4272
|
+
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
4273
|
+
});
|
|
4274
|
+
if (critRhythm) {
|
|
4275
|
+
messages.push("🎵 暴击韵律祈愿:攻击暴击率+20%");
|
|
4268
4276
|
}
|
|
4269
4277
|
return {
|
|
4270
|
-
|
|
4271
|
-
messages
|
|
4272
|
-
radiationLayerAdded,
|
|
4273
|
-
coldLayerAdded,
|
|
4274
|
-
energyDrained,
|
|
4275
|
-
layerReduced,
|
|
4276
|
-
bileDetonationTrigger
|
|
4278
|
+
value,
|
|
4279
|
+
message: messages.join(",")
|
|
4277
4280
|
};
|
|
4278
4281
|
}
|
|
4279
|
-
__name(
|
|
4282
|
+
__name(calculateWishAdditive, "calculateWishAdditive");
|
|
4283
|
+
function calculateRankAdditive(rankRecord) {
|
|
4284
|
+
if (!rankRecord || rankRecord.rank <= 0) return { value: 0, message: "" };
|
|
4285
|
+
const baseValue = Math.floor(rankRecord.rank / 300) * 0.01;
|
|
4286
|
+
const cappedValue = Math.min(baseValue, 1);
|
|
4287
|
+
if (cappedValue > 0) {
|
|
4288
|
+
const percentage = Math.round(cappedValue * 100);
|
|
4289
|
+
return {
|
|
4290
|
+
value: cappedValue,
|
|
4291
|
+
message: `🏆 胜点榜积分加成:攻击伤害+${percentage}%`
|
|
4292
|
+
};
|
|
4293
|
+
}
|
|
4294
|
+
return { value: 0, message: "" };
|
|
4295
|
+
}
|
|
4296
|
+
__name(calculateRankAdditive, "calculateRankAdditive");
|
|
4280
4297
|
|
|
4281
4298
|
// src/boss/attackhandling.ts
|
|
4282
4299
|
async function getCleanerRewardBroadcast(ctx, boss, killerHandle, killerName) {
|
|
@@ -4815,6 +4832,20 @@ async function handleIgnoreReductionEffects(ctx, handle, weaponName, targetBoss)
|
|
|
4815
4832
|
};
|
|
4816
4833
|
}
|
|
4817
4834
|
__name(handleIgnoreReductionEffects, "handleIgnoreReductionEffects");
|
|
4835
|
+
async function testAttackFunction(ctx, session, handle, config, equippedWeapon, targetBoss, activeBosses, weaponName) {
|
|
4836
|
+
const damageResult = await calculateTotalDamage(ctx, session, config, equippedWeapon, targetBoss);
|
|
4837
|
+
const ignoreReduction = await handleIgnoreReductionEffects(ctx, handle, weaponName, targetBoss);
|
|
4838
|
+
const EffectProcessor = applyPassiveEffects(targetBoss, activeBosses, weaponName, damageResult.damage, ignoreReduction.ignoreRate);
|
|
4839
|
+
const initialDamage = EffectProcessor.finalDamage;
|
|
4840
|
+
return {
|
|
4841
|
+
initialDamage,
|
|
4842
|
+
hasCrit: damageResult.hasCrit,
|
|
4843
|
+
effectMessage: damageResult.effectMessage,
|
|
4844
|
+
passiveMessages: EffectProcessor.messages,
|
|
4845
|
+
ignoreMessage: ignoreReduction.messages
|
|
4846
|
+
};
|
|
4847
|
+
}
|
|
4848
|
+
__name(testAttackFunction, "testAttackFunction");
|
|
4818
4849
|
|
|
4819
4850
|
// src/index.ts
|
|
4820
4851
|
var name = "ggcevo-game";
|
|
@@ -7470,11 +7501,25 @@ ${validTypes.join("、")}`;
|
|
|
7470
7501
|
cleanerRewardBroadcast
|
|
7471
7502
|
);
|
|
7472
7503
|
});
|
|
7473
|
-
ctx.command("ggcevo/攻击假人").option("tags", "-t <tags:string> 添加BOSS标签(逗号分隔)").action(async (argv) => {
|
|
7504
|
+
ctx.command("ggcevo/攻击假人").option("tags", "-t <tags:string> 添加BOSS标签(逗号分隔)").option("passives", "-p <passives:string> 添加被动技能(逗号分隔)").option("hp", "-l <hp:number> 模拟假人血量").option("energy", "-e <energy:number> 模拟假人能量").option("skillStacks", "-s <stacks:number> 技能层数").option("radiation", "-r <rad:number> 辐射层数").option("cold", "-c <cold:number> 寒冷层数").option("status", "-a <status:number> 状态层数").action(async (argv) => {
|
|
7474
7505
|
const session = argv.session;
|
|
7475
7506
|
const { options } = argv;
|
|
7507
|
+
let hp = 1e4;
|
|
7508
|
+
if (typeof options.hp === "number") {
|
|
7509
|
+
hp = Math.max(1, Math.min(options.hp, 1e4));
|
|
7510
|
+
}
|
|
7511
|
+
let energy = 1e3;
|
|
7512
|
+
if (typeof options.energy === "number") {
|
|
7513
|
+
energy = Math.max(0, Math.min(options.energy, 1e3));
|
|
7514
|
+
}
|
|
7515
|
+
const clampLayer = /* @__PURE__ */ __name((value, max = 100) => typeof value === "number" ? Math.max(0, Math.min(value, max)) : 0, "clampLayer");
|
|
7516
|
+
const skillStacks = clampLayer(options.skillStacks);
|
|
7517
|
+
const radiationLayers = clampLayer(options.radiation);
|
|
7518
|
+
const coldLayers = clampLayer(options.cold);
|
|
7519
|
+
const statusLayers = clampLayer(options.status);
|
|
7476
7520
|
const parseList = /* @__PURE__ */ __name((str) => str ? str.split(",").map((s) => s.trim()).filter(Boolean) : [], "parseList");
|
|
7477
7521
|
const tags = parseList(options.tags);
|
|
7522
|
+
const passives = parseList(options.passives);
|
|
7478
7523
|
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
7479
7524
|
if (!profile) return "🔒 需要先绑定游戏句柄。";
|
|
7480
7525
|
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
@@ -7487,38 +7532,71 @@ ${validTypes.join("、")}`;
|
|
|
7487
7532
|
if (!equippedWeapon) return '请先输入"装备 武器名称"后再测试。';
|
|
7488
7533
|
const dummyBoss = {
|
|
7489
7534
|
name: "测试假人",
|
|
7490
|
-
HP:
|
|
7535
|
+
HP: hp,
|
|
7491
7536
|
type: "主宰",
|
|
7492
7537
|
groupId: 0,
|
|
7493
|
-
tags: tags || []
|
|
7494
|
-
|
|
7538
|
+
tags: tags || [],
|
|
7539
|
+
skills: passives || [],
|
|
7540
|
+
skillStacks,
|
|
7541
|
+
// 使用自定义技能层数
|
|
7542
|
+
radiationLayers,
|
|
7543
|
+
// 使用自定义辐射层数
|
|
7544
|
+
coldLayers,
|
|
7545
|
+
// 使用自定义寒冷层数
|
|
7546
|
+
energy,
|
|
7547
|
+
isActive: true,
|
|
7548
|
+
statusLayers,
|
|
7549
|
+
// 使用自定义状态层数
|
|
7550
|
+
lastWeaponName: ""
|
|
7495
7551
|
};
|
|
7496
|
-
const
|
|
7497
|
-
ctx,
|
|
7498
|
-
session,
|
|
7499
|
-
config,
|
|
7500
|
-
equippedWeapon,
|
|
7501
|
-
dummyBoss,
|
|
7502
|
-
{
|
|
7503
|
-
isTest: true,
|
|
7504
|
-
// 标记为测试模式
|
|
7505
|
-
customTags: tags
|
|
7506
|
-
}
|
|
7507
|
-
);
|
|
7552
|
+
const activeBosses = [dummyBoss];
|
|
7508
7553
|
const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
|
|
7509
7554
|
const [weaponName] = weaponConfigEntry;
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7555
|
+
try {
|
|
7556
|
+
const testResult = await testAttackFunction(
|
|
7557
|
+
ctx,
|
|
7558
|
+
session,
|
|
7559
|
+
handle,
|
|
7560
|
+
config,
|
|
7561
|
+
equippedWeapon,
|
|
7562
|
+
dummyBoss,
|
|
7563
|
+
activeBosses,
|
|
7564
|
+
weaponName
|
|
7565
|
+
);
|
|
7566
|
+
const layerInfo = [];
|
|
7567
|
+
if (skillStacks > 0) layerInfo.push(`技能层数: ${skillStacks}`);
|
|
7568
|
+
if (radiationLayers > 0) layerInfo.push(`辐射层数: ${radiationLayers}`);
|
|
7569
|
+
if (coldLayers > 0) layerInfo.push(`寒冷层数: ${coldLayers}`);
|
|
7570
|
+
if (statusLayers > 0) layerInfo.push(`状态层数: ${statusLayers}`);
|
|
7571
|
+
const layerDisplay = layerInfo.length > 0 ? `📊 层数状态: ${layerInfo.join(" | ")}` : "";
|
|
7572
|
+
return [
|
|
7573
|
+
`🎯 使用武器 ${weaponName} 攻击 ${dummyBoss.name}`,
|
|
7574
|
+
`❤️ 假人血量:${dummyBoss.HP}`,
|
|
7575
|
+
`⚡ 假人能量:${dummyBoss.energy}`,
|
|
7576
|
+
options.tags?.length && `🏷️ 模拟标签:${tags.join(", ")}`,
|
|
7577
|
+
options.passives?.length && `✨ 模拟被动:${passives.join(", ")}`,
|
|
7578
|
+
layerDisplay,
|
|
7579
|
+
// 添加层数显示
|
|
7580
|
+
...testResult.effectMessage.length > 0 ? [
|
|
7581
|
+
`⚡ 攻击效果:
|
|
7582
|
+
${testResult.effectMessage.map((m) => `▸ ${m}`).join("\n")}`
|
|
7583
|
+
] : [],
|
|
7584
|
+
...testResult.ignoreMessage.length > 0 ? [
|
|
7585
|
+
`🗡️ 无视减伤效果:
|
|
7586
|
+
${testResult.ignoreMessage.map((m) => `▸ ${m}`).join("\n")}`
|
|
7587
|
+
] : [],
|
|
7588
|
+
...testResult.passiveMessages.length > 0 ? [
|
|
7589
|
+
`🛡️ 被动效果:
|
|
7590
|
+
${testResult.passiveMessages.map((m) => `▸ ${m}`).join("\n")}`
|
|
7591
|
+
] : [],
|
|
7592
|
+
`📊 理论伤害值:${testResult.initialDamage}${testResult.hasCrit ? "(✨ 暴击)" : ""}`,
|
|
7593
|
+
"💡 提示:可添加标签(-t)、被动(-p)、血量(-l)、能量(-e)",
|
|
7594
|
+
"💡 层数选项:技能层数(-s)、辐射层数(-r)、寒冷层数(-c)、状态层数(-a)",
|
|
7595
|
+
`ℹ️ 测试假人最大血量:10000 | 最大能量:1000 | 最大层数:100`
|
|
7596
|
+
].filter((line) => line).join("\n");
|
|
7597
|
+
} finally {
|
|
7598
|
+
Object.keys("测试假人").forEach((key) => delete battleStatsMap[key]);
|
|
7599
|
+
}
|
|
7522
7600
|
});
|
|
7523
7601
|
ctx.command("ggcevo/伤害榜 [page]", "查看当前主宰伤害排名").usage("输入 伤害榜 [页码] 查看对应页的排行榜,每页10条").action(async (_, page) => {
|
|
7524
7602
|
const pageNum = parseInt(page) || 1;
|