mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: implement most equalizer
This commit is contained in:
1 parent
6835004945
commit
77c516a6eb
10 files changed
+58
-41
No files matched your search
@@ -168,6 +168,7 @@ if (changedTanks.length > 0) {
|
|||||||
)
|
)
|
||||||
.map((id) => currentEquipmentDefinitions.equipments[id]);
|
.map((id) => currentEquipmentDefinitions.equipments[id]);
|
||||||
|
|
||||||
|
const equalize = false;
|
||||||
const currentCharacteristics = tankCharacteristics(
|
const currentCharacteristics = tankCharacteristics(
|
||||||
{
|
{
|
||||||
tank: current,
|
tank: current,
|
||||||
@@ -193,6 +194,7 @@ if (changedTanks.length > 0) {
|
|||||||
stockTurret: current.turrets[0],
|
stockTurret: current.turrets[0],
|
||||||
track: currentTracks,
|
track: currentTracks,
|
||||||
turret: currentTurret,
|
turret: currentTurret,
|
||||||
|
equalize,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
equipmentDefinitions: currentEquipmentDefinitions,
|
equipmentDefinitions: currentEquipmentDefinitions,
|
||||||
@@ -225,6 +227,7 @@ if (changedTanks.length > 0) {
|
|||||||
stockTurret: preview.turrets[0],
|
stockTurret: preview.turrets[0],
|
||||||
track: previewTracks,
|
track: previewTracks,
|
||||||
turret: previewTurret,
|
turret: previewTurret,
|
||||||
|
equalize,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
equipmentDefinitions: previewEquipmentDefinitions,
|
equipmentDefinitions: previewEquipmentDefinitions,
|
||||||
|
|||||||
+8
-6
@@ -59,11 +59,12 @@ export const InfoWithDelta = memo<InfoWithDeltaProps>(
|
|||||||
const delta = useDelta(uhWhatDoICallThisVariable);
|
const delta = useDelta(uhWhatDoICallThisVariable);
|
||||||
const protagonistTank = Duel.use((state) => state.protagonist.tank);
|
const protagonistTank = Duel.use((state) => state.protagonist.tank);
|
||||||
const shellIndex = Duel.use((state) =>
|
const shellIndex = Duel.use((state) =>
|
||||||
state.protagonist.gun.shells.indexOf(state.protagonist.shell)
|
state.protagonist.gun.shells.indexOf(state.protagonist.shell),
|
||||||
);
|
);
|
||||||
const equipmentMatrix = Duel.use(
|
const equipmentMatrix = Duel.use(
|
||||||
(state) => state.protagonist.equipmentMatrix
|
(state) => state.protagonist.equipmentMatrix,
|
||||||
);
|
);
|
||||||
|
const equalize = Duel.use((state) => state.equalize);
|
||||||
const others = useMemo(() => {
|
const others = useMemo(() => {
|
||||||
const defaultSkills = createDefaultSkills(skillDefinitions);
|
const defaultSkills = createDefaultSkills(skillDefinitions);
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ export const InfoWithDelta = memo<InfoWithDeltaProps>(
|
|||||||
tank.class === protagonistTank.class) ||
|
tank.class === protagonistTank.class) ||
|
||||||
(relativeAgainst === TankopediaRelativeAgainst.Tier &&
|
(relativeAgainst === TankopediaRelativeAgainst.Tier &&
|
||||||
tank.tier === protagonistTank.tier) ||
|
tank.tier === protagonistTank.tier) ||
|
||||||
relativeAgainst === TankopediaRelativeAgainst.All
|
relativeAgainst === TankopediaRelativeAgainst.All,
|
||||||
)
|
)
|
||||||
.map((tank) => {
|
.map((tank) => {
|
||||||
const member = tankToDuelMember(tank, provisionDefinitions);
|
const member = tankToDuelMember(tank, provisionDefinitions);
|
||||||
@@ -105,12 +106,13 @@ export const InfoWithDelta = memo<InfoWithDeltaProps>(
|
|||||||
track: member.track,
|
track: member.track,
|
||||||
turret: member.turret,
|
turret: member.turret,
|
||||||
assaultDistance: member.assaultDistance,
|
assaultDistance: member.assaultDistance,
|
||||||
|
equalize,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
equipmentDefinitions,
|
equipmentDefinitions,
|
||||||
provisionDefinitions,
|
provisionDefinitions,
|
||||||
tankModelDefinition: modelDefinitions.models[tank.id],
|
tankModelDefinition: modelDefinitions.models[tank.id],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.filter((tank) => {
|
.filter((tank) => {
|
||||||
@@ -123,7 +125,7 @@ export const InfoWithDelta = memo<InfoWithDeltaProps>(
|
|||||||
|
|
||||||
return othersValue !== undefined;
|
return othersValue !== undefined;
|
||||||
}) as TankCharacteristics[];
|
}) as TankCharacteristics[];
|
||||||
}, [relativeAgainst, shellIndex, equipmentMatrix]);
|
}, [relativeAgainst, shellIndex, equipmentMatrix, equalize]);
|
||||||
const betterTanks = others.filter((tank) => {
|
const betterTanks = others.filter((tank) => {
|
||||||
const othersValue =
|
const othersValue =
|
||||||
typeof props.value === "function"
|
typeof props.value === "function"
|
||||||
@@ -183,5 +185,5 @@ export const InfoWithDelta = memo<InfoWithDeltaProps>(
|
|||||||
|
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
(typeof a.value === "function" ? a.value(a.stats) : a.stats[a.value]) ===
|
(typeof a.value === "function" ? a.value(a.stats) : a.stats[a.value]) ===
|
||||||
(typeof b.value === "function" ? b.value(b.stats) : b.stats[b.value])
|
(typeof b.value === "function" ? b.value(b.stats) : b.stats[b.value]),
|
||||||
);
|
);
|
||||||
+2
@@ -31,6 +31,7 @@ export function Characteristics({ skeleton }: MaybeSkeletonComponentProps) {
|
|||||||
const equipmentMatrix = Duel.use(
|
const equipmentMatrix = Duel.use(
|
||||||
(state) => state.protagonist.equipmentMatrix,
|
(state) => state.protagonist.equipmentMatrix,
|
||||||
);
|
);
|
||||||
|
const equalize = Duel.use((state) => state.equalize);
|
||||||
const { tank, turret, gun, engine, track, shell } = Duel.use(
|
const { tank, turret, gun, engine, track, shell } = Duel.use(
|
||||||
(state) => state.protagonist,
|
(state) => state.protagonist,
|
||||||
);
|
);
|
||||||
@@ -62,6 +63,7 @@ export function Characteristics({ skeleton }: MaybeSkeletonComponentProps) {
|
|||||||
applyDynamicArmor: false,
|
applyDynamicArmor: false,
|
||||||
applySpallLiner: false,
|
applySpallLiner: false,
|
||||||
assaultDistance,
|
assaultDistance,
|
||||||
|
equalize,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tankModelDefinition,
|
tankModelDefinition,
|
||||||
|
|||||||
+2
-2
@@ -16,7 +16,7 @@ import { ConfigurationChildWrapper } from "./ConfigurationChildWrapper";
|
|||||||
|
|
||||||
export function Equalizer() {
|
export function Equalizer() {
|
||||||
const { strings } = useLocale();
|
const { strings } = useLocale();
|
||||||
const equalize = Duel.use((state) => state.protagonist.equalize);
|
const equalize = Duel.use((state) => state.equalize);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfigurationChildWrapper>
|
<ConfigurationChildWrapper>
|
||||||
@@ -33,7 +33,7 @@ export function Equalizer() {
|
|||||||
mt="2"
|
mt="2"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
Duel.mutate((draft) => {
|
Duel.mutate((draft) => {
|
||||||
draft.protagonist.equalize = !draft.protagonist.equalize;
|
draft.equalize = !draft.equalize;
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
width="100%"
|
width="100%"
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export function tankCharacteristics(
|
|||||||
applyDynamicArmor,
|
applyDynamicArmor,
|
||||||
applySpallLiner,
|
applySpallLiner,
|
||||||
assaultDistance,
|
assaultDistance,
|
||||||
|
equalize,
|
||||||
}: {
|
}: {
|
||||||
tank: TankDefinition;
|
tank: TankDefinition;
|
||||||
turret: TurretDefinition;
|
turret: TurretDefinition;
|
||||||
@@ -67,6 +68,7 @@ export function tankCharacteristics(
|
|||||||
applyDynamicArmor: boolean;
|
applyDynamicArmor: boolean;
|
||||||
applySpallLiner: boolean;
|
applySpallLiner: boolean;
|
||||||
assaultDistance: number;
|
assaultDistance: number;
|
||||||
|
equalize: boolean;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tankModelDefinition,
|
tankModelDefinition,
|
||||||
@@ -81,6 +83,13 @@ export function tankCharacteristics(
|
|||||||
const preset = equipmentDefinitions.presets[tank.equipment_preset];
|
const preset = equipmentDefinitions.presets[tank.equipment_preset];
|
||||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||||
|
const equalizer = (equalize ? tank.equalizer : undefined) ?? {
|
||||||
|
armor: 1,
|
||||||
|
damage: 1,
|
||||||
|
health: 1,
|
||||||
|
module_health: 1,
|
||||||
|
penetration: 1,
|
||||||
|
};
|
||||||
|
|
||||||
function equipment(id: number) {
|
function equipment(id: number) {
|
||||||
return preset.slots.some((slot, index) => {
|
return preset.slots.some((slot, index) => {
|
||||||
@@ -177,15 +186,17 @@ export function tankCharacteristics(
|
|||||||
(coefficient([hasGunRammer, -0.05]) *
|
(coefficient([hasGunRammer, -0.05]) *
|
||||||
coefficient([true, degressiveStat(loaderMastery)])) /
|
coefficient([true, degressiveStat(loaderMastery)])) /
|
||||||
coefficient([hasAdrenaline && gun.gun_type!.$case === "regular", 0.17]);
|
coefficient([hasAdrenaline && gun.gun_type!.$case === "regular", 0.17]);
|
||||||
const penetrationCoefficient = coefficient([
|
const penetrationCoefficient =
|
||||||
hasCalibratedShells,
|
coefficient([
|
||||||
resolvePenetrationCoefficient(true, shell.type) - 1,
|
hasCalibratedShells,
|
||||||
]);
|
resolvePenetrationCoefficient(true, shell.type) - 1,
|
||||||
const healthCoefficient = coefficient(
|
]) * equalizer.penetration;
|
||||||
[hasSandbagArmor, 0.03],
|
const healthCoefficient =
|
||||||
[hasEnhancedSandbagArmor, 0.06],
|
coefficient(
|
||||||
[hasImprovedAssembly, 0.04],
|
[hasSandbagArmor, 0.03],
|
||||||
);
|
[hasEnhancedSandbagArmor, 0.06],
|
||||||
|
[hasImprovedAssembly, 0.04],
|
||||||
|
) * equalizer.health;
|
||||||
const shellVelocityCoefficient = coefficient(
|
const shellVelocityCoefficient = coefficient(
|
||||||
[hasSupercharger, 0.35],
|
[hasSupercharger, 0.35],
|
||||||
[hasImprovedGunPowder, 0.3],
|
[hasImprovedGunPowder, 0.3],
|
||||||
@@ -345,7 +356,9 @@ export function tankCharacteristics(
|
|||||||
const resolvedEnginePower = engine.power * enginePowerCoefficient;
|
const resolvedEnginePower = engine.power * enginePowerCoefficient;
|
||||||
const damageCoefficientWithoutAssault = armorDamageCoefficient;
|
const damageCoefficientWithoutAssault = armorDamageCoefficient;
|
||||||
const damageCoefficient =
|
const damageCoefficient =
|
||||||
damageCoefficientWithoutAssault * assaultDamageCoefficient;
|
damageCoefficientWithoutAssault *
|
||||||
|
assaultDamageCoefficient *
|
||||||
|
equalizer.damage;
|
||||||
const dpm = resolveDpm(
|
const dpm = resolveDpm(
|
||||||
gun,
|
gun,
|
||||||
shell,
|
shell,
|
||||||
@@ -654,13 +667,3 @@ export const characteristicsOrder: {
|
|||||||
items: ["crewCount"],
|
items: ["crewCount"],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// export const characteristicsStyling: Record<
|
|
||||||
// TankCharacteristicsKey,
|
|
||||||
// {
|
|
||||||
// name: string;
|
|
||||||
// indent?: boolean;
|
|
||||||
// condition?: TankCharacteristicsCondition[];
|
|
||||||
// }
|
|
||||||
// > = {
|
|
||||||
// };
|
|
||||||
@@ -26,6 +26,5 @@ export function tankToDuelMember(
|
|||||||
track: tank.tracks.at(-1)!,
|
track: tank.tracks.at(-1)!,
|
||||||
turret,
|
turret,
|
||||||
assaultDistance: (gun.assault_ranges?.ranges[0].distance ?? 0) / 2,
|
assaultDistance: (gun.assault_ranges?.ranges[0].distance ?? 0) / 2,
|
||||||
equalize: false,
|
|
||||||
} satisfies DuelMember;
|
} satisfies DuelMember;
|
||||||
}
|
}
|
||||||
@@ -45,6 +45,7 @@ export function Page({ locale }: LocaleAcceptorProps) {
|
|||||||
|
|
||||||
function Content() {
|
function Content() {
|
||||||
const members = CompareEphemeral.use((state) => state.members);
|
const members = CompareEphemeral.use((state) => state.members);
|
||||||
|
const equalize = CompareEphemeral.use((state) => state.equalize);
|
||||||
const [addTankDialogOpen, setAddTankDialogOpen] = useState(false);
|
const [addTankDialogOpen, setAddTankDialogOpen] = useState(false);
|
||||||
const crewSkills = CompareEphemeral.use((state) => state.crewSkills);
|
const crewSkills = CompareEphemeral.use((state) => state.crewSkills);
|
||||||
const { strings } = useLocale();
|
const { strings } = useLocale();
|
||||||
@@ -61,26 +62,30 @@ function Content() {
|
|||||||
stockTurret: thisMember.tank.turrets[0],
|
stockTurret: thisMember.tank.turrets[0],
|
||||||
applyReactiveArmor: members.some(
|
applyReactiveArmor: members.some(
|
||||||
(member) =>
|
(member) =>
|
||||||
member.key !== thisMember.key && member.consumables.includes(33)
|
member.key !== thisMember.key &&
|
||||||
|
member.consumables.includes(33),
|
||||||
),
|
),
|
||||||
applyDynamicArmor: members.some(
|
applyDynamicArmor: members.some(
|
||||||
(member) =>
|
(member) =>
|
||||||
member.key !== thisMember.key && member.consumables.includes(73)
|
member.key !== thisMember.key &&
|
||||||
|
member.consumables.includes(73),
|
||||||
),
|
),
|
||||||
applySpallLiner: members.some(
|
applySpallLiner: members.some(
|
||||||
(member) =>
|
(member) =>
|
||||||
member.key !== thisMember.key && member.provisions.includes(101)
|
member.key !== thisMember.key &&
|
||||||
|
member.provisions.includes(101),
|
||||||
),
|
),
|
||||||
assaultDistance: thisMember.assaultDistance,
|
assaultDistance: thisMember.assaultDistance,
|
||||||
|
equalize,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
equipmentDefinitions: equipmentDefinitions,
|
equipmentDefinitions: equipmentDefinitions,
|
||||||
provisionDefinitions: provisionDefinitions,
|
provisionDefinitions: provisionDefinitions,
|
||||||
tankModelDefinition: modelDefinitions.models[thisMember.tank.id],
|
tankModelDefinition: modelDefinitions.models[thisMember.tank.id],
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
),
|
),
|
||||||
[members, crewSkills]
|
[members, crewSkills],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -112,7 +117,7 @@ function Content() {
|
|||||||
window.history.replaceState(
|
window.history.replaceState(
|
||||||
{},
|
{},
|
||||||
"",
|
"",
|
||||||
`${window.location.pathname}?${search.toString()}`
|
`${window.location.pathname}?${search.toString()}`,
|
||||||
);
|
);
|
||||||
}, [members]);
|
}, [members]);
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const getStaticPaths = (async () => {
|
|||||||
parentPaths.map((parent) => ({
|
parentPaths.map((parent) => ({
|
||||||
params: { ...parent.params, slug: tank.slug },
|
params: { ...parent.params, slug: tank.slug },
|
||||||
props: { ...parent.props, id: tank.id },
|
props: { ...parent.props, id: tank.id },
|
||||||
}))
|
})),
|
||||||
)
|
)
|
||||||
.flat();
|
.flat();
|
||||||
}) satisfies GetStaticPaths;
|
}) satisfies GetStaticPaths;
|
||||||
@@ -86,8 +86,9 @@ const characteristics = tankCharacteristics(
|
|||||||
stockTrack: tank.tracks[0],
|
stockTrack: tank.tracks[0],
|
||||||
track: tank.tracks.at(-1)!,
|
track: tank.tracks.at(-1)!,
|
||||||
assaultDistance: 0,
|
assaultDistance: 0,
|
||||||
|
equalize: false,
|
||||||
},
|
},
|
||||||
{ equipmentDefinitions, provisionDefinitions, tankModelDefinition }
|
{ equipmentDefinitions, provisionDefinitions, tankModelDefinition },
|
||||||
);
|
);
|
||||||
const description = literals(
|
const description = literals(
|
||||||
strings.website.tools.tankopedia.tank_seo_description,
|
strings.website.tools.tankopedia.tank_seo_description,
|
||||||
@@ -98,7 +99,7 @@ const description = literals(
|
|||||||
penetration: Math.round(characteristics.penetration).toLocaleString(locale),
|
penetration: Math.round(characteristics.penetration).toLocaleString(locale),
|
||||||
speed: Math.round(characteristics.speedForwards).toLocaleString(locale),
|
speed: Math.round(characteristics.speedForwards).toLocaleString(locale),
|
||||||
health: Math.round(characteristics.health).toLocaleString(locale),
|
health: Math.round(characteristics.health).toLocaleString(locale),
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const guideUrl = `${assertSecret(import.meta.env.PUBLIC_GUIDE_WEBSITE)}/${tank.slug}`;
|
const guideUrl = `${assertSecret(import.meta.env.PUBLIC_GUIDE_WEBSITE)}/${tank.slug}`;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export interface CompareMember extends DuelMember {
|
|||||||
|
|
||||||
export interface CompareEphemeral {
|
export interface CompareEphemeral {
|
||||||
crewSkills: Record<string, number>;
|
crewSkills: Record<string, number>;
|
||||||
|
equalize: boolean;
|
||||||
members: CompareMember[];
|
members: CompareMember[];
|
||||||
sorting?: {
|
sorting?: {
|
||||||
direction: "ascending" | "descending";
|
direction: "ascending" | "descending";
|
||||||
@@ -19,5 +20,6 @@ export const CompareEphemeral = new Varuna<
|
|||||||
Record<string, number>
|
Record<string, number>
|
||||||
>((crewSkills) => ({
|
>((crewSkills) => ({
|
||||||
crewSkills,
|
crewSkills,
|
||||||
|
equalize: false,
|
||||||
members: [],
|
members: [],
|
||||||
}));
|
}));
|
||||||
@@ -36,12 +36,12 @@ export interface DuelMember {
|
|||||||
camouflage: boolean;
|
camouflage: boolean;
|
||||||
cooldownBooster: number;
|
cooldownBooster: number;
|
||||||
assaultDistance: number;
|
assaultDistance: number;
|
||||||
equalize: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DuelStore {
|
export interface DuelStore {
|
||||||
protagonist: DuelMember;
|
protagonist: DuelMember;
|
||||||
antagonist: DuelMember;
|
antagonist: DuelMember;
|
||||||
|
equalize: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const provisionDefinitions = await awaitableProvisionDefinitions;
|
const provisionDefinitions = await awaitableProvisionDefinitions;
|
||||||
@@ -52,5 +52,5 @@ export const Duel = new Varuna<
|
|||||||
>(({ tank, model }) => {
|
>(({ tank, model }) => {
|
||||||
const protagonist = tankToDuelMember(tank, provisionDefinitions);
|
const protagonist = tankToDuelMember(tank, provisionDefinitions);
|
||||||
|
|
||||||
return { protagonist, antagonist: protagonist, model };
|
return { protagonist, antagonist: protagonist, model, equalize: false };
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user