diff --git a/packages/website-ue/src/components/TankopediaCharacteristics/index.module.css b/packages/website-ue/src/components/TankopediaCharacteristics/index.module.css
index 8b7773572..fd0a5a77c 100644
--- a/packages/website-ue/src/components/TankopediaCharacteristics/index.module.css
+++ b/packages/website-ue/src/components/TankopediaCharacteristics/index.module.css
@@ -1,24 +1,37 @@
.characteristics {
+ --cell-width: 2.5rem;
+ --group-span: 7;
+ --inner-padding: var(--space-4);
+
+ display: grid;
+ grid-auto-rows: var(--cell-width);
+ grid-template-columns: repeat(auto-fill, minmax(var(--cell-width), 1fr));
+ grid-auto-flow: dense;
+
padding: var(--space-5);
+ gap: var(--space-4);
- display: flex;
- flex-direction: column;
- gap: var(--space-5);
box-sizing: border-box;
.group {
- display: flex;
- flex-direction: column;
+ display: grid;
+ grid-template-columns: 1fr;
- gap: var(--space-4);
+ grid-column: span var(--group-span);
+ gap: inherit;
.title-wrapper {
+ background-color: var(--amber-a3);
+ grid-row: span 1;
+
+ padding: 0 var(--inner-padding);
+
display: flex;
align-items: center;
- gap: var(--space-4);
+ gap: var(--space-3);
.title {
- .title-content {
+ .content {
display: flex;
align-items: center;
gap: var(--space-2);
@@ -31,67 +44,60 @@
}
}
}
-
- .separator {
- height: var(--space-1);
- flex: 1;
-
- background-color: var(--gray-5);
- }
}
- .content {
- --cell-width: 2rem;
- --toy-span: 6;
+ .item {
+ padding: 0 var(--inner-padding);
- display: grid;
- grid-auto-rows: var(--cell-width);
- grid-template-columns: repeat(auto-fill, minmax(var(--cell-width), 1fr));
- grid-auto-flow: row dense;
- gap: var(--space-4);
+ grid-row: span 1;
- .item {
- grid-row: span 1;
- grid-column: span var(--toy-span);
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ gap: var(--space-2);
+ .value {
display: flex;
- flex-direction: column;
- justify-content: center;
- gap: var(--space-2);
+ justify-content: space-between;
+ }
- .value {
- display: flex;
- justify-content: space-between;
- }
+ .ranking {
+ display: flex;
+ align-items: center;
+ gap: var(--space-3);
- .ranking {
- display: flex;
- align-items: center;
- gap: var(--space-3);
+ .bar-wrapper {
+ flex: 1;
+ height: var(--space-1);
- .bar-wrapper {
- flex: 1;
- height: var(--space-1);
+ background-color: var(--gray-3);
+ border-radius: var(--radius-max);
+ overflow: hidden;
- background-color: var(--gray-3);
- border-radius: var(--radius-max);
- overflow: hidden;
-
- .bar {
- background-color: var(--jade-9);
- width: 75%;
- height: 100%;
- }
+ .bar {
+ background-color: var(--jade-9);
+ width: 75%;
+ height: 100%;
}
}
}
+ }
- .toy {
- grid-row: span var(--toy-span);
- grid-column: span var(--toy-span);
+ .toy {
+ grid-row: span var(--group-span);
+ padding: var(--inner-padding);
- background-color: var(--gray-3);
- border: var(--gray-5) solid var(--space-1);
+ .content {
+ background-color: green;
+ width: 100%;
+ height: 100%;
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ background-color: var(--gray-2);
+ outline: var(--gray-5) solid var(--space-1);
border-radius: var(--space-3);
}
diff --git a/packages/website-ue/src/components/TankopediaCharacteristics/index.tsx b/packages/website-ue/src/components/TankopediaCharacteristics/index.tsx
index 6af504f42..d753ceba0 100644
--- a/packages/website-ue/src/components/TankopediaCharacteristics/index.tsx
+++ b/packages/website-ue/src/components/TankopediaCharacteristics/index.tsx
@@ -1,7 +1,6 @@
-import { CaretDownIcon, CaretRightIcon } from "@radix-ui/react-icons";
+import { GearIcon } from "@radix-ui/react-icons";
import { useCharacteristicRenderer } from "../../hooks/useCharacteristicRenderer";
import { useStrings } from "../../hooks/useStrings";
-import { Tankopedia } from "../../stores/tankopedia";
import type { CharacteristicOutput } from "../../tankopedia/characteristics";
import {
characteristicsOrder,
@@ -9,7 +8,6 @@ import {
type CharacteristicsGroup,
} from "../../tankopedia/characteristicsOrder";
import type { ComputedCharacteristics } from "../../tankopedia/computeCharacteristics";
-import { Heading } from "../Heading";
import { Text } from "../Text";
import styles from "./index.module.css";
@@ -35,35 +33,35 @@ interface GroupProps {
}
function Group({ group, characteristics }: GroupProps) {
- const isOpen = Tankopedia.use((state) => state.groups[group.group]);
const strings = useStrings();
+ const toys = group.order.filter((item) => "toy" in item).length;
+ const items = group.order.filter((item) => "name" in item).length;
+ const span = `calc(${toys} * var(--group-span) + ${items} + 1)`;
return (
-
+
-
-
- {isOpen ?
:
}
- {
- (strings.tanks.characteristics.titles as Record
)[
- group.group
- ]
- }
+
+
+ {group.group}
+
-
-
-
+
-
- {group.order.map((item) =>
- "toy" in item ? (
-
- ) : (
-
- ),
- )}
-
+ {group.order.map((item) =>
+ "toy" in item ? (
+
+ ) : (
+
+ ),
+ )}
);
}
@@ -80,13 +78,7 @@ function Item({ config, value }: ItemProps) {
return (
-
- {
- (strings.tanks.characteristics.items as Record)[
- config.name
- ]
- }
-
+ {config.name}
{renderCharacteristic(value, config)}
@@ -108,5 +100,11 @@ interface ToyProps {
}
function Toy({ toy }: ToyProps) {
- return ;
+ return (
+
+ );
}
diff --git a/packages/website-ue/src/pages/[...locale]/tanks/[slug]/_index.tsx b/packages/website-ue/src/pages/[...locale]/tanks/[slug]/_index.tsx
index a3c30a4c7..023ff37c2 100644
--- a/packages/website-ue/src/pages/[...locale]/tanks/[slug]/_index.tsx
+++ b/packages/website-ue/src/pages/[...locale]/tanks/[slug]/_index.tsx
@@ -1,4 +1,4 @@
-import { Fragment, useMemo } from "react";
+import { useMemo } from "react";
import { api } from "../../../../api/dynamic";
import { TankopediaCharacteristics } from "../../../../components/TankopediaCharacteristics";
import { TankopediaLoadout } from "../../../../components/TankopediaLoadout";
@@ -6,10 +6,8 @@ import { TankopediaSandbox } from "../../../../components/TankopediaSandbox";
import { withErrorWrapper } from "../../../../hocs/withErrorWrapper";
import { withLocale } from "../../../../hocs/withLocale";
import { useAwait } from "../../../../hooks/useAwait";
-import { useCharacteristicRenderer } from "../../../../hooks/useCharacteristicRenderer";
import { useEquipment } from "../../../../hooks/useEquipment";
import { Tankopedia } from "../../../../stores/tankopedia";
-import { characteristicsOrder } from "../../../../tankopedia/characteristicsOrder";
import { computeCharacteristics } from "../../../../tankopedia/computeCharacteristics";
import styles from "./_index.module.css";
@@ -50,62 +48,3 @@ export const Page = withErrorWrapper(
);
}),
);
-
-export const _Page = withErrorWrapper(
- withLocale(({ id }) => {
- const protagonistTank = useAwait(() => api.tank(id), `tank-${id}`);
-
- Tankopedia.useInitialization(protagonistTank);
-
- const renderCharacteristic = useCharacteristicRenderer();
-
- const protagonist = Tankopedia.use((state) => state.protagonist);
- const protagonistEquipment = useEquipment(protagonistTank.tank!);
-
- const { characteristics } = useMemo(
- () =>
- computeCharacteristics(
- protagonistTank,
- protagonistEquipment,
- protagonist,
- ),
- [protagonist],
- );
-
- return (
- <>
- {protagonist.id}
-
-
-
-
-
- characteristics
-
- {characteristicsOrder.map((group) => {
- return (
-
- {group.group}
-
- {group.order.map((item) => {
- if ("toy" in item) {
- return toy: {item.toy};
- }
-
- const value = characteristics[item.name];
-
- if (value == null) return null;
-
- return (
-
- {item.name}: {renderCharacteristic(value, item)}
-
- );
- })}
-
- );
- })}
- >
- );
- }),
-);
diff --git a/packages/website-ue/src/pages/[...locale]/tanks/[slug]/index.astro b/packages/website-ue/src/pages/[...locale]/tanks/[slug]/index.astro
index e41516244..2e2577c7c 100644
--- a/packages/website-ue/src/pages/[...locale]/tanks/[slug]/index.astro
+++ b/packages/website-ue/src/pages/[...locale]/tanks/[slug]/index.astro
@@ -23,6 +23,7 @@ const { id, locale } = Astro.props;
+
diff --git a/packages/website-ue/src/tankopedia/characteristics.ts b/packages/website-ue/src/tankopedia/characteristics.ts
index c6897a338..0741d9891 100644
--- a/packages/website-ue/src/tankopedia/characteristics.ts
+++ b/packages/website-ue/src/tankopedia/characteristics.ts
@@ -419,4 +419,60 @@ export const characteristics = {
compensation({ tank }) {
return tank.compensation!.compensation?.currency_reward?.amount ?? null;
},
+
+ purchase_price() {
+ return -Infinity;
+ },
+
+ upgrade_price() {
+ return -Infinity;
+ },
+
+ research_level() {
+ return -Infinity;
+ },
+
+ crew_xp_multiplier() {
+ return -Infinity;
+ },
+
+ clipping_potential() {
+ return -Infinity;
+ },
+
+ burst_size() {
+ return -Infinity;
+ },
+
+ intra_burst() {
+ return -Infinity;
+ },
+
+ dispersion_angle() {
+ return -Infinity;
+ },
+
+ gun_yaw_range() {
+ return -Infinity;
+ },
+
+ brake_force() {
+ return -Infinity;
+ },
+
+ gun_traverse_speed() {
+ return -Infinity;
+ },
+
+ fire_health_burn() {
+ return -Infinity;
+ },
+
+ ramming_resistance() {
+ return -Infinity;
+ },
+
+ width() {
+ return -Infinity;
+ },
} satisfies Record;
diff --git a/packages/website-ue/src/tankopedia/characteristicsOrder.tsx b/packages/website-ue/src/tankopedia/characteristicsOrder.tsx
index d33885532..982980dc0 100644
--- a/packages/website-ue/src/tankopedia/characteristicsOrder.tsx
+++ b/packages/website-ue/src/tankopedia/characteristicsOrder.tsx
@@ -29,19 +29,25 @@ export interface CharacteristicRenderConfig {
}) => ReactNode;
}
+export interface ToyRenderConfig {
+ toy: string;
+}
+
export type CharacteristicsGroup = {
group: string;
- order: (
- | CharacteristicRenderConfig
- | {
- toy: string;
- }
- )[];
+ render: CharacteristicsGroupRender;
+ order: (CharacteristicRenderConfig | ToyRenderConfig)[];
};
+export enum CharacteristicsGroupRender {
+ Flashy,
+ Statistical,
+}
+
export const characteristicsOrder: CharacteristicsGroup[] = [
{
group: "meta",
+ render: CharacteristicsGroupRender.Flashy,
order: [
{
name: "name",
@@ -80,15 +86,29 @@ export const characteristicsOrder: CharacteristicsGroup[] = [
return strings.tiers[name as keyof typeof strings.tiers];
},
},
- { name: "compensation" },
{ name: "id" },
{ name: "slug" },
],
},
+
{
- group: "firepower",
+ group: "economics",
+ render: CharacteristicsGroupRender.Statistical,
+ order: [
+ { name: "purchase_price" },
+ { name: "compensation" },
+ { name: "upgrade_price" },
+ { name: "research_level" },
+ { name: "crew_xp_multiplier" },
+
+ // TODO: investigate ATTRIBUTE_NAME_CREW_XP_MULTIPLIER
+ ],
+ },
+
+ {
+ group: "gun",
+ render: CharacteristicsGroupRender.Statistical,
order: [
- { toy: "reload" },
{
name: "gun_type",
render({ output }) {
@@ -96,75 +116,123 @@ export const characteristicsOrder: CharacteristicsGroup[] = [
},
},
{ name: "dpm", decimals: 0, units: "hp_min" },
+ { name: "damage", units: "hp" },
+ { name: "module_damage", units: "hp" },
{ name: "reload", decimals: 2, units: "s" },
{ name: "reloads", decimals: 2, units: "s" },
- { name: "damage", units: "hp" },
- { name: "module_damage", units: "hp" },
+ { toy: "reload" },
+ ],
+ },
+
+ {
+ group: "clip",
+ render: CharacteristicsGroupRender.Statistical,
+ order: [
+ { name: "clipping_potential" },
{ name: "clip_size" },
+ { name: "optimal_shell" },
{ name: "intra_clip", decimals: 2, units: "s" },
- // { name: "burst_size" }, // TODO: implement burst size
- // { name: 'intra_burst', decimals: 2, units: "s" }, // TODO: implement intra burst
+ { name: "burst_size" },
+ { name: "intra_burst", decimals: 2, units: "s" },
+
// TODO: investigate ATTRIBUTE_NAME_SHELLS_SLOTS
// TODO: investigate ATTRIBUTE_NAME_RELOAD_SPEED_SCALE
// TODO: investigate ATTRIBUTE_NAME_AVERAGE_THICKNESS
+ // TODO: investigate ATTRIBUTE_NAME_TRACER_SHELLS_OBSERVATION_TIMEOUT
+ ],
+ },
- // { toy: "ricochet" },
+ {
+ group: "shell",
+ render: CharacteristicsGroupRender.Statistical,
+ order: [
{ name: "penetration", units: "mm" },
+ { name: "shell_velocity", units: "m_s" },
+ { name: "shell_range", units: "m" },
+ { name: "shell_capacity" },
{ name: "caliber", units: "mm" },
{ name: "normalization", units: "deg" },
{ name: "ricochet", units: "deg" },
- { name: "shell_velocity", units: "m_s" },
- { name: "shell_range", units: "m" },
- { name: "shell_capacity" },
-
- // { toy: "aim_time" },
- { name: "aim_time", decimals: 1, units: "s" },
- { name: "dispersion", decimals: 3, units: "m" },
- // { name: "dispersion_angle", decimals: 3, units: "m" }, // TODO: implement dispersion angle
-
- // { toy: "flexibility" },
- { name: "gun_depression", decimals: 0, units: "deg" },
- { name: "gun_elevation", decimals: 0, units: "deg" },
- // { name: "gun_yaw_range", decimals: 0, units: "deg" }, // TODO: implement gun yaw range
+ { toy: "ricochet" },
],
},
+
+ {
+ group: "accuracy",
+ render: CharacteristicsGroupRender.Statistical,
+ order: [
+ { name: "aim_time", decimals: 1, units: "s" },
+ { name: "dispersion", decimals: 3, units: "m" },
+ { name: "dispersion_angle", decimals: 3, units: "m" },
+ { toy: "aim_time" },
+ ],
+ },
+
+ {
+ group: "flexibility",
+ render: CharacteristicsGroupRender.Statistical,
+ order: [
+ { name: "gun_depression", decimals: 0, units: "deg" },
+ { name: "gun_elevation", decimals: 0, units: "deg" },
+ { name: "gun_yaw_range", decimals: 0, units: "deg" },
+
+ { toy: "flexibility" },
+ ],
+ },
+
{
group: "maneuverability",
+ render: CharacteristicsGroupRender.Statistical,
order: [
- // { toy: "traverse" },
{ name: "speed_forward", units: "km_h" },
{ name: "speed_backward", units: "km_h" },
{ name: "engine_power", units: "bhp" },
- // { name: "brake_force", units: "N" }, // TODO: implement brake force
+ { name: "brake_force", units: "N" },
{ name: "weight", decimals: 1, units: "t" },
{ name: "terrain_coefficient" },
{ name: "power_to_weight", decimals: 1, units: "bhp_t" },
+
{ name: "hull_traverse_speed", units: "deg_s" },
{ name: "turret_traverse_speed", units: "deg_s" },
- // { name: "gun_traverse_speed", units: "deg_s" }, // TODO: implement gun traverse speed
+ { name: "gun_traverse_speed", units: "deg_s" },
+
+ { toy: "traverse" },
+
+ // TODO: investigate ATTRIBUTE_NAME_TERRAIN_SIDE_FRICTION
+ // TODO: investigate ATTRIBUTE_NAME_TERRAIN_FORWARD_FRICTION
+ // TODO: investigate ATTRIBUTE_NAME_RESERVE_TRACK_BACKWARD_SPEED
],
},
+
{
group: "survivability",
+ render: CharacteristicsGroupRender.Statistical,
order: [
{ name: "health", units: "hp" },
{ name: "fire_chance", units: "%" },
- // { name: "fire_health_burn", units: "hp_s" }, // TODO: implement fire health burn
- // { name: "ramming_resistance", units: "%" }, // TODO: implement ramming resistance
+ { name: "fire_health_burn", units: "hp_s" },
+ { name: "ramming_resistance", units: "%" },
- // { toy: "view_range" },
+ { toy: "fire_health_burn" },
+
+ // TODO: investigate ATTRIBUTE_NAME_MAX_FIRE_DURATION
+ ],
+ },
+
+ {
+ group: "concealment",
+ render: CharacteristicsGroupRender.Statistical,
+ order: [
{ name: "view_range", units: "m" },
{ name: "camouflage", decimals: 0, units: "%" },
- // { name: "consumable_cooldown", decimals: 0, units: "%" }, // TODO: implement consumable cooldown
- // { name: "consumable_duration", decimals: 0, units: "s" }, // TODO: implement consumable duration
- // { name: "consumable_reload", decimals: 0, units: "s" }, // TODO: implement consumable reload
+ { toy: "view_range" },
- // { name: "width", units: "m" }, // TODO: implement width
+ { name: "width", units: "m" },
{ name: "height", units: "m" },
{ name: "length", units: "m" },
{ name: "volume", units: "m" },