mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-14 07:06:14 -05:00
Obj DMG Calc: special cases calculation data driven
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import type { DamageType } from "./types";
|
||||
import type objectDamages from "./object-dmg.json";
|
||||
import type { MainWeaponId } from "../in-game-lists";
|
||||
import { type MainWeaponId, mainWeaponIds } from "../in-game-lists";
|
||||
import invariant from "tiny-invariant";
|
||||
|
||||
export const MAX_LDE_INTENSITY = 21;
|
||||
export const MAX_AP = 57;
|
||||
@@ -169,6 +170,46 @@ export const objectDamageJsonKeyPriority: Record<
|
||||
UltraStamp_Throw: null,
|
||||
};
|
||||
|
||||
export const damageTypesToCombine: Partial<
|
||||
Record<
|
||||
MainWeaponId,
|
||||
Array<{
|
||||
when: DamageType;
|
||||
combineWith: DamageType;
|
||||
/** for this weapon "when" damage already includes "combineWith" damage, so calculating multiplier only */
|
||||
multiplierOnly?: boolean;
|
||||
}>
|
||||
>
|
||||
> = {
|
||||
// Splatana Stamper
|
||||
8000: [
|
||||
{ when: "SPLATANA_VERTICAL_DIRECT", combineWith: "SPLATANA_VERTICAL" },
|
||||
{
|
||||
when: "SPLATANA_HORIZONTAL_DIRECT",
|
||||
combineWith: "SPLATANA_HORIZONTAL",
|
||||
multiplierOnly: true,
|
||||
},
|
||||
],
|
||||
// Splatana Wiper
|
||||
8010: [
|
||||
{ when: "SPLATANA_VERTICAL_DIRECT", combineWith: "SPLATANA_VERTICAL" },
|
||||
{
|
||||
when: "SPLATANA_HORIZONTAL_DIRECT",
|
||||
combineWith: "SPLATANA_HORIZONTAL",
|
||||
multiplierOnly: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
invariant(
|
||||
mainWeaponIds.every((id) => {
|
||||
// not Splatana
|
||||
if (id < 8000 || id >= 9000) return true;
|
||||
|
||||
return Boolean(damageTypesToCombine[id]);
|
||||
}),
|
||||
"Splatana weapon missing from damageTypesToCombine"
|
||||
);
|
||||
|
||||
export const multiShot: Partial<Record<MainWeaponId, number>> = {
|
||||
// L-3
|
||||
300: 3,
|
||||
|
||||
@@ -11,6 +11,7 @@ import type {
|
||||
SubWeaponId,
|
||||
} from "../in-game-lists";
|
||||
import {
|
||||
damageTypesToCombine,
|
||||
damageTypeToWeaponType,
|
||||
DAMAGE_RECEIVERS,
|
||||
objectDamageJsonKeyPriority,
|
||||
@@ -114,21 +115,12 @@ export function calculateDamage({
|
||||
damageType: DamageType;
|
||||
isMultiShot: boolean;
|
||||
}) {
|
||||
const toCombine = (damageTypesToCombine[mainWeaponId] ?? []).find(
|
||||
(c) => c.when === damageType
|
||||
);
|
||||
|
||||
const filteredDamages = analyzed.stats.damages
|
||||
.filter(
|
||||
(d) =>
|
||||
d.type === damageType ||
|
||||
// Splatana direct seems to use two damage sources
|
||||
// The way Splatana damage works is a bit confusing:
|
||||
// Vertical Direct = Vertical + Vertical Direct damage vs. Objects only
|
||||
// Horizontal Direct = Horizontal + Horizontal Direct damage vs. both objects and players both
|
||||
// so that's why Horizontal Direct damage has these baked in while
|
||||
// with Vertical Direct we add them here in not so clean manner
|
||||
(damageType === "SPLATANA_VERTICAL_DIRECT" &&
|
||||
d.type === "SPLATANA_VERTICAL") ||
|
||||
(damageType === "SPLATANA_HORIZONTAL_DIRECT" &&
|
||||
d.type === "SPLATANA_HORIZONTAL")
|
||||
)
|
||||
.filter((d) => d.type === damageType || toCombine?.combineWith === d.type)
|
||||
.map((damage) => {
|
||||
if (!isMultiShot || !damage.multiShots) return damage;
|
||||
|
||||
@@ -173,66 +165,45 @@ export function calculateDamage({
|
||||
{ ...damage, objectShredder: true },
|
||||
])
|
||||
.flatMap((damage) => {
|
||||
if (
|
||||
(damageType === "SPLATANA_VERTICAL_DIRECT" &&
|
||||
damage.type === "SPLATANA_VERTICAL") ||
|
||||
(damageType === "SPLATANA_HORIZONTAL_DIRECT" &&
|
||||
damage.type === "SPLATANA_HORIZONTAL")
|
||||
) {
|
||||
if (toCombine?.combineWith === damage.type) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const splatanaDmg = (type: "VERTICAL" | "HORIZONTAL") => {
|
||||
const key =
|
||||
type === "VERTICAL" ? "SPLATANA_VERTICAL" : "SPLATANA_HORIZONTAL";
|
||||
const splatanaVerticalDamage = filteredDamages.find(
|
||||
(damage) => damage.type === key
|
||||
);
|
||||
invariant(splatanaVerticalDamage);
|
||||
const otherDamage = () => {
|
||||
const result = filteredDamages.find(
|
||||
(damage) => damage.type === toCombine?.combineWith
|
||||
)?.value;
|
||||
invariant(result);
|
||||
|
||||
return splatanaVerticalDamage.value;
|
||||
return result;
|
||||
};
|
||||
const dmg = () => {
|
||||
if (damageType === "SPLATANA_VERTICAL_DIRECT") {
|
||||
return damage.value + splatanaDmg("VERTICAL");
|
||||
if (toCombine && !toCombine?.multiplierOnly) {
|
||||
return damage.value + otherDamage();
|
||||
}
|
||||
return damage.value;
|
||||
};
|
||||
const baseMultiplier = () => {
|
||||
const normalMultiplier = multipliers[damage.type]![receiver];
|
||||
if (
|
||||
[
|
||||
"SPLATANA_VERTICAL_DIRECT",
|
||||
"SPLATANA_HORIZONTAL_DIRECT",
|
||||
].includes(damageType)
|
||||
) {
|
||||
const otherDamageKey =
|
||||
damageType === "SPLATANA_VERTICAL_DIRECT"
|
||||
? "SPLATANA_VERTICAL"
|
||||
: "SPLATANA_HORIZONTAL";
|
||||
const otherDamage =
|
||||
damageType === "SPLATANA_VERTICAL_DIRECT"
|
||||
? splatanaDmg("VERTICAL")
|
||||
: splatanaDmg("HORIZONTAL");
|
||||
if (toCombine) {
|
||||
const actualDamage = () => {
|
||||
if (damageType === "SPLATANA_HORIZONTAL_DIRECT") {
|
||||
if (toCombine.multiplierOnly) {
|
||||
// undo "baked in" damage (see above)
|
||||
return damage.value - otherDamage;
|
||||
return damage.value - otherDamage();
|
||||
}
|
||||
|
||||
return damage.value;
|
||||
};
|
||||
|
||||
const splatanaVerticalMultiplier =
|
||||
multipliers[otherDamageKey]![receiver];
|
||||
invariant(splatanaVerticalMultiplier);
|
||||
const otherMultiplier =
|
||||
multipliers[toCombine.combineWith]![receiver];
|
||||
|
||||
// calculate "made up" multiplier that is taking the
|
||||
// weighted average of the two multipliers
|
||||
return (
|
||||
(normalMultiplier * actualDamage() +
|
||||
splatanaVerticalMultiplier * otherDamage) /
|
||||
(actualDamage() + otherDamage)
|
||||
otherMultiplier * otherDamage()) /
|
||||
(actualDamage() + otherDamage())
|
||||
);
|
||||
}
|
||||
return normalMultiplier;
|
||||
|
||||
Reference in New Issue
Block a user