Add teleport feature
This commit is contained in:
parent
57779cacbd
commit
405b562f8f
BIN
public/images/Jump.png
Normal file
BIN
public/images/Jump.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
BIN
public/images/NoImg.png
Normal file
BIN
public/images/NoImg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
public/images/Passiveicon.png
Normal file
BIN
public/images/Passiveicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
public/images/Teleport.png
Normal file
BIN
public/images/Teleport.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
BIN
public/images/dowde.png
Normal file
BIN
public/images/dowde.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 117 KiB |
@ -29,7 +29,7 @@ function Ability(props: IAbilityProps){
|
||||
aria-controls="panel1-content"
|
||||
>
|
||||
<span style={{fontSize: 20, color: textColor, display: 'flex', alignItems: 'center'}}>
|
||||
{ability.activationType === "Passive ability" ? <img className="abilityIcon" src="/images/PassiveIcon.gif"/> : <img className="abilityIcon" src={getIcon(ability.icon)}/>}
|
||||
{ability.activationType === "Passive ability" ? <img className="abilityIcon" src="/images/PassiveIcon.png"/> : <img className="abilityIcon" src={getIcon(ability.icon)}/>}
|
||||
{ability.name ? ability.name : ability.fileName.charAt(0).toUpperCase() + ability.fileName.slice(1).replaceAll('_', ' ').replace('.rgd', '')}
|
||||
<i style={{fontSize: 12, color: 'rgba(255,255,255,0.5)'}}> ({ability.activationType})</i>
|
||||
</span>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {useTheme} from "@mui/material/styles";
|
||||
import useMediaQuery from "@mui/material/useMediaQuery";
|
||||
import {AbilityUrl, AvailableBuildings, AvailableUnits, UserUrl, WeaponUrl} from "../core/api";
|
||||
import {IWeapon} from "../types/IUnit";
|
||||
import ArmorTypeNames from "../types/ArmorTypeValues";
|
||||
@ -24,7 +25,6 @@ import AvTimerOutlinedIcon from "@mui/icons-material/AvTimer";
|
||||
import ability from "./Ability";
|
||||
import AbilitySpawnedObject from "./AbilitySpawnedObject";
|
||||
import DpsTable from "./DpsTable";
|
||||
import {DescriptionBox} from "../commons/DescriptionBox";
|
||||
import {StyledPaper} from "../commons/StyledPaper";
|
||||
import {StyledTableCell} from "../commons/StyledTableCell";
|
||||
|
||||
@ -34,6 +34,7 @@ interface IAbilityFullState {
|
||||
|
||||
export default function AbilityFull(props: { abilityId?: number, mod: IMod, race: Irace, isChild?: boolean, abilityFull?: IAbilityFill }) {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const isDark = theme.palette.mode === 'dark';
|
||||
const textColor = isDark ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)';
|
||||
|
||||
@ -181,7 +182,7 @@ export default function AbilityFull(props: { abilityId?: number, mod: IMod, race
|
||||
</TableContainer><br/>
|
||||
</Grid2>
|
||||
<Grid2 size={8}>
|
||||
{props.isChild !== true && <DescriptionBox>{ability.description}</DescriptionBox>}
|
||||
{props.isChild !== true && <span style={{ whiteSpace: 'pre-wrap' }}>{ability.description}</span>}
|
||||
</Grid2>
|
||||
{showDpsTable ?
|
||||
<Grid2 size={12}>
|
||||
@ -191,8 +192,71 @@ export default function AbilityFull(props: { abilityId?: number, mod: IMod, race
|
||||
</Grid2> : showTargetTable ?
|
||||
<Grid2 size={12}>
|
||||
<TableContainer>
|
||||
{ props.mod !== undefined && props.mod.technicalName === 'UltimateApocalypse' ?
|
||||
<Table sx={{ textAlign: "center"}} size="small" aria-label="a dense table">
|
||||
{isMobile ? (() => {
|
||||
const items = props.mod !== undefined && props.mod.technicalName === 'UltimateApocalypse' ? [
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryLow}/>, value: () => isAbilityApplyTo(ArmorTypeNames.InfantryLow) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryMedium}/>, value: () => isAbilityApplyTo(ArmorTypeNames.InfantryMedium) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHigh}/>, value: () => isAbilityApplyTo(ArmorTypeNames.InfantryHigh) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyMedium}/>, value: () => isAbilityApplyTo(ArmorTypeNames.InfantryHeavyMedium) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyHigh}/>, value: () => isAbilityApplyTo(ArmorTypeNames.InfantryHeavyHigh) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Commander}/>, value: () => isAbilityApplyTo(ArmorTypeNames.Commander) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonLow}/>, value: () => isAbilityApplyTo(ArmorTypeNames.DemonLow) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonMedium}/>, value: () => isAbilityApplyTo(ArmorTypeNames.DemonMedium) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonHigh}/>, value: () => isAbilityApplyTo(ArmorTypeNames.DemonHigh) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Air}/>, value: () => isAbilityApplyTo(ArmorTypeNames.Air) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleLow}/>, value: () => isAbilityApplyTo(ArmorTypeNames.VehicleLow) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleMedium}/>, value: () => isAbilityApplyTo(ArmorTypeNames.VehicleMedium) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleHigh}/>, value: () => isAbilityApplyTo(ArmorTypeNames.VehicleHigh) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.LivingMetal}/>, value: () => isAbilityApplyTo(ArmorTypeNames.LivingMetal) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Titan}/>, value: () => isAbilityApplyTo(ArmorTypeNames.Titan) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingLow}/>, value: () => isAbilityApplyTo(ArmorTypeNames.BuildingLow) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingMedium}/>, value: () => isAbilityApplyTo(ArmorTypeNames.BuildingMedium) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingHigh}/>, value: () => isAbilityApplyTo(ArmorTypeNames.BuildingHigh) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingSuper}/>, value: () => isAbilityApplyTo(ArmorTypeNames.BuildingSuper) },
|
||||
{ label: null, value: () => null },
|
||||
] : [
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryLow}/>, value: () => isAbilityApplyTo(ArmorTypeNames.InfantryLow) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryMedium}/>, value: () => isAbilityApplyTo(ArmorTypeNames.InfantryMedium) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHigh}/>, value: () => isAbilityApplyTo(ArmorTypeNames.InfantryHigh) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyMedium}/>, value: () => isAbilityApplyTo(ArmorTypeNames.InfantryHeavyMedium) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyHigh}/>, value: () => isAbilityApplyTo(ArmorTypeNames.InfantryHeavyHigh) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Commander}/>, value: () => isAbilityApplyTo(ArmorTypeNames.Commander) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonMedium}/>, value: () => isAbilityApplyTo(ArmorTypeNames.DemonMedium) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonHigh}/>, value: () => isAbilityApplyTo(ArmorTypeNames.DemonHigh) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Air}/>, value: () => isAbilityApplyTo(ArmorTypeNames.Air) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleLow}/>, value: () => isAbilityApplyTo(ArmorTypeNames.VehicleLow) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleMedium}/>, value: () => isAbilityApplyTo(ArmorTypeNames.VehicleMedium) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleHigh}/>, value: () => isAbilityApplyTo(ArmorTypeNames.VehicleHigh) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingLow}/>, value: () => isAbilityApplyTo(ArmorTypeNames.BuildingLow) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingMedium}/>, value: () => isAbilityApplyTo(ArmorTypeNames.BuildingMedium) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingHigh}/>, value: () => isAbilityApplyTo(ArmorTypeNames.BuildingHigh) },
|
||||
];
|
||||
|
||||
const chunks = [];
|
||||
for (let i = 0; i < items.length; i += 5) {
|
||||
chunks.push(items.slice(i, i + 5));
|
||||
}
|
||||
|
||||
return (<>{chunks.map((chunk, chunkIndex) => (
|
||||
<Table key={chunkIndex} sx={{marginTop: "10px", textAlign: "center"}} size="small" aria-label="a dense table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
{chunk.map((item, i) => (
|
||||
<StyledTableCell key={i}>{item.label}</StyledTableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
<TableRow sx={{'&:last-child td, &:last-child th': {border: 0}}}>
|
||||
{chunk.map((item, i) => (
|
||||
<StyledTableCell key={i}>{item.value()}</StyledTableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
))}</>)
|
||||
})() : props.mod !== undefined && props.mod.technicalName === 'UltimateApocalypse' ?
|
||||
<Table sx={{ textAlign: "center", minWidth: 600}} size="small" aria-label="a dense table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<StyledTableCell><ArmorType
|
||||
@ -268,7 +332,7 @@ export default function AbilityFull(props: { abilityId?: number, mod: IMod, race
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table> :
|
||||
<Table size="small" aria-label="a dense table">
|
||||
<Table sx={{ minWidth: 800 }} size="small" aria-label="a dense table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<StyledTableCell><ArmorType
|
||||
@ -324,7 +388,8 @@ export default function AbilityFull(props: { abilityId?: number, mod: IMod, race
|
||||
</Table>
|
||||
}
|
||||
</TableContainer>
|
||||
</Grid2> : <span></span>}
|
||||
</Grid2>
|
||||
: <span></span>}
|
||||
<ModifiersProvidesTable modifiers={ability.modifiers} affectedData={ability.affectedData} modId={props.mod.id} race={props.race}/>
|
||||
</Grid2>
|
||||
{(ability.abilityEnvironment != null) && <AbilitySpawnedObject abilityEnvironment={ability.abilityEnvironment} race={props.race} mod={props.mod}/>}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import React from "react";
|
||||
import {useTheme} from "@mui/material/styles";
|
||||
import useMediaQuery from "@mui/material/useMediaQuery";
|
||||
import ArmorTypeNames from "../types/ArmorTypeValues";
|
||||
import {
|
||||
Table,
|
||||
@ -14,6 +16,8 @@ import {IArmorType} from "../types/IArmorType";
|
||||
import {StyledTableCell} from "../commons/StyledTableCell";
|
||||
|
||||
export default function DpsTable(props: { mod: IMod, minDamageValue?: number, minDamage?: number, maxDamage?: number, piercings: IPiercing[], targetFilter: IArmorType[], moraleDamage?: number }) {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
|
||||
function getPiercingK(armorType: string): number|null {
|
||||
if(props.targetFilter.length > 0 && props.targetFilter.find(tf => tf.name == armorType) === undefined) return null
|
||||
@ -72,6 +76,72 @@ export default function DpsTable(props: { mod: IMod, minDamageValue?: number, mi
|
||||
if(props.moraleDamage !== undefined) return (props.moraleDamage / 2).toFixed(2)
|
||||
}
|
||||
|
||||
if (isMobile) {
|
||||
const items = props.mod !== undefined && props.mod.name.includes("Ultimate Apocalypse") ? [
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryLow}/>, value: () => getTotalDamage(infLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryMedium}/>, value: () => getTotalDamage(infMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHigh}/>, value: () => getTotalDamage(infHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyMedium}/>, value: () => getTotalDamage(infHeavyMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyHigh}/>, value: () => getTotalDamage(infHeavyHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Commander}/>, value: () => getTotalDamage(commanderPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonLow}/>, value: () => getTotalDamage(demonLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonMedium}/>, value: () => getTotalDamage(demonPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonHigh}/>, value: () => getTotalDamage(demonHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Air}/>, value: () => getTotalDamage(airPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleLow}/>, value: () => getTotalDamage(vehLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleMedium}/>, value: () => getTotalDamage(vehMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleHigh}/>, value: () => getTotalDamage(vehHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.LivingMetal}/>, value: () => getTotalDamage(livingMetalPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Titan}/>, value: () => getTotalDamage(titanPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingLow}/>, value: () => getTotalDamage(buildingLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingMedium}/>, value: () => getTotalDamage(buildingMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingHigh}/>, value: () => getTotalDamage(buildingHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingSuper}/>, value: () => getTotalDamage(buildingSuperPiercing) },
|
||||
{ label: <ArmorType name="Morale damage"/>, value: () => getMoraleDamage() },
|
||||
] : [
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryLow}/>, value: () => getTotalDamage(infLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryMedium}/>, value: () => getTotalDamage(infMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHigh}/>, value: () => getTotalDamage(infHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyMedium}/>, value: () => getTotalDamage(infHeavyMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyHigh}/>, value: () => getTotalDamage(infHeavyHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Commander}/>, value: () => getTotalDamage(commanderPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonMedium}/>, value: () => getTotalDamage(demonPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonHigh}/>, value: () => getTotalDamage(demonHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Air}/>, value: () => getTotalDamage(airPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleLow}/>, value: () => getTotalDamage(vehLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleMedium}/>, value: () => getTotalDamage(vehMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleHigh}/>, value: () => getTotalDamage(vehHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingLow}/>, value: () => getTotalDamage(buildingLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingMedium}/>, value: () => getTotalDamage(buildingMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingHigh}/>, value: () => getTotalDamage(buildingHighPiercing) },
|
||||
{ label: <ArmorType name="Morale damage"/>, value: () => getMoraleDamage() },
|
||||
];
|
||||
|
||||
const chunks = [];
|
||||
for (let i = 0; i < items.length; i += 5) {
|
||||
chunks.push(items.slice(i, i + 5));
|
||||
}
|
||||
|
||||
return (<>{chunks.map((chunk, chunkIndex) => (
|
||||
<Table key={chunkIndex} sx={{marginTop: "10px", textAlign: "center"}} size="small" aria-label="a dense table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
{chunk.map((item, i) => (
|
||||
<StyledTableCell key={i}>{item.label}</StyledTableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
<TableRow sx={{'&:last-child td, &:last-child th': {border: 0}}}>
|
||||
{chunk.map((item, i) => (
|
||||
<StyledTableCell key={i}>{item.value()}</StyledTableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
))}</>)
|
||||
}
|
||||
|
||||
return (
|
||||
<TableContainer>
|
||||
{ props.mod !== undefined && props.mod.name.includes("Ultimate Apocalypse") ?
|
||||
@ -153,7 +223,7 @@ export default function DpsTable(props: { mod: IMod, minDamageValue?: number, mi
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table> :
|
||||
<Table size="small" aria-label="a dense table">
|
||||
<Table sx={{ minWidth: 800 }} size="small" aria-label="a dense table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<StyledTableCell><ArmorType
|
||||
|
||||
100
src/classes/Jump.tsx
Normal file
100
src/classes/Jump.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
import React from "react";
|
||||
import {AccordionDetails, AccordionSummary, Grid2, Table, TableBody, TableCell, TableRow, TableContainer} from "@mui/material";
|
||||
import {ExpandMore} from "@mui/icons-material";
|
||||
import {useTheme} from "@mui/material/styles";
|
||||
import {IJumps} from "../types/IUnit";
|
||||
import {Irace} from "../types/Irace";
|
||||
import {IMod} from "../types/Imod";
|
||||
import {StyledAccordion} from "../commons/StyledAccordion";
|
||||
import {StyledPaper} from "../commons/StyledPaper";
|
||||
import Required from "./Required";
|
||||
|
||||
interface IJumpProps {
|
||||
jumps: IJumps,
|
||||
race: Irace,
|
||||
mod: IMod,
|
||||
}
|
||||
|
||||
function Jump(props: IJumpProps) {
|
||||
const theme = useTheme();
|
||||
const isDark = theme.palette.mode === 'dark';
|
||||
const textColor = isDark ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)';
|
||||
|
||||
const jumps = props.jumps;
|
||||
const isTeleport = jumps.teleport;
|
||||
const icon = isTeleport ? "/images/Teleport.png" : "/images/Jump.png";
|
||||
const title = isTeleport ? "Teleport" : "Jumps";
|
||||
|
||||
return (
|
||||
<div style={{marginBottom: 10}}>
|
||||
<StyledAccordion TransitionProps={{unmountOnExit: true, timeout: 100}}>
|
||||
<AccordionSummary
|
||||
expandIcon={<ExpandMore sx={{color: textColor}}/>}
|
||||
aria-controls="jump-content"
|
||||
id="jump-header"
|
||||
sx={{
|
||||
color: textColor,
|
||||
'& .MuiAccordionSummary-content': {margin: '12px 0'},
|
||||
'& .MuiAccordionSummary-content.Mui-expanded': {margin: '12px 0'}
|
||||
}}
|
||||
>
|
||||
<span style={{fontSize: 20, color: textColor, display: 'flex', alignItems: 'center'}}>
|
||||
<img className="jumpIcon" src={icon}/>
|
||||
{title}
|
||||
</span>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails sx={{color: textColor}}>
|
||||
<Grid2 container spacing={2}>
|
||||
{(() => {
|
||||
const rows: { label: string; value: React.ReactNode }[] = [
|
||||
{ label: "Charge cost", value: jumps.chargeJumpCostMin === jumps.chargeJumpCostMax
|
||||
? jumps.chargeJumpCostMin.toFixed(0)
|
||||
: `${jumps.chargeJumpCostMin.toFixed(0)} - ${jumps.chargeJumpCostMax.toFixed(0)}` },
|
||||
{ label: "Charge max", value: jumps.chargeMax.toFixed(0) },
|
||||
{ label: "Charge regeneration", value: `${jumps.chargeRegeneration}/s` },
|
||||
{ label: "Distance", value: jumps.jumpDistanceMax.toFixed(0) },
|
||||
{ label: "Setup time", value: <span><img style={{verticalAlign: "top"}} src="/images/Time_icon.webp"/> {jumps.setupTime}s</span> },
|
||||
{ label: "Breakdown time", value: <span><img style={{verticalAlign: "top"}} src="/images/Time_icon.webp"/> {jumps.breakdownTime}s</span> },
|
||||
];
|
||||
if (!isTeleport) {
|
||||
if (jumps.goUpTime !== undefined && jumps.goUpTime !== null) {
|
||||
rows.push({ label: "Go up time", value: <span><img style={{verticalAlign: "top"}} src="/images/Time_icon.webp"/> {jumps.goUpTime}s</span> });
|
||||
}
|
||||
if (jumps.goDownTime !== undefined && jumps.goDownTime !== null) {
|
||||
rows.push({ label: "Go down time", value: <span><img style={{verticalAlign: "top"}} src="/images/Time_icon.webp"/> {jumps.goDownTime}s</span> });
|
||||
}
|
||||
}
|
||||
const chunks: { label: string; value: React.ReactNode }[][] = [];
|
||||
for (let i = 0; i < rows.length; i += 3) {
|
||||
chunks.push(rows.slice(i, i + 3));
|
||||
}
|
||||
return chunks.map((chunk, chunkIndex) => (
|
||||
<Grid2 key={chunkIndex} size={{xs: 12, md: 4}}>
|
||||
<TableContainer component={StyledPaper} elevation={0}>
|
||||
<Table size="small" aria-label="jump stats table">
|
||||
<TableBody>
|
||||
{chunk.map((row, i) => (
|
||||
<TableRow key={i} sx={{'&:last-child td, &:last-child th': {border: 0}}}>
|
||||
<TableCell component="th" scope="row">{row.label}</TableCell>
|
||||
<TableCell>{row.value}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</Grid2>
|
||||
));
|
||||
})()}
|
||||
</Grid2>
|
||||
{jumps.requirements !== null &&
|
||||
<Grid2 size={{xs: 12, md: 12}}>
|
||||
<Required requirement={jumps.requirements} modId={props.mod.id}
|
||||
raceId={props.race.id}/>
|
||||
</Grid2>}
|
||||
</AccordionDetails>
|
||||
</StyledAccordion>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Jump;
|
||||
@ -265,7 +265,7 @@ export function ModifiersProvidesTable(props: IModifiersProvidesResearchTable) {
|
||||
export function getIcon(icon?: string): string {
|
||||
if (icon !== null && icon !== undefined) {
|
||||
return IconUrl + icon.replaceAll('\\', '/')
|
||||
} else return '/images/NoImg.gif'
|
||||
} else return '/images/NoImg.png'
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {useTheme} from "@mui/material/styles";
|
||||
import useMediaQuery from "@mui/material/useMediaQuery";
|
||||
import {AvailableBuildings, AvailableUnits, UserUrl, WeaponUrl} from "../core/api";
|
||||
import {IWeapon} from "../types/IUnit";
|
||||
import ArmorTypeNames from "../types/ArmorTypeValues";
|
||||
@ -20,7 +21,6 @@ import {Irace} from "../types/Irace";
|
||||
import {IRaceUnits} from "../types/IUnitShort";
|
||||
import {IRaceBuildings} from "../types/IBuildingShort";
|
||||
import {ModifiersProvidesTable} from "./ModifiersProvideTable";
|
||||
import {DescriptionBox} from "../commons/DescriptionBox";
|
||||
import {StyledPaper} from "../commons/StyledPaper";
|
||||
import {StyledTableCell} from "../commons/StyledTableCell";
|
||||
import AvTimerOutlinedIcon from "@mui/icons-material/AvTimer";
|
||||
@ -32,6 +32,7 @@ interface IWeaponFull {
|
||||
|
||||
export default function WeaponFull(props: {weaponId: number, isDefault: Boolean, mod: IMod, race: Irace, haveReinforceMenu: Boolean}) {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const isDark = theme.palette.mode === 'dark';
|
||||
const textColor = isDark ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)';
|
||||
|
||||
@ -54,8 +55,6 @@ export default function WeaponFull(props: {weaponId: number, isDefault: Boolean,
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
|
||||
if(weaoponFull.weapon !== undefined){
|
||||
|
||||
const weapon = weaoponFull.weapon
|
||||
@ -126,9 +125,7 @@ export default function WeaponFull(props: {weaponId: number, isDefault: Boolean,
|
||||
<div style={{color: textColor}}>
|
||||
<Grid2 container spacing={2}>
|
||||
{!props.isDefault && <Grid2 size={12}>
|
||||
<DescriptionBox>
|
||||
<span className="weaponDescription">{weapon.description}</span>
|
||||
</DescriptionBox>
|
||||
<span className="weaponDescription" style={{ whiteSpace: 'pre-wrap' }}>{weapon.description}</span>
|
||||
</Grid2>}
|
||||
|
||||
<Grid2 size={{xs: 12, md: 4}}>
|
||||
@ -238,7 +235,71 @@ export default function WeaponFull(props: {weaponId: number, isDefault: Boolean,
|
||||
<ToggleButton size="small" value="one hit" sx={{ color: textColor, '&.Mui-selected': {borderColor: textColor, color: textColor, backgroundColor: isDark ? 'rgba(255, 255, 255, 0.15)' : 'rgba(0, 0, 0, 0.15)' } }}>One hit average damage</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
<TableContainer>
|
||||
{ props.mod !== undefined && props.mod.technicalName === 'UltimateApocalypse' ?
|
||||
{isMobile ? (() => {
|
||||
const items = props.mod !== undefined && props.mod.technicalName === 'UltimateApocalypse' ? [
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryLow}/>, value: () => getTotalDamage(infLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryMedium}/>, value: () => getTotalDamage(infMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHigh}/>, value: () => getTotalDamage(infHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyMedium}/>, value: () => getTotalDamage(infHeavyMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyHigh}/>, value: () => getTotalDamage(infHeavyHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Commander}/>, value: () => getTotalDamage(commanderPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonLow}/>, value: () => getTotalDamage(demonLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonMedium}/>, value: () => getTotalDamage(demonPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonHigh}/>, value: () => getTotalDamage(demonHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Air}/>, value: () => getTotalDamage(airPiercing, true) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleLow}/>, value: () => getTotalDamage(vehLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleMedium}/>, value: () => getTotalDamage(vehMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleHigh}/>, value: () => getTotalDamage(vehHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.LivingMetal}/>, value: () => getTotalDamage(livingMetalPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Titan}/>, value: () => getTotalDamage(titanPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingLow}/>, value: () => getTotalDamage(buildingLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingMedium}/>, value: () => getTotalDamage(buildingMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingHigh}/>, value: () => getTotalDamage(buildingHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingSuper}/>, value: () => getTotalDamage(buildingSuperPiercing) },
|
||||
{ label: (<><img style={{verticalAlign: "top"}} src="/images/ARM_Morale.webp"/><div style={{width: 20, fontSize: 12, height: 50, color: textColor}}><i>Morale</i></div></>), value: () => getMoraleDamage() },
|
||||
] : [
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryLow}/>, value: () => getTotalDamage(infLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryMedium}/>, value: () => getTotalDamage(infMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHigh}/>, value: () => getTotalDamage(infHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyMedium}/>, value: () => getTotalDamage(infHeavyMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.InfantryHeavyHigh}/>, value: () => getTotalDamage(infHeavyHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Commander}/>, value: () => getTotalDamage(commanderPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonMedium}/>, value: () => getTotalDamage(demonPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.DemonHigh}/>, value: () => getTotalDamage(demonHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.Air}/>, value: () => getTotalDamage(airPiercing, true) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleLow}/>, value: () => getTotalDamage(vehLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleMedium}/>, value: () => getTotalDamage(vehMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.VehicleHigh}/>, value: () => getTotalDamage(vehHighPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingLow}/>, value: () => getTotalDamage(buildingLowPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingMedium}/>, value: () => getTotalDamage(buildingMedPiercing) },
|
||||
{ label: <ArmorType name={ArmorTypeNames.BuildingHigh}/>, value: () => getTotalDamage(buildingHighPiercing) },
|
||||
{ label: <ArmorType name="Morale damage"/>, value: () => getMoraleDamage() },
|
||||
];
|
||||
|
||||
const chunks = [];
|
||||
for (let i = 0; i < items.length; i += 5) {
|
||||
chunks.push(items.slice(i, i + 5));
|
||||
}
|
||||
|
||||
return chunks.map((chunk, chunkIndex) => (
|
||||
<Table key={chunkIndex} sx={{marginTop: "10px", textAlign: "center"}} size="small" aria-label="a dense table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
{chunk.map((item, i) => (
|
||||
<StyledTableCell key={i}>{item.label}</StyledTableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
<TableRow sx={{'&:last-child td, &:last-child th': {border: 0}}}>
|
||||
{chunk.map((item, i) => (
|
||||
<StyledTableCell key={i}>{item.value()}</StyledTableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
));
|
||||
})() : props.mod !== undefined && props.mod.technicalName === 'UltimateApocalypse' ?
|
||||
<Table sx={{marginTop: "10px", textAlign: "center"}} size="small" aria-label="a dense table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
@ -378,7 +439,6 @@ export default function WeaponFull(props: {weaponId: number, isDefault: Boolean,
|
||||
</TableBody>
|
||||
</Table>
|
||||
}
|
||||
|
||||
</TableContainer>
|
||||
|
||||
</Grid2>
|
||||
|
||||
@ -18,7 +18,6 @@ import {IMod} from "../../types/Imod";
|
||||
import {getIcon, ModifiersProvidesTable,} from "../ModifiersProvideTable";
|
||||
import Required from "../Required";
|
||||
import {StyledAccordion} from "../../commons/StyledAccordion";
|
||||
import {DescriptionBox} from "../../commons/DescriptionBox";
|
||||
import {StyledPaper} from "../../commons/StyledPaper";
|
||||
import {styled} from "@mui/material/styles";
|
||||
|
||||
@ -92,9 +91,7 @@ function BuildingAddon(props: IBuildingAddonProps){
|
||||
</TableContainer><br/>
|
||||
</Grid2>
|
||||
<Grid2 size={{xs: 12, md: 8}}>
|
||||
<DescriptionBox>
|
||||
{addon.description}
|
||||
</DescriptionBox>
|
||||
<span style={{ whiteSpace: 'pre-wrap' }}>{addon.description}</span>
|
||||
</Grid2>
|
||||
<ModifiersProvidesTable modifiers={addon.addonModifiers} affectedData={addon.affectedData} modId={props.mod.id} race={building.race}/>
|
||||
{addon.addonRequirement !== null &&
|
||||
|
||||
@ -22,7 +22,6 @@ import {IResearchShort} from "../../types/IResearchShort";
|
||||
import {ResearchUrl, WeaponUrl} from "../../core/api";
|
||||
import {IWeapon} from "../../types/IUnit";
|
||||
import {styled} from '@mui/material/styles';
|
||||
import {DescriptionBox} from "../../commons/DescriptionBox";
|
||||
import {StyledPaper} from "../../commons/StyledPaper";
|
||||
|
||||
|
||||
@ -96,10 +95,7 @@ function ResearchFull(props: { id: number, building: IBuilding }){
|
||||
</TableContainer><br/>
|
||||
</Grid2>
|
||||
<Grid2 size={{xs: 12, md: 8}}>
|
||||
<DescriptionBox>
|
||||
{research.description}
|
||||
</DescriptionBox>
|
||||
|
||||
<span style={{ whiteSpace: 'pre-wrap' }}>{research.description}</span>
|
||||
</Grid2>
|
||||
<Grid2 size={{xs: 12, md: 12}}>
|
||||
<ModifiersProvidesTable modifiers={research.modifiers} affectedData={research.affectedData}
|
||||
|
||||
@ -17,6 +17,10 @@ export const StyledTableCell = styled(TableCell)(({theme}) => {
|
||||
color: textColor,
|
||||
paddingRight: 18,
|
||||
paddingLeft: 10,
|
||||
[theme.breakpoints.down('md')]: {
|
||||
paddingRight: 4,
|
||||
paddingLeft: 2,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@ -21,6 +21,11 @@
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.jumpIcon{
|
||||
padding: 0px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.unitHeader{
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
@ -183,7 +183,6 @@ function Mods({ mods }: ModsProps) {
|
||||
const sameMods = mapWithModVersions.get(modName) ?? [];
|
||||
// The latest version is the one with the maximum id
|
||||
const latest = sameMods.reduce((max, mod) => mod.id > max.id ? mod : max, sameMods[0]);
|
||||
const nonBetaMods = sameMods.filter(m => !m.isBeta);
|
||||
const betaMods = sameMods.filter(m => m.isBeta);
|
||||
return {
|
||||
latest: latest,
|
||||
@ -329,7 +328,7 @@ class ModsPage extends React.Component<any, ModsPageState> {
|
||||
const response = await fetch(AvailableMods);
|
||||
const data: IMod[] = await response.json();
|
||||
this.setState({
|
||||
mods: data,
|
||||
mods: data.filter(mod => !mod.isHide),
|
||||
loading: false
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@ -33,6 +33,7 @@ import {AffectedResearches} from "../classes/building/Research";
|
||||
import {ModifiersProvidesTable} from "../classes/ModifiersProvideTable";
|
||||
import Ability from "../classes/Ability";
|
||||
import DeathExplosion from "../classes/DeathExplosion";
|
||||
import Jump from "../classes/Jump";
|
||||
import {styled} from '@mui/material/styles';
|
||||
import {withTheme} from "../core/api";
|
||||
import {DescriptionBox} from "../commons/DescriptionBox";
|
||||
@ -337,7 +338,7 @@ function Unit(unit: IUnit, mod: IMod, theme: Theme) {
|
||||
unit.moraleBrakeModifiers.find(m => m.reference.includes("speed_maximum_modifier") && m.value === 1.2) !== undefined &&
|
||||
unit.moraleBrakeModifiers.length === 2)
|
||||
&& <Grid2 size={12}>
|
||||
<SectionTitle><img style={{verticalAlign: "top"}} src="/images/ARM_Morale.webp"/> Morale broken unusual behavior <img style={{verticalAlign: "top"}} src="/images/ARM_Morale.webp"/></SectionTitle>
|
||||
<SectionTitle><img style={{verticalAlign: "top"}} src="/images/ARM_Morale.webp"/> Morale broken <img style={{verticalAlign: "top"}} src="/images/ARM_Morale.webp"/></SectionTitle>
|
||||
<ModifiersProvidesTable modifiers={unit.moraleBrakeModifiers} modId={unit.modId} race={unit.race} affectedData={unit.affectedData}/>
|
||||
</Grid2>}
|
||||
|
||||
@ -353,6 +354,11 @@ function Unit(unit: IUnit, mod: IMod, theme: Theme) {
|
||||
)}
|
||||
</Grid2>}
|
||||
|
||||
{unit.jumps != null && <Grid2 size={12}>
|
||||
<SectionTitle>Jumps</SectionTitle>
|
||||
<Jump jumps={unit.jumps} race={unit.race} mod={mod}/>
|
||||
</Grid2>}
|
||||
|
||||
<Grid2 size={12}>
|
||||
{[...mapWithUnitWeapons.keys()].sort(function (a, b) {
|
||||
return a - b;
|
||||
|
||||
@ -61,8 +61,8 @@ export const lightTheme = createTheme({
|
||||
paper: '#ffffff',
|
||||
},
|
||||
text: {
|
||||
primary: 'rgba(0, 0, 0, 0.85)',
|
||||
secondary: 'rgba(0, 0, 0, 0.6)',
|
||||
primary: '#111111',
|
||||
secondary: '#333333',
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
@ -75,7 +75,7 @@ export const lightTheme = createTheme({
|
||||
MuiTableCell: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: 'rgba(0, 0, 0, 0.85)',
|
||||
color: '#111111',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -13,6 +13,21 @@ export interface IUnitResponse {
|
||||
units: IUnit[]
|
||||
}
|
||||
|
||||
export interface IJumps {
|
||||
chargeRegeneration: number;
|
||||
goUpTime?: number;
|
||||
jumpDistanceMax: number;
|
||||
breakdownTime: number;
|
||||
chargeJumpCostMin: number;
|
||||
chargeJumpCostMax: number;
|
||||
jumpHeight: number;
|
||||
chargeMax: number;
|
||||
setupTime: number;
|
||||
goDownTime?: number;
|
||||
teleport: boolean;
|
||||
requirements: IRequirement | null;
|
||||
}
|
||||
|
||||
export interface IUnit {
|
||||
id: number
|
||||
race: Irace
|
||||
@ -69,6 +84,7 @@ export interface IUnit {
|
||||
affectedData: IAffectedData,
|
||||
affectedResearches: IResearchShort[],
|
||||
deathExplosions: IDeathExplosion[],
|
||||
jumps?: IJumps | null,
|
||||
hotkey?: string,
|
||||
}
|
||||
|
||||
|
||||
@ -5,4 +5,5 @@ export interface IMod {
|
||||
version: string;
|
||||
technicalName: string;
|
||||
isBeta: boolean;
|
||||
isHide: boolean;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user