0.2.4-dev: round-29 community fixes and the official shared card pool
- Shared card pool and item stock as in the official mode (the owner's request, from the 路标档案馆 video and public notes): solo low-tier exceptions, co-op operators x2, shared item stock with special-item exceptions, normal / advanced occupancy 1 / 2, re-check on buy, 机变 exhaustion, release on consume / destroy / elimination; 整备 never exceeds stock; invariant held <= cap. - 突袭: one taunt-first reselect right after a revive (the owner's rule); ordinary polls and redeploys keep the 0.2.3 rule; a revive on an enemy's tile stays. #475: online boss / hidden-boss Raid may land on the empty half (owner-limited scope). - 浊心斯卡蒂 S1 x 坚守 no longer bounce redirected damage, and the two shares conserve the hit (idea of PR #464 by @HappyTanuki). - Operator fixes adapted from PRs by @Xinglan233 (#459 哈洛德 S2 elemental trigger, #460 涤火杰西卡 shield on the four adjacent tiles, #461 家族徽章 first hit after stealth, #462 松果 S2 regrow per deploy); 克莱门莎 S2 splash 1.1 / 100% ATK and air auto-trigger (#467); 白面 copying 歌蕾蒂娅 / 余 skips the three-member condition (#473, the owner's video). - 香槟炸弹 is not chosen by friendly auras / heals (PR #468 / #476 by @Siornya); 琳琅诗怀雅 coin balance (PR #450 by @IceCodeNew); Touch prep display (PR #451 by @YinqiMargatroid); lobby header (PR #471 by @YuriRestia); Japanese UI terms (PR #448 by @scutkane). - AI-only boss countdown grace, render-failure cache / recovery without restarting a battle, device units kept on a same-field re-entry, DIY detail / skill previews, large-text result buttons. - golden: battle families equal 0.2.3 except diy-135 / diy-136 (克莱门莎); all 18 release matches move through the shared pool, every flip named in docs/history/0.2.4.md §29.12; two coverage scenarios added.
This commit is contained in:
1 parent
1db8e51023
commit
6bfc08270c
129 files changed
+3477
-1011
No files matched your search
@@ -15,8 +15,10 @@ export default {
|
||||
const kit = {
|
||||
skill: {
|
||||
kind: 'duration',
|
||||
onStart({ battle, unit, skill }) {
|
||||
const atk = steps[Math.min(steps.length - 1, Math.max(0, skill.activations - 1))];
|
||||
onStart({ battle, unit }) {
|
||||
const uses = unit.mem.pinecnS2Uses ?? 0;
|
||||
unit.mem.pinecnS2Uses = uses + 1;
|
||||
const atk = steps[Math.min(steps.length - 1, uses)];
|
||||
battle.addBuff(unit, { key: 'skill:pinecn_atk', mods: { atkPct: atk } });
|
||||
},
|
||||
onEnd({ battle, unit }) { battle.removeBuff(unit, 'skill:pinecn_atk'); },
|
||||
@@ -33,7 +35,10 @@ export default {
|
||||
}),
|
||||
talents: [{ install(battle, unit) {
|
||||
battle.on('deploy', (ctx) => {
|
||||
if (ctx.unit === unit) battle.addBuff(unit, { key: 'talent:pinecn_power', duration: num(t0.duration, 60), mods: { spRecoveryFlat: num(t0.sp_recovery_per_sec) } });
|
||||
if (ctx.unit !== unit) return;
|
||||
// PRTS 松果: count skill uses since this deployment; the runtime's activation identity stays cumulative.
|
||||
unit.mem.pinecnS2Uses = 0;
|
||||
battle.addBuff(unit, { key: 'talent:pinecn_power', duration: num(t0.duration, 60), mods: { spRecoveryFlat: num(t0.sp_recovery_per_sec) } });
|
||||
}, { owner: unit });
|
||||
} }],
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Conventions of the tier-6 kits: ../shared/tier6.js; kit contract and rules: ../README.md.
|
||||
|
||||
import { aggregateMods } from '../../../buffs.js';
|
||||
import { applyRedirectCut, redirectShare } from '../../../damage.js';
|
||||
import { COLS } from '../../../constants.js';
|
||||
import { bardRegen } from '../../../professions.js';
|
||||
import { startCountdown } from '../../tokens.js';
|
||||
@@ -123,12 +124,15 @@ function skadi2(bb, chess, def) {
|
||||
if (!(share > 0) || !t || t === unit || t.side !== 'ally' || t.kind === 'device' || !live(unit) || !unit.skill?.active) return;
|
||||
if (d.type === 'element' || d.type === 'elemental' || d.skadiShare || d.tags?.includes('transfer') || !inCover(battle, unit, t)) return;
|
||||
d.skadiShare = { share, tag: TAG }; // 同类效果取最高: one transfer per damage instance
|
||||
d.mul *= 1 - share;
|
||||
applyRedirectCut(d, share); // her share of the pre-redirect hit; the victim keeps the rest
|
||||
}, { owner: unit, priority: -20 });
|
||||
battle.on('damaged', (ctx) => {
|
||||
const x = ctx.dmg?.skadiShare;
|
||||
if (!x || x.tag !== TAG || !(ctx.amount > 0) || !live(unit)) return;
|
||||
battle.dealDamage(ctx.source, unit, { amount: ctx.amount * x.share / Math.max(1e-6, 1 - x.share), type: 'true', canDodge: false, tags: ['transfer'] });
|
||||
// Keep the earlier 坚守 redirect's marker. Rebuilding damage without it lets the same two effects bounce
|
||||
// the hit forever; each existing sharing effect still gets its first application along this path.
|
||||
battle.dealDamage(ctx.source, unit, { amount: redirectShare(ctx.amount, x.share, ctx.dmg.redirectCuts), type: 'true', canDodge: false,
|
||||
tags: ['transfer', ...(ctx.dmg.tags?.includes('bond:stead:share') ? ['bond:stead:share'] : [])] });
|
||||
}, { owner: unit });
|
||||
}
|
||||
// module 新生代: "自身技能期间,攻击范围内的友军获得30点物理与法术伤害减免" (flat reduction per hit)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// 克莱门莎 (char_4231_clemnt), 本源近卫. Official CN tables 2026-10-08 (client 2.7.81),
|
||||
// PRTS 克莱门莎, 2026-10-09: all skills at ranks 4/7 and both potential-sensitive talents.
|
||||
// https://prts.wiki/w/克莱门莎 . No module was released with her.
|
||||
// PRTS still marks several launch-day details unknown: [ASSUMED] S2's ordinary splash radius 1.5;
|
||||
// carriage's unresolved 放逐 combination = cannot walk/attack/be blocked, but remains damageable;
|
||||
// PRTS still marks several launch-day details unknown: [ASSUMED] carriage's unresolved 放逐 combination =
|
||||
// cannot walk/attack/be blocked, but remains damageable;
|
||||
// its boundary clearance 0.4, carriage updates once per sim tick, vortex ends with the skill;
|
||||
// S3 first bombardment at 0.5 s, then twice at 1 s intervals, launched shots survive skill end.
|
||||
// These pending confirmations are listed in DESIGN §28.1; keep each assumption local to this kit.
|
||||
|
||||
import { num, talentBb, skillRec, up } from '../shared/tier1.js';
|
||||
import { canTargetEnemy } from '../../../targeting.js';
|
||||
import { absoluteRangeKeys, canTargetEnemy } from '../../../targeting.js';
|
||||
import { bodyInKeys, hitRect } from '../../../body.js';
|
||||
import { dirVec } from '../../../dir.js';
|
||||
import { COLS } from '../../../constants.js';
|
||||
@@ -18,7 +18,7 @@ const S1 = 'skchr_clemnt_1', S2 = 'skchr_clemnt_2', S3 = 'skchr_clemnt_3';
|
||||
const GROUND = Object.freeze({ canHitFly: false, groundOnly: true });
|
||||
const AIR = Object.freeze({ canHitFly: true });
|
||||
const SPEED = 2, DISTANCE = 3, CATCH_HALF = 0.55, VORTEX_RADIUS = 1.5;
|
||||
const SPLASH_RADIUS = 1.5; // [ASSUMED] PRTS has not published S2's normal attack splash radius.
|
||||
const SPLASH_RADIUS = 1.1; // PRTS 2026-10-10: collision test; four secondary targets take 100% ATK.
|
||||
const FIRST_BOMB = 0.5; // [ASSUMED] Neither PRTS nor the edited official demo settles the first landing offset.
|
||||
const CAST = 'clemnt:cast', CARRY = 'clemnt:carry:';
|
||||
const skillBb = (raw, id) => skillRec(raw, id)?.bb ?? {};
|
||||
@@ -159,11 +159,11 @@ export default {
|
||||
if (kind !== 'main' || !target) return;
|
||||
// Main victim plus at most four neighbours, never every unit in the radius.
|
||||
// [ASSUMED] Ties among splash victims follow the engine's stable spawn order.
|
||||
const near = battle.foesInRadius(target.x, target.y, SPLASH_RADIUS, true)
|
||||
const near = battle.foesInRadius(target.x, target.y, SPLASH_RADIUS)
|
||||
.filter((e) => e !== target && canTargetEnemy(unit, e, GROUND))
|
||||
.slice(0, Math.max(0, num(b2['attack@max_target'], 5) - 1));
|
||||
for (const e of near) battle.dealDamage(unit, e, {
|
||||
amount: unit.s.atk * unit.s.atkScaleMul * num(b2['attack@aoe_atk_scale'], 1), type: 'phys',
|
||||
amount: unit.s.atk * unit.s.atkScaleMul, type: 'phys',
|
||||
isAttack: true, isSplash: true, isSkill: true, attackId, tags: ['skill', 'clemnt:splash'],
|
||||
});
|
||||
} },
|
||||
@@ -212,6 +212,15 @@ export default {
|
||||
} },
|
||||
],
|
||||
install(battle, unit) {
|
||||
if (unit.skill?.id === S2) {
|
||||
// Maintainer 2026-10-10 (#467): follow Chen S3 automation. The vortex hits air while normal attacks do not.
|
||||
// [ASSUMED] No mode footage establishes a separate auto-cast shape for this new operator; use the expanded
|
||||
// skill attack grid with permanent extensions, retaining shared operation cooldown/control checks.
|
||||
unit.skill.addTriggerRange(() => [{
|
||||
keys: absoluteRangeKeys(skillRec(raw, S2)?.rangeGrid, unit.tileR, unit.tileC, unit.dir, unit.s.baseRangeExtend || 0),
|
||||
profile: AIR,
|
||||
}]);
|
||||
}
|
||||
battle.on('elementBurst', ({ target, element }) => {
|
||||
if (element !== 'erosion' || !up(unit) || !unit.skill?.active || unit.skill.id !== S3
|
||||
|| !canTargetEnemy(unit, target, GROUND)) return;
|
||||
|
||||
Reference in new issue
Block a user