feat: show icons in statistics (#16)

This commit is contained in:
Patric Stout
2023-11-20 22:10:34 +01:00
committed by GitHub
parent 8ee97f2dc2
commit 76f3467829
10 changed files with 181 additions and 44 deletions

View File

@@ -18,7 +18,7 @@
"author": "Patric Stout <eveshipfit@truebrain.nl>",
"license": "MIT",
"dependencies": {
"@eveshipfit/dogma-engine": "^2.2.0",
"@eveshipfit/dogma-engine": "^2.2.1",
"clsx": "^2.0.0"
},
"devDependencies": {
@@ -61,7 +61,7 @@
"typescript-plugin-css-modules": "^5.0.2"
},
"peerDependencies": {
"@eveshipfit/dogma-engine": "^2.2.0",
"@eveshipfit/dogma-engine": "^2.2.1",
"react": "^18.2.0"
},
"main": "dist/cjs/index.js",

View File

@@ -1,14 +1,13 @@
import React from "react";
import { DogmaAttribute, DogmaEffect, TypeDogma, TypeID } from "./DataTypes";
import { defaultDataUrl } from "../settings";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line import/extensions
import * as esf_pb2 from "./esf_pb2.js";
const defaultDataUrl = "https://data.eveship.fit/20231115-0/";
interface DogmaData {
loaded?: boolean;
typeIDs?: Record<string, TypeID>;
@@ -59,7 +58,7 @@ function isLoaded(dogmaData: DogmaData): boolean | undefined {
* ```
*/
export const EveDataProvider = (props: DogmaDataProps) => {
const dataUrl = props.dataUrl ?? defaultDataUrl;
const dataUrl = props.dataUrl ?? `${defaultDataUrl}sde/`;
const [dogmaData, setDogmaData] = React.useState<DogmaData>({});
React.useEffect(() => {

18
src/Icon/Icon.stories.tsx Normal file
View File

@@ -0,0 +1,18 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Icon } from './';
const meta: Meta<typeof Icon> = {
component: Icon,
tags: ['autodocs'],
title: 'Component/Icon',
};
export default meta;
type Story = StoryObj<typeof Icon>;
export const Default: Story = {
args: {
name: "em-resistance",
},
};

45
src/Icon/Icon.tsx Normal file
View File

@@ -0,0 +1,45 @@
import React from "react";
import { defaultDataUrl } from "../settings";
const iconMapping = {
"align-time": "texture/classes/fitting/statsicons/aligntime.png",
"armor-hp": "texture/classes/fitting/statsicons/armorhp.png",
"armor-repair-rate": "texture/classes/fitting/statsicons/armorrepairrate.png",
"em-resistance": "texture/classes/fitting/statsicons/emresistance.png",
"explosive-resistance": "texture/classes/fitting/statsicons/explosiveresistance.png",
"hull-hp": "texture/classes/fitting/statsicons/structurehp.png",
"hull-repair-rate": "texture/classes/fitting/statsicons/hullrepairrate.png",
"inertia-modifier": "texture/classes/fitting/statsicons/inertiamodifier.png",
"kinetic-resistance": "texture/classes/fitting/statsicons/kineticresistance.png",
"mass": "texture/classes/fitting/statsicons/mass.png",
"maximum-locked-targets": "texture/classes/fitting/statsicons/maximumlockedtargets.png",
"passive-shield-recharge": "texture/classes/fitting/statsicons/passiveshieldrecharge.png",
"scan-resolution": "texture/classes/fitting/statsicons/scanresolution.png",
"sensor-strength": "texture/classes/fitting/statsicons/sensorstrength.png",
"shield-boost-rate": "texture/classes/fitting/statsicons/shieldboostrate.png",
"shield-hp": "texture/classes/fitting/statsicons/shieldhp.png",
"signature-radius": "texture/classes/fitting/statsicons/signatureradius.png",
"thermal-resistance": "texture/classes/fitting/statsicons/thermalresistance.png",
"warp-speed": "texture/classes/fitting/statsicons/warpspeed.png",
} as const;
export type IconName = keyof typeof iconMapping;
export interface IconProps {
/** Name of the icon. */
name: IconName;
/** Size (in pixels) of the icon. */
size?: number;
}
/**
* Render a single attribute of a ship's snapshot.
*/
export const Icon = (props: IconProps) => {
const icon = iconMapping[props.name];
if (icon === undefined) {
return <span>Unknown icon: {props.name}</span>;
}
return <img src={`${defaultDataUrl}ui/${icon}`} width={props.size} />
};

1
src/Icon/index.ts Normal file
View File

@@ -0,0 +1 @@
export { type IconName, Icon } from "./Icon";

View File

@@ -4,21 +4,32 @@ import { useShipAttribute } from '../ShipAttribute';
import styles from "./ShipStatistics.module.css";
import clsx from "clsx";
import { IconName, Icon } from "../Icon";
export const RechargeRateItem = (props: {name: string, icon: React.ReactNode}) => {
export const RechargeRateItem = (props: {name: string, icon: IconName}) => {
const stringValue = useShipAttribute({
name: props.name,
fixed: 1,
});
if (stringValue == "0.0") {
return <span>
{props.icon} No Module
return <span className={styles.statistic}>
<span>
<Icon name={props.icon} size={24} />
</span>
<span>
No Module
</span>
</span>
}
return <span>
{props.icon} {stringValue} hp/s
return <span className={styles.statistic}>
<span>
<Icon name={props.icon} size={24} />
</span>
<span>
{stringValue} hp/s
</span>
</span>
}
@@ -37,10 +48,10 @@ export const RechargeRate = () => {
<div onClick={() => { setModuleType("shieldBoostRate"); setShowDropdown(false); }} className={clsx({[styles.rechargeRateDropdownContentSelected]: moduleType == "shieldBoostRate"})}>Shield boost rate</div>
</div> }
<div onClick={() => setShowDropdown((current) => !current)}>
{ moduleType == "armorRepairRate" && <RechargeRateItem name="armorRepairRate" icon={<>A</>} /> }
{ moduleType == "hullRepairRate" && <RechargeRateItem name="hullRepairRate" icon={<>H</>} /> }
{ moduleType == "passiveShieldRecharge" && <RechargeRateItem name="passiveShieldRecharge" icon={<>P</>} /> }
{ moduleType == "shieldBoostRate" && <RechargeRateItem name="shieldBoostRate" icon={<>S</>} /> }
{ moduleType == "armorRepairRate" && <RechargeRateItem name="armorRepairRate" icon="armor-repair-rate" /> }
{ moduleType == "hullRepairRate" && <RechargeRateItem name="hullRepairRate" icon="hull-repair-rate" /> }
{ moduleType == "passiveShieldRecharge" && <RechargeRateItem name="passiveShieldRecharge" icon="passive-shield-recharge" /> }
{ moduleType == "shieldBoostRate" && <RechargeRateItem name="shieldBoostRate" icon="shield-boost-rate" /> }
</div>
</span>
}

View File

@@ -42,27 +42,38 @@
margin: 0px 5px;
}
.statistic {
display: flex;
}
.statistic > span:last-child {
line-height: 24px;
margin-left: 4px;
}
.defense {
margin: 20px 0px;
}
.defense:last-child {
margin-bottom: 10px;
}
.defenseShield {
display: flex;
position: relative;
top: -5px;
}
.defenseShield > span:first-child {
line-height: 30px;
}
.defenseShield > span:first-child > img {
padding-top: 4px;
}
.defenseShield > span:last-child {
line-height: 15px;
}
.resistanceHeader {
display: inline-block;
text-align: center;
margin-left: 5px;
width: 50px;
}

View File

@@ -1,3 +1,4 @@
import clsx from "clsx";
import React from "react";
import { ShipAttribute } from '../ShipAttribute';
@@ -7,6 +8,7 @@ import { RechargeRate } from "./RechargeRate";
import { Resistance } from "./Resistance";
import styles from "./ShipStatistics.module.css";
import { Icon } from "../Icon";
/**
* Render ship statistics similar to how it is done in-game.
@@ -47,16 +49,16 @@ export const ShipStatistics = () => {
<CategoryLine>
<RechargeRate />
<span style={{flex: 2}}>
<span className={styles.resistanceHeader}>E</span>
<span className={styles.resistanceHeader}>T</span>
<span className={styles.resistanceHeader}>K</span>
<span className={styles.resistanceHeader}>X</span>
<span className={styles.resistanceHeader}><Icon name="em-resistance" size={28} /></span>
<span className={styles.resistanceHeader}><Icon name="thermal-resistance" size={28} /></span>
<span className={styles.resistanceHeader}><Icon name="kinetic-resistance" size={28} /></span>
<span className={styles.resistanceHeader}><Icon name="explosive-resistance" size={28} /></span>
</span>
</CategoryLine>
<CategoryLine className={styles.defense}>
<span className={styles.defenseShield}>
<span className={clsx(styles.statistic, styles.defenseShield)}>
<span>
S
<Icon name="shield-hp" size={24} />
</span>
<span>
<ShipAttribute name="shieldCapacity" fixed={0} /> hp<br/>
@@ -71,9 +73,13 @@ export const ShipStatistics = () => {
</span>
</CategoryLine>
<CategoryLine className={styles.defense}>
<span>
A
<ShipAttribute name="armorHP" fixed={0} /> hp
<span className={styles.statistic}>
<span>
<Icon name="armor-hp" size={24} />
</span>
<span>
<ShipAttribute name="armorHP" fixed={0} /> hp
</span>
</span>
<span style={{flex: 2}}>
<Resistance name="armorEmDamageResonance" />
@@ -83,9 +89,13 @@ export const ShipStatistics = () => {
</span>
</CategoryLine>
<CategoryLine className={styles.defense}>
<span>
S
<ShipAttribute name="hp" fixed={0} /> hp
<span className={styles.statistic}>
<span>
<Icon name="hull-hp" size={24} />
</span>
<span>
<ShipAttribute name="hp" fixed={0} /> hp
</span>
</span>
<span style={{flex: 2}}>
<Resistance name="emDamageResonance" />
@@ -100,19 +110,39 @@ export const ShipStatistics = () => {
<span><ShipAttribute name="maxTargetRange" fixed={2} divideBy={1000} /> km</span>
}>
<CategoryLine>
<span title="Scan Strength">
<ShipAttribute name="scanStrength" fixed={2} /> points
<span title="Scan Strength" className={styles.statistic}>
<span>
<Icon name="sensor-strength" size={24} />
</span>
<span>
<ShipAttribute name="scanStrength" fixed={2} /> points
</span>
</span>
<span title="Scan Resolution">
<ShipAttribute name="scanResolution" fixed={0} /> mm
<span title="Scan Resolution" className={styles.statistic}>
<span>
<Icon name="scan-resolution" size={24} />
</span>
<span>
<ShipAttribute name="scanResolution" fixed={0} /> mm
</span>
</span>
</CategoryLine>
<CategoryLine>
<span title="Signature Radius">
<ShipAttribute name="signatureRadius" fixed={0} /> m
<span title="Signature Radius" className={styles.statistic}>
<span>
<Icon name="signature-radius" size={24} />
</span>
<span>
<ShipAttribute name="signatureRadius" fixed={0} /> m
</span>
</span>
<span title="Maximum Locked Targets">
<ShipAttribute name="maxLockedTargets" fixed={0} />x
<span title="Maximum Locked Targets" className={styles.statistic}>
<span>
<Icon name="maximum-locked-targets" size={24} />
</span>
<span>
<ShipAttribute name="maxLockedTargets" fixed={0} />x
</span>
</span>
</CategoryLine>
</Category>
@@ -121,19 +151,39 @@ export const ShipStatistics = () => {
<span><ShipAttribute name="maxVelocity" fixed={1} /> m/s</span>
}>
<CategoryLine>
<span title="Mass">
<ShipAttribute name="mass" fixed={2} /> t
<span title="Mass" className={styles.statistic}>
<span>
<Icon name="mass" size={24} />
</span>
<span>
<ShipAttribute name="mass" fixed={2} /> t
</span>
</span>
<span title="Inertia Modifier">
<ShipAttribute name="agility" fixed={4} />x
<span title="Inertia Modifier" className={styles.statistic}>
<span>
<Icon name="inertia-modifier" size={24} />
</span>
<span>
<ShipAttribute name="agility" fixed={4} />x
</span>
</span>
</CategoryLine>
<CategoryLine>
<span title="Ship Warp Speed">
<ShipAttribute name="warpSpeedMultiplier" fixed={2} /> AU/s
<span title="Ship Warp Speed" className={styles.statistic}>
<span>
<Icon name="warp-speed" size={24} />
</span>
<span>
<ShipAttribute name="warpSpeedMultiplier" fixed={2} /> AU/s
</span>
</span>
<span title="Align Time">
<ShipAttribute name="alignTime" fixed={2} />s
<span title="Align Time" className={styles.statistic}>
<span>
<Icon name="align-time" size={24} />
</span>
<span>
<ShipAttribute name="alignTime" fixed={2} />s
</span>
</span>
</CategoryLine>
</Category>

View File

@@ -1,6 +1,7 @@
export * from './DogmaEngineProvider';
export * from './EveDataProvider';
export * from './FormatEftToEsi';
export * from './Icon';
export * from './ShipAttribute';
export * from './ShipFit';
export * from './ShipFitExtended';

1
src/settings.ts Normal file
View File

@@ -0,0 +1 @@
export const defaultDataUrl = "https://data.eveship.fit/v1.1-20231115/";