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