feat: show launcher/turret slots and usage above fit (#112)
This commit is contained in:
@@ -16,6 +16,7 @@ interface DogmaData {
|
||||
typeDogma?: Record<string, TypeDogma>;
|
||||
dogmaEffects?: Record<string, DogmaEffect>;
|
||||
dogmaAttributes?: Record<string, DogmaAttribute>;
|
||||
effectMapping?: Record<string, number>;
|
||||
attributeMapping?: Record<string, number>;
|
||||
}
|
||||
|
||||
@@ -44,6 +45,7 @@ function isLoaded(dogmaData: DogmaData): boolean | undefined {
|
||||
if (dogmaData.typeDogma === undefined) return undefined;
|
||||
if (dogmaData.dogmaEffects === undefined) return undefined;
|
||||
if (dogmaData.dogmaAttributes === undefined) return undefined;
|
||||
if (dogmaData.effectMapping === undefined) return undefined;
|
||||
if (dogmaData.attributeMapping === undefined) return undefined;
|
||||
|
||||
return true;
|
||||
@@ -89,25 +91,31 @@ export const EveDataProvider = (props: DogmaDataProps) => {
|
||||
}, [dataUrl]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!dogmaData.dogmaAttributes) return;
|
||||
if (!dogmaData.dogmaAttributes || !dogmaData.dogmaEffects) return;
|
||||
|
||||
/* Create a reverse mapping to quickly lookup attribute name to attribute ID. */
|
||||
/* Create a reverse mapping to quickly lookup attribute/effect name to attribute/effect ID. */
|
||||
const attributeMapping: Record<string, number> = {};
|
||||
for (const id in dogmaData.dogmaAttributes) {
|
||||
const name = dogmaData.dogmaAttributes[id].name;
|
||||
attributeMapping[name] = parseInt(id);
|
||||
}
|
||||
const effectMapping: Record<string, number> = {};
|
||||
for (const id in dogmaData.dogmaEffects) {
|
||||
const name = dogmaData.dogmaEffects[id].name;
|
||||
effectMapping[name] = parseInt(id);
|
||||
}
|
||||
|
||||
setDogmaData((prevDogmaData: DogmaData) => {
|
||||
const newDogmaData = {
|
||||
...prevDogmaData,
|
||||
attributeMapping: attributeMapping,
|
||||
effectMapping: effectMapping,
|
||||
};
|
||||
|
||||
newDogmaData.loaded = isLoaded(newDogmaData);
|
||||
return newDogmaData;
|
||||
});
|
||||
}, [dogmaData.dogmaAttributes]);
|
||||
}, [dogmaData.dogmaAttributes, dogmaData.dogmaEffects]);
|
||||
|
||||
return <EveDataContext.Provider value={dogmaData}>{props.children}</EveDataContext.Provider>;
|
||||
};
|
||||
|
||||
@@ -207,15 +207,15 @@ export const HardwareListing = () => {
|
||||
slotType = eveData.typeDogma?.[typeId]?.dogmaEffects
|
||||
.map((effect) => {
|
||||
switch (effect.effectID) {
|
||||
case 11:
|
||||
case eveData.effectMapping?.loPower:
|
||||
return "lowslot";
|
||||
case 13:
|
||||
case eveData.effectMapping?.medPower:
|
||||
return "medslot";
|
||||
case 12:
|
||||
case eveData.effectMapping?.hiPower:
|
||||
return "hislot";
|
||||
case 2663:
|
||||
case eveData.effectMapping?.rigSlot:
|
||||
return "rig";
|
||||
case 3772:
|
||||
case eveData.effectMapping?.subSystem:
|
||||
return "subsystem";
|
||||
}
|
||||
})
|
||||
|
||||
@@ -22,6 +22,8 @@ const iconMapping = {
|
||||
"fitting-lowslot": "texture/classes/fitting/filtericonlowslot.png",
|
||||
"fitting-medslot": "texture/classes/fitting/filtericonmediumslot.png",
|
||||
"fitting-rig-subsystem": "texture/classes/fitting/filtericonrigslot.png",
|
||||
"hardpoint-launcher": "texture/classes/fitting/iconlauncherhardpoint.png",
|
||||
"hardpoint-turret": "texture/classes/fitting/iconturrethardpoint.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",
|
||||
|
||||
@@ -68,6 +68,29 @@
|
||||
top: 3.5%;
|
||||
}
|
||||
|
||||
.turretLauncherIcon {
|
||||
height: 2.5%;
|
||||
margin-top: -2%;
|
||||
position: relative;
|
||||
transform: rotate(var(--reverse-rotation));
|
||||
width: 2.5%;
|
||||
}
|
||||
.turretLauncherIcon > img {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
.turretLauncherItem {
|
||||
border-radius: 50%;
|
||||
border: 1px solid #9d9d9d;
|
||||
height: 1.1%;
|
||||
margin-top: -2%;
|
||||
width: 1.1%;
|
||||
}
|
||||
.turretLauncherItemUsed {
|
||||
background-color: #707070;
|
||||
}
|
||||
|
||||
.radialMenu {
|
||||
filter: drop-shadow(0 0 2px #ffffff);
|
||||
position: absolute;
|
||||
|
||||
@@ -1,24 +1,41 @@
|
||||
import React from "react";
|
||||
import clsx from "clsx";
|
||||
|
||||
import { EveDataContext } from "../EveDataProvider";
|
||||
import { ShipSnapshotContext } from "../ShipSnapshotProvider";
|
||||
|
||||
import { FitLink } from "./FitLink";
|
||||
import { Hull } from "./Hull";
|
||||
import { Slot } from "./Slot";
|
||||
import { Icon } from "../Icon";
|
||||
import { RadialMenu } from "./RadialMenu";
|
||||
import { RingOuter } from "./RingOuter";
|
||||
import { RingInner } from "./RingInner";
|
||||
import { RingOuter } from "./RingOuter";
|
||||
import { RingTop, RingTopItem } from "./RingTop";
|
||||
import { Slot } from "./Slot";
|
||||
|
||||
import styles from "./ShipFit.module.css";
|
||||
|
||||
/**
|
||||
* Render a ship fit similar to how it is done in-game.
|
||||
*/
|
||||
export const ShipFit = () => {
|
||||
export const ShipFit = (props: { withTurrentLauncherSlots?: boolean }) => {
|
||||
const eveData = React.useContext(EveDataContext);
|
||||
const shipSnapshot = React.useContext(ShipSnapshotContext);
|
||||
const slots = shipSnapshot.slots;
|
||||
|
||||
let launcherSlotsUsed =
|
||||
shipSnapshot.items?.filter((item) =>
|
||||
eveData?.typeDogma?.[item.type_id].dogmaEffects.find(
|
||||
(effect) => effect.effectID === eveData.effectMapping?.launcherFitted,
|
||||
),
|
||||
).length ?? 0;
|
||||
let turretSlotsUsed =
|
||||
shipSnapshot.items?.filter((item) =>
|
||||
eveData?.typeDogma?.[item.type_id].dogmaEffects.find(
|
||||
(effect) => effect.effectID === eveData.effectMapping?.turretFitted,
|
||||
),
|
||||
).length ?? 0;
|
||||
|
||||
return (
|
||||
<div className={styles.fit}>
|
||||
<RingOuter />
|
||||
@@ -28,6 +45,50 @@ export const ShipFit = () => {
|
||||
<FitLink />
|
||||
|
||||
<RingTop>
|
||||
{props.withTurrentLauncherSlots && (
|
||||
<>
|
||||
<RingTopItem rotation={-45}>
|
||||
<div className={styles.turretLauncherIcon}>
|
||||
<Icon name="hardpoint-turret" size={16} />
|
||||
</div>
|
||||
</RingTopItem>
|
||||
{Array.from({ length: slots?.turret }, (_, i) => {
|
||||
turretSlotsUsed--;
|
||||
return (
|
||||
<RingTopItem key={i} rotation={-40 + i * 3}>
|
||||
<div
|
||||
className={clsx(styles.turretLauncherItem, {
|
||||
[styles.turretLauncherItemUsed]: turretSlotsUsed >= 0,
|
||||
})}
|
||||
>
|
||||
|
||||
</div>
|
||||
</RingTopItem>
|
||||
);
|
||||
})}
|
||||
|
||||
<RingTopItem rotation={43}>
|
||||
<div className={styles.turretLauncherIcon}>
|
||||
<Icon name="hardpoint-launcher" size={16} />
|
||||
</div>
|
||||
</RingTopItem>
|
||||
{Array.from({ length: slots?.launcher }, (_, i) => {
|
||||
launcherSlotsUsed--;
|
||||
return (
|
||||
<RingTopItem key={i} rotation={39 - i * 3}>
|
||||
<div
|
||||
className={clsx(styles.turretLauncherItem, {
|
||||
[styles.turretLauncherItemUsed]: launcherSlotsUsed >= 0,
|
||||
})}
|
||||
>
|
||||
|
||||
</div>
|
||||
</RingTopItem>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
|
||||
<RingTopItem rotation={-45}>
|
||||
<RadialMenu type="hislot" />
|
||||
</RingTopItem>
|
||||
|
||||
@@ -89,7 +89,7 @@ const FitName = () => {
|
||||
export const ShipFitExtended = () => {
|
||||
return (
|
||||
<div className={styles.fit}>
|
||||
<ShipFit />
|
||||
<ShipFit withTurrentLauncherSlots />
|
||||
|
||||
<div className={styles.fitName}>
|
||||
<FitName />
|
||||
|
||||
@@ -49,6 +49,8 @@ interface ShipSnapshotSlots {
|
||||
lowslot: number;
|
||||
subsystem: number;
|
||||
rig: number;
|
||||
launcher: number;
|
||||
turret: number;
|
||||
}
|
||||
|
||||
export type ShipSnapshotSlotsType = keyof ShipSnapshotSlots;
|
||||
@@ -89,6 +91,8 @@ export const ShipSnapshotContext = React.createContext<ShipSnapshot>({
|
||||
lowslot: 0,
|
||||
subsystem: 0,
|
||||
rig: 0,
|
||||
launcher: 0,
|
||||
turret: 0,
|
||||
},
|
||||
addModule: () => {},
|
||||
removeModule: () => {},
|
||||
@@ -109,6 +113,8 @@ const slotStart: Record<ShipSnapshotSlotsType, number> = {
|
||||
lowslot: 11,
|
||||
subsystem: 125,
|
||||
rig: 92,
|
||||
launcher: 27,
|
||||
turret: 27,
|
||||
};
|
||||
|
||||
export interface ShipSnapshotProps {
|
||||
@@ -137,6 +143,8 @@ export const ShipSnapshotProvider = (props: ShipSnapshotProps) => {
|
||||
lowslot: 0,
|
||||
subsystem: 0,
|
||||
rig: 0,
|
||||
launcher: 0,
|
||||
turret: 0,
|
||||
},
|
||||
addModule: () => {},
|
||||
removeModule: () => {},
|
||||
@@ -409,6 +417,8 @@ export const ShipSnapshotProvider = (props: ShipSnapshotProps) => {
|
||||
lowslot: 0,
|
||||
subsystem: 0,
|
||||
rig: 0,
|
||||
launcher: 0,
|
||||
turret: 0,
|
||||
};
|
||||
|
||||
slots.hislot = snapshot.hull.attributes.get(eveData?.attributeMapping?.hiSlots || 0)?.value || 0;
|
||||
@@ -416,12 +426,16 @@ export const ShipSnapshotProvider = (props: ShipSnapshotProps) => {
|
||||
slots.lowslot = snapshot.hull.attributes.get(eveData?.attributeMapping?.lowSlots || 0)?.value || 0;
|
||||
slots.subsystem = snapshot.hull.attributes.get(eveData?.attributeMapping?.maxSubSystems || 0)?.value || 0;
|
||||
slots.rig = snapshot.hull?.attributes.get(eveData?.attributeMapping?.rigSlots || 0)?.value || 0;
|
||||
slots.launcher = snapshot.hull?.attributes.get(eveData?.attributeMapping?.launcherSlotsLeft || 0)?.value || 0;
|
||||
slots.turret = snapshot.hull?.attributes.get(eveData?.attributeMapping?.turretSlotsLeft || 0)?.value || 0;
|
||||
|
||||
const items = snapshot.items;
|
||||
for (const item of items) {
|
||||
slots.hislot += item.attributes.get(eveData?.attributeMapping?.hiSlotModifier || 0)?.value || 0;
|
||||
slots.medslot += item.attributes.get(eveData?.attributeMapping?.medSlotModifier || 0)?.value || 0;
|
||||
slots.lowslot += item.attributes.get(eveData?.attributeMapping?.lowSlotModifier || 0)?.value || 0;
|
||||
slots.launcher += item.attributes.get(eveData?.attributeMapping?.launcherHardPointModifier || 0)?.value || 0;
|
||||
slots.turret += item.attributes.get(eveData?.attributeMapping?.turretHardPointModifier || 0)?.value || 0;
|
||||
}
|
||||
|
||||
setShipSnapshot((oldSnapshot) => {
|
||||
|
||||
Reference in New Issue
Block a user