620 lines
42 KiB
TypeScript

import React, {useEffect, useState} from "react";
import {useTheme} from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
import {WeaponUrl} from "../core/api";
import ArmorTypeNames from "../types/ArmorTypeValues";
import {
Grid2,
Table,
TableBody,
TableCell,
TableContainer, TableHead,
TableRow, ToggleButton, ToggleButtonGroup
} from "@mui/material";
import ArmorType from "./ArmorType";
import Required from "./Required";
import {AffectedResearches} from "./building/Research";
import {IMod} from "../types/Imod";
import {Irace} from "../types/Irace";
import {ModifiersProvidesTable, getIcon} from "./ModifiersProvideTable";
import {StyledPaper} from "../commons/StyledPaper";
import {StyledTableCell} from "../commons/StyledTableCell";
import AvTimerOutlinedIcon from "@mui/icons-material/AvTimer";
import {IWeapon, IWeaponResearch} from "../types/IUnit";
interface IWeaponFull {
currentTable: string;
weapon?: IWeapon;
}
export default function WeaponFull(props: {weaponId: number, isDefault: Boolean, mod: IMod, race: Irace, haveReinforceMenu: Boolean}) {
const theme = useTheme();
const isSmallMobile = useMediaQuery(theme.breakpoints.down('sm'));
const isMediumMobile = useMediaQuery(theme.breakpoints.between('sm', 'md'));
const isMobile = isSmallMobile || isMediumMobile;
const columnsPerRow = isSmallMobile ? 4 : 6;
const isDark = theme.palette.mode === 'dark';
const textColor = isDark ? '#dee2e6' : 'rgba(0, 0, 0, 0.85)';
const [weaoponFull, setWeaponFull] = useState<IWeaponFull>({
currentTable: "dps",
weapon: undefined,
});
const [enabledResearchIds, setEnabledResearchIds] = useState<Set<number>>(new Set());
function applyResearchEffects(weapon: IWeapon, enabledIds: Set<number>): IWeapon {
if (enabledIds.size === 0 || !weapon.researches || weapon.researches.length === 0) {
return weapon;
}
const modified: any = { ...weapon };
const enabledResearches = weapon.researches.filter((r: IWeaponResearch) => enabledIds.has(r.research.id));
for (const research of enabledResearches) {
if (!research.effects || research.effects.length === 0) continue;
for (const effect of research.effects) {
const usageType: string = effect.usageType;
const apply = (value: number): number => {
if (usageType.includes('multiplication')) {
return value * effect.modifierValue;
} else if (usageType.includes('addition')) {
return value + effect.modifierValue;
} else if (usageType.includes('replace')) {
return effect.modifierValue;
}
return value;
};
const field = effect.field;
switch (field) {
case 'armourPiercing':
if (!modified.weaponArmorPiercing || modified.weaponArmorPiercing.length === 0) continue;
modified.weaponArmorPiercing = modified.weaponArmorPiercing.map((p: any) => ({
...p,
piercingValue: apply(p.piercingValue),
}));
break;
case 'accuracyReductionMoving':
modified.accuracyReductionMoving = apply(modified.accuracyReductionMoving);
break;
case 'accuracy':
modified.accuracy = apply(modified.accuracy);
break;
case 'maxDamage':
modified.maxDamage = apply(modified.maxDamage);
break;
case 'maxRange':
modified.maxRange = apply(modified.maxRange);
break;
case 'minDamage':
modified.minDamage = apply(modified.minDamage);
break;
case 'reloadTime':
modified.reloadTime = apply(modified.reloadTime);
break;
case 'setupTime':
modified.setupTime = apply(modified.setupTime);
break;
}
}
}
return modified as IWeapon;
}
useEffect(() => {
fetch(WeaponUrl + "/" + props.mod.id + "/" + props.weaponId)
.then(res => res.json())
.then((weapon: IWeapon) => {
setWeaponFull({
currentTable: "dps",
weapon: weapon,
})
});
}, []);
if(weaoponFull.weapon !== undefined){
const weapon = weaoponFull.weapon
const displayWeapon = applyResearchEffects(weapon, enabledResearchIds);
function getPiercingK(armorType: string): number {
const weaponPiercing = displayWeapon.weaponArmorPiercing.find((p) => p.armorType.name === armorType)
return (typeof weaponPiercing !== "undefined" ? weaponPiercing.piercingValue : 10) / 100
}
function handleChange (e: React.MouseEvent, selectedDamageTable: string) {
setWeaponFull({
currentTable: selectedDamageTable,
weapon: weaoponFull.weapon,
});
}
if(displayWeapon.reloadTime < 0.125) displayWeapon.reloadTime = 0.125
const dpsK = (weaoponFull.currentTable == "dps") ? displayWeapon.accuracy * (1 / (displayWeapon.reloadTime - (displayWeapon.reloadTime % 0.125))) : 1
const infLowPiercing = getPiercingK(ArmorTypeNames.InfantryLow)
const infMedPiercing = getPiercingK(ArmorTypeNames.InfantryMedium)
const infHighPiercing = getPiercingK(ArmorTypeNames.InfantryHigh)
const infHeavyMedPiercing = getPiercingK(ArmorTypeNames.InfantryHeavyMedium)
const infHeavyHighPiercing = getPiercingK(ArmorTypeNames.InfantryHeavyHigh)
const demonPiercing = getPiercingK(ArmorTypeNames.DemonMedium)
const demonHighPiercing = getPiercingK(ArmorTypeNames.DemonHigh)
const commanderPiercing = getPiercingK(ArmorTypeNames.Commander)
const airPiercing = getPiercingK(ArmorTypeNames.Air)
const vehLowPiercing = getPiercingK(ArmorTypeNames.VehicleLow)
const vehMedPiercing = getPiercingK(ArmorTypeNames.VehicleMedium)
const vehHighPiercing = getPiercingK(ArmorTypeNames.VehicleHigh)
const buildingLowPiercing = getPiercingK(ArmorTypeNames.BuildingLow)
const buildingMedPiercing = getPiercingK(ArmorTypeNames.BuildingMedium)
const buildingHighPiercing = getPiercingK(ArmorTypeNames.BuildingHigh)
// UA mod
const demonLowPiercing = getPiercingK(ArmorTypeNames.DemonLow)
const buildingSuperPiercing = getPiercingK(ArmorTypeNames.BuildingSuper)
const livingMetalPiercing = getPiercingK(ArmorTypeNames.LivingMetal)
const titanPiercing = getPiercingK(ArmorTypeNames.Titan)
const getTotalDamage = (damagePiercing: number, isAir: boolean = false) => {
if (!isAir && !weapon.canAttackGround && !weapon.isMeleeWeapon) return ""
if (isAir && !weapon.canAttackAir) return ""
var minDamage = damagePiercing * displayWeapon.minDamage
var maxDamage = damagePiercing * displayWeapon.maxDamage
if (minDamage < displayWeapon.minDamageValue) {
minDamage = displayWeapon.minDamageValue
}
if (maxDamage < displayWeapon.minDamageValue) {
maxDamage = displayWeapon.minDamageValue
}
const averageDmg = (minDamage + maxDamage) / 2
return (averageDmg * dpsK).toFixed(2)
}
const getMoraleDamage = () => {
return (displayWeapon.moraleDamage * dpsK / 2).toFixed(2)
}
return (
<div style={{color: textColor}}>
<Grid2 container spacing={2}>
{!props.isDefault && <Grid2 size={12}>
<span className="weaponDescription" style={{ whiteSpace: 'pre-wrap' }}>{weapon.description}</span>
</Grid2>}
<Grid2 size={{xs: 12, md: 4}}>
<TableContainer component={StyledPaper} elevation={0}>
<Table size="small" aria-label="a dense table">
<TableBody>
<TableRow
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell component="th" scope="row" >Base damage</TableCell>
<TableCell>{displayWeapon.minDamage.toFixed(2)} {displayWeapon.maxDamage !== displayWeapon.minDamage && "- " + displayWeapon.maxDamage.toFixed(2)}</TableCell>
</TableRow>
<TableRow
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell component="th" scope="row" >Accuracy</TableCell>
<TableCell>{displayWeapon.accuracy.toFixed(3).replace(/[,.]?0+$/, '')}</TableCell>
</TableRow>
<TableRow
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell component="th" scope="row" >Accuracy moving</TableCell>
<TableCell>{displayWeapon.setupTime === 0 && displayWeapon.accuracy - displayWeapon.accuracyReductionMoving > 0 ? (displayWeapon.accuracy - displayWeapon.accuracyReductionMoving).toFixed(3).replace(/[,.]?0+$/, '') : "-"}</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Grid2>
<Grid2 size={{xs: 12, md: 4}}>
<TableContainer component={StyledPaper} elevation={0}>
<Table size="small" aria-label="a dense table">
<TableBody>
<TableRow
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell component="th" scope="row" >Reload time</TableCell>
<TableCell>{displayWeapon.reloadTime}</TableCell>
</TableRow>
<TableRow
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell component="th" scope="row" >Range</TableCell>
<TableCell>{displayWeapon.maxRange ? (displayWeapon.maxRange) : "-"} {weapon.minRange ? "(min " + (weapon.minRange) + ")" : ""}</TableCell>
</TableRow>
<TableRow
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell component="th" scope="row" >Damage radius</TableCell>
<TableCell>{weapon.damageRadius ? (weapon.damageRadius) : "-"}</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Grid2>
<Grid2 size={{xs: 12, md: 4}}>
<TableContainer component={StyledPaper} elevation={0}>
<Table size="small" aria-label="a dense table">
<TableBody>
<TableRow
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell component="th" scope="row" >Cost</TableCell>
{(weapon.costRequisition > 0 || weapon.costPower > 0) ?
<TableCell>
{weapon.costRequisition > 0 &&
<span>&nbsp;<img style={{verticalAlign: "top"}}
src="/images/Resource_requisition.gif"/>&nbsp;
{weapon.costRequisition.toFixed(0)}</span>}
{weapon.costPower > 0 &&
<span>&nbsp;<img style={{verticalAlign: "top"}}
src="/images/Resource_power.gif"/>&nbsp;
{weapon.costPower.toFixed(0)}</span>}
{(weapon.costTimeSeconds !== undefined && weapon.costTimeSeconds > 0) &&
<span>&nbsp;<AvTimerOutlinedIcon
style={{verticalAlign: "top", fontSize: "18px"}}/>&nbsp;
{weapon.costTimeSeconds}s</span>}
</TableCell> : <TableCell> - </TableCell>
}
</TableRow>
<TableRow
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell component="th" scope="row" >Setup time</TableCell>
<TableCell>{displayWeapon.setupTime != 0 ? (displayWeapon.setupTime).toFixed(3).replace(/[,.]?0+$/, '') : "-"}</TableCell>
</TableRow>
<TableRow
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell component="th" scope="row" >Throw force</TableCell>
<TableCell>{weapon.throwForceMin != 0 ? weapon.throwForceMin + " - " + weapon.throwForceMax : "-"}</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Grid2>
<Grid2 size={12}>
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 12, marginBottom: 8 }}>
<ToggleButtonGroup
color="primary"
exclusive
aria-label="Platform"
value={weaoponFull.currentTable}
onChange={handleChange}
>
<ToggleButton size="small" value="dps" sx={{ color: textColor, '&.Mui-selected': { borderColor: textColor, color: textColor, backgroundColor: isDark ? 'rgba(255, 255, 255, 0.15)' : 'rgba(0, 0, 0, 0.15)' } }}>Dps</ToggleButton>
<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>
{weapon.researches && weapon.researches.length > 0 && (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
{(() => {
// topological order: a research is always rendered to the right of its requirements
const ordered: IWeaponResearch[] = [];
const visited = new Set<number>();
const visit = (wr: IWeaponResearch) => {
if (visited.has(wr.research.id)) return;
visited.add(wr.research.id);
wr.researchRequired?.forEach(req => {
const dep = weapon.researches.find((w: IWeaponResearch) => w.research.id === req.id);
if (dep) visit(dep);
});
ordered.push(wr);
};
weapon.researches.forEach(visit);
return ordered.map((r: IWeaponResearch) => {
const rs = r.research;
const selected = enabledResearchIds.has(rs.id);
return (
<ToggleButton
key={rs.id}
value={rs.id}
size="small"
selected={selected}
onChange={() => {
const next = new Set(enabledResearchIds);
if (next.has(rs.id)) {
next.delete(rs.id);
// researches that require this one (directly or transitively) can no longer be applied
let changed = true;
while (changed) {
changed = false;
weapon.researches.forEach((wr: IWeaponResearch) => {
if (next.has(wr.research.id) && wr.researchRequired?.some(req => !next.has(req.id))) {
next.delete(wr.research.id);
changed = true;
}
});
}
} else {
next.add(rs.id);
// research can only be applied if its required researches are done
// (requirements can have their own requirements, so enable transitively)
const queue = [...(r.researchRequired ?? [])];
while (queue.length > 0) {
const req = queue.pop()!;
if (!next.has(req.id)) {
next.add(req.id);
const wr = weapon.researches.find((w: IWeaponResearch) => w.research.id === req.id);
wr?.researchRequired?.forEach(rr => queue.push(rr));
}
}
}
setEnabledResearchIds(next);
}}
sx={{
color: textColor,
borderRadius: '8px',
border: '1px solid',
borderColor: isDark ? 'rgba(255,255,255,0.23)' : 'rgba(0,0,0,0.23)',
textTransform: 'none',
'&.Mui-selected': {
borderColor: isDark ? 'rgba(25, 118, 210, 0.7)' : 'rgba(25, 118, 210, 0.5)',
color: textColor,
backgroundColor: isDark ? 'rgba(25, 118, 210, 0.3)' : 'rgba(25, 118, 210, 0.15)',
'&:hover': {
backgroundColor: isDark ? 'rgba(25, 118, 210, 0.4)' : 'rgba(25, 118, 210, 0.22)',
},
},
}}
>
{rs.icon && <img style={{height: 20, marginRight: 6, verticalAlign: 'middle'}} src={getIcon(rs.icon)} alt={rs.name}/>}
{rs.name}
</ToggleButton>
);
});
})()}
</div>
)}
</div>
<TableContainer>
{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: any[] = [];
for (let i = 0; i < items.length; i += columnsPerRow) {
chunks.push(items.slice(i, i + columnsPerRow));
}
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>
<StyledTableCell><ArmorType
name={ArmorTypeNames.InfantryLow}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.InfantryMedium}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.InfantryHigh}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.InfantryHeavyMedium}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.InfantryHeavyHigh}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.Commander}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.DemonLow}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.DemonMedium}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.DemonHigh}/></StyledTableCell>
<StyledTableCell><ArmorType name={ArmorTypeNames.Air}/></StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow sx={{'&:last-child td, &:last-child th': {border: 0}}}>
<StyledTableCell>{getTotalDamage(infLowPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(infMedPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(infHighPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(infHeavyMedPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(infHeavyHighPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(commanderPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(demonLowPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(demonPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(demonHighPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(airPiercing, true)}</StyledTableCell>
</TableRow>
</TableBody>
<TableHead>
<TableRow>
<StyledTableCell><ArmorType
name={ArmorTypeNames.VehicleLow}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.VehicleMedium}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.VehicleHigh}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.LivingMetal}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.Titan}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.BuildingLow}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.BuildingMedium}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.BuildingHigh}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.BuildingSuper}/></StyledTableCell>
<StyledTableCell><img style={{verticalAlign: "top"}}
src="/images/ARM_Morale.webp"/>
<div style={{width: 20, fontSize: 12, height: 50, color: textColor}}>
<i>Morale</i></div>
</StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow sx={{'&:last-child td, &:last-child th': {border: 0}}}>
<StyledTableCell>{getTotalDamage(vehLowPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(vehMedPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(vehHighPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(livingMetalPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(titanPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(buildingLowPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(buildingMedPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(buildingHighPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(buildingSuperPiercing)}</StyledTableCell>
<StyledTableCell>{getMoraleDamage()}</StyledTableCell>
</TableRow>
</TableBody>
</Table> :
<Table sx={{marginTop: "10px"}} size="small" aria-label="a dense table">
<TableHead>
<TableRow>
<StyledTableCell><ArmorType
name={ArmorTypeNames.InfantryLow}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.InfantryMedium}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.InfantryHigh}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.InfantryHeavyMedium}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.InfantryHeavyHigh}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.Commander}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.DemonMedium}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.DemonHigh}/></StyledTableCell>
<StyledTableCell><ArmorType name={ArmorTypeNames.Air}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.VehicleLow}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.VehicleMedium}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.VehicleHigh}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.BuildingLow}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.BuildingMedium}/></StyledTableCell>
<StyledTableCell><ArmorType
name={ArmorTypeNames.BuildingHigh}/></StyledTableCell>
<StyledTableCell><ArmorType
name='Morale damage'/>
</StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow sx={{'&:last-child td, &:last-child th': {border: 0}}}>
<StyledTableCell>{getTotalDamage(infLowPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(infMedPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(infHighPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(infHeavyMedPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(infHeavyHighPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(commanderPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(demonPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(demonHighPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(airPiercing, true)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(vehLowPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(vehMedPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(vehHighPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(buildingLowPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(buildingMedPiercing)}</StyledTableCell>
<StyledTableCell>{getTotalDamage(buildingHighPiercing)}</StyledTableCell>
<StyledTableCell>{getMoraleDamage()}</StyledTableCell>
</TableRow>
</TableBody>
</Table>
}
</TableContainer>
</Grid2>
{weapon.modifiers.length > 0 && <Grid2 size={12}>
<h3 style={{color: textColor, fontWeight: 700}}>Modifiers</h3>
<ModifiersProvidesTable modifiers={weapon.modifiers} modId={props.mod.id} race={props.race} affectedData={null}/>
</Grid2>}
{weapon.requirements !== null && !props.isDefault && props.haveReinforceMenu &&
<Grid2 size={{xs: 12, md: 12}}>
<Required requirement={weapon.requirements} modId={props.mod.id} raceId={props.race.id}/>
</Grid2>}
<Grid2 size={12}>
<AffectedResearches researches={weapon.affectedResearches} modId={props.mod.id} raceId={props.race.id} />
</Grid2>
</Grid2>
<b className="hotkey" >{!props.isDefault && props.haveReinforceMenu && <span>Hotkey: {weapon.hotkey} </span>}
<span style={{ fontSize: '12px', fontWeight: 400, color: 'rgba(128,128,128,0.7)' }}>Filename: {weapon.filename}</span></b>
</div>
)
} else return <div style={{color: 'rgba(255, 255, 255, 0.5)'}}>loading...</div>;
}