You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
AdLike2048/assets/script/battle/skill/BaseAtkParamReader.ts

156 lines
5.8 KiB

import { TableNames } from '../../game/ConfigTableData';
import type { SkillPresentationContext } from './SkillPresentationTypes';
export interface AtkTypeParts {
head: number;
param: number;
}
export interface WuSpinSkillParts {
secPerRev: number;
stickCount: number;
volumeCells: number;
durationSec: number;
damageScale: number;
}
export interface WheelSkillParts {
secPerRev: number;
count: number;
volume: number;
radiusPx: number;
damageScale: number;
}
export function parseAtkTypeString(raw: string): AtkTypeParts | null {
const t = String(raw ?? '').trim();
if (!t || t === '0') return null;
const parts = t.split(',').map(Number);
const head = parts[0];
if (!Number.isFinite(head)) return null;
const param = parts.length >= 2 && Number.isFinite(parts[1]) ? parts[1] : 0;
return { head, param };
}
export function readBaseAtkRow(baseAtkId: number): ITableSkill | null {
if (baseAtkId <= 0) return null;
return gg.data.table.getTableData<ITableSkill>(TableNames.Skill, baseAtkId) ?? null;
}
export function readAtkTypeParamFromBaseAtkId(
baseAtkId: number,
expectedHead?: number,
): number | null {
const row = readBaseAtkRow(baseAtkId);
if (!row) return null;
const parsed = parseAtkTypeString(row.atk_type);
if (!parsed) return null;
if (expectedHead != null && parsed.head !== expectedHead) return null;
return parsed.param > 0 ? parsed.param : null;
}
export function resolvePresentationAtkTypeParam(
ctx: Pick<SkillPresentationContext, 'params' | 'baseAtkId'>,
expectedHead?: number,
): number | null {
const fromParam = Number(ctx.params.atkTypeParam);
if (Number.isFinite(fromParam) && fromParam > 0) return fromParam;
return readAtkTypeParamFromBaseAtkId(ctx.baseAtkId, expectedHead);
}
export function requirePart(parts: readonly number[], index: number): number | null {
if (index < 0 || index >= parts.length) return null;
const v = Number(parts[index]);
return Number.isFinite(v) ? v : null;
}
export function requirePositivePart(parts: readonly number[], index: number): number | null {
const v = requirePart(parts, index);
return v != null && v > 0 ? v : null;
}
export function requireNonNegativePart(parts: readonly number[], index: number): number | null {
const v = requirePart(parts, index);
return v != null && v >= 0 ? v : null;
}
export function parseSkillParts(params: Readonly<Record<string, unknown>>): number[] | null {
const rawParts = params.skillParts as number[] | undefined;
if (rawParts?.length) return [...rawParts];
const raw = String(params.skillRaw ?? '').trim();
if (!raw) return null;
const parts = raw.split(',').map(Number);
return parts.some((n) => !Number.isFinite(n)) ? null : parts;
}
export function parseWuSpinSkillParts(parts: readonly number[]): WuSpinSkillParts | null {
if ((parts[0] ?? 0) !== 1 || parts.length < 5) return null;
const secPerRev = requirePositivePart(parts, 1);
const stickCountRaw = requirePart(parts, 2);
const volumeCells = requirePositivePart(parts, 3);
const durationSec = requirePositivePart(parts, 4);
if (secPerRev == null || stickCountRaw == null || volumeCells == null || durationSec == null) {
return null;
}
const stickCount = Math.floor(stickCountRaw);
if (stickCount < 1) return null;
const damageScale = parts.length >= 6
? requirePositivePart(parts, 5)
: requirePositivePart(parts, parts.length - 1);
if (damageScale == null) return null;
return { secPerRev, stickCount, volumeCells, durationSec, damageScale };
}
export function parseWheelSkillParts(parts: readonly number[]): WheelSkillParts | null {
if ((parts[0] ?? 0) !== 7 || parts.length < 6) return null;
const secPerRev = requirePositivePart(parts, 1);
const countRaw = requirePart(parts, 2);
const volume = requirePositivePart(parts, 3);
const radiusPx = requirePositivePart(parts, 4);
const damageScale = requirePositivePart(parts, 5);
if (secPerRev == null || countRaw == null || volume == null || radiusPx == null || damageScale == null) {
return null;
}
const count = Math.floor(countRaw);
if (count < 1) return null;
return { secPerRev, count, volume, radiusPx, damageScale };
}
export function parseSkill2RadiusParts(
parts: readonly number[],
rangeAdd = 0,
): { radiusPx: number; damageScale: number } | null {
if ((parts[0] ?? 0) !== 2 || parts.length < 3) return null;
const radiusBase = requirePositivePart(parts, 1);
const damageScale = requirePositivePart(parts, 2);
if (radiusBase == null || damageScale == null) return null;
return { radiusPx: radiusBase + rangeAdd, damageScale };
}
export function parseSkill5AreaParts(parts: readonly number[]): {
radiusPx: number;
scale: number;
intervalSec: number;
durationSec: number;
} | null {
if ((parts[0] ?? 0) !== 5 || parts.length < 5) return null;
const radiusPx = requirePositivePart(parts, 1);
const scale = requirePositivePart(parts, 2);
const intervalSec = requirePositivePart(parts, 3);
const durationSec = requirePositivePart(parts, 4);
if (radiusPx == null || scale == null || intervalSec == null || durationSec == null) return null;
return { radiusPx, scale, intervalSec, durationSec };
}
export function parseSkill6BeamParts(parts: readonly number[]): {
scale: number;
intervalSec: number;
durationSec: number;
} | null {
if ((parts[0] ?? 0) !== 6 || parts.length < 4) return null;
const scale = requirePositivePart(parts, 1);
const intervalSec = requirePositivePart(parts, 2);
const durationSec = requirePositivePart(parts, 3);
if (scale == null || intervalSec == null || durationSec == null) return null;
return { scale, intervalSec, durationSec };
}