diff --git a/public/images/ARM_Dmn_Lo.webp b/public/images/ARM_Dmn_Lo.webp new file mode 100644 index 0000000..62eb7dd Binary files /dev/null and b/public/images/ARM_Dmn_Lo.webp differ diff --git a/public/images/ARM_building_super.webp b/public/images/ARM_building_super.webp new file mode 100644 index 0000000..7759026 Binary files /dev/null and b/public/images/ARM_building_super.webp differ diff --git a/public/images/ARM_living_metal.webp b/public/images/ARM_living_metal.webp new file mode 100644 index 0000000..18dbf81 Binary files /dev/null and b/public/images/ARM_living_metal.webp differ diff --git a/public/images/ARM_titan.webp b/public/images/ARM_titan.webp new file mode 100644 index 0000000..d6d44d1 Binary files /dev/null and b/public/images/ARM_titan.webp differ diff --git a/src/classes/ArmorType.tsx b/src/classes/ArmorType.tsx index d27b539..679e389 100644 --- a/src/classes/ArmorType.tsx +++ b/src/classes/ArmorType.tsx @@ -26,6 +26,8 @@ class ArmorType extends React.Component { return '/images/ARM_Hvy_Inf_Hi.webp'; case 'Commander': return '/images/ARM_Cmdr.webp'; + case 'Living Metal': + return '/images/ARM_living_metal.webp'; case 'Vehicle Low': return '/images/ARM_Veh_Lo.webp'; case 'Vehicle Medium': @@ -40,10 +42,16 @@ class ArmorType extends React.Component { return '/images/ARM_Bld_Mid.webp'; case 'Building High': return '/images/ARM_Bld_Hi.webp'; + case 'Building Super': + return '/images/ARM_building_super.webp'; + case 'Demon Low': + return '/images/ARM_Dmn_Lo.webp'; case 'Demon Medium': return '/images/ARM_Dmn_Mid.webp'; case 'Demon High': return '/images/ARM_Dmn_Hi.webp'; + case 'Titan': + return '/images/ARM_titan.webp'; default: return armorTypeId; } diff --git a/src/classes/Sergeant.tsx b/src/classes/Sergeant.tsx index dc318aa..059c272 100644 --- a/src/classes/Sergeant.tsx +++ b/src/classes/Sergeant.tsx @@ -17,11 +17,13 @@ import ArmorType from "./ArmorType"; import {ExpandMore} from "@mui/icons-material"; import WeaponSlot from "./WeaponSlot"; import Vision from "./Vision"; +import {IMod} from "../types/Imod"; export interface SergeantProps { - sergeant: ISergeant + sergeant: ISergeant, + mod: IMod } const Sergeant = (props: SergeantProps) => { @@ -51,7 +53,7 @@ const Sergeant = (props: SergeantProps) => { - cost + Cost {sergeant.buildCostRequisition > 0 &&   { {sergeant.buildCostTime}s} + {(sergeant.requisitionIncome !== undefined && sergeant.requisitionIncome !== null || sergeant.powerIncome !== undefined && sergeant.powerIncome !== null || sergeant.faithIncome !== undefined && sergeant.faithIncome !== null) && + + Resource income + + {sergeant.requisitionIncome !== undefined && sergeant.requisitionIncome > 0 && +    + {sergeant.requisitionIncome}} + {sergeant.powerIncome !== undefined && sergeant.powerIncome > 0 && +    + {sergeant.powerIncome}} + {sergeant.faithIncome !== undefined && sergeant.faithIncome > 0 && +    + {sergeant.faithIncome}} + + + } - armor type + Armor type @@ -85,7 +106,7 @@ const Sergeant = (props: SergeantProps) => { - health + Health   @@ -96,7 +117,7 @@ const Sergeant = (props: SergeantProps) => { - morale + Morale -{sergeant.moraleDeathPenalty} @@ -105,7 +126,7 @@ const Sergeant = (props: SergeantProps) => { - detect + Detect @@ -123,7 +144,7 @@ const Sergeant = (props: SergeantProps) => { {[...mapWithUnitWeapons.keys()].sort(function (a, b) { return a - b; - }).map(h => )} + }).map(h => )} {sergeant.filename} diff --git a/src/classes/Weapon.tsx b/src/classes/Weapon.tsx index 32bcf5e..de89ce9 100644 --- a/src/classes/Weapon.tsx +++ b/src/classes/Weapon.tsx @@ -20,10 +20,12 @@ import ArmorTypeNames from "../types/ArmorTypeValues"; import {IconUrl} from "../core/api"; import {ExpandMore} from "@mui/icons-material"; import Sergeant from "./Sergeant"; +import {IMod} from "../types/Imod"; interface IWeaponProps { weapon: IWeapon, isDefault: Boolean, + mod: IMod, } interface IWeaponState { @@ -85,6 +87,12 @@ class Weapon extends React.Component { const buildingMedPiercing = this.getPiercingK(ArmorTypeNames.BuildingMedium) const buildingHighPiercing = this.getPiercingK(ArmorTypeNames.BuildingHigh) + // UA mod + const demonLowPiercing = this.getPiercingK(ArmorTypeNames.DemonLow) + const buildingSuperPiercing = this.getPiercingK(ArmorTypeNames.BuildingSuper) + const livingMetalPiercing = this.getPiercingK(ArmorTypeNames.LivingMetal) + const titanPiercing = this.getPiercingK(ArmorTypeNames.Titan) + const getTotalDamage = (damagePiercing: number, isAir: boolean = false) => { if (!isAir && !weapon.canAttackGround && !weapon.isMeleeWeapon) return "" @@ -155,7 +163,7 @@ class Weapon extends React.Component { > Base damage {weapon.minDamage} {weapon.maxDamage !== weapon.minDamage && -weapon.maxDamage} + scope="row">{weapon.minDamage} {weapon.maxDamage !== weapon.minDamage && "- " + weapon.maxDamage} { One hit average damage - - - - - - - - - - - - - - - - - - - - - - - - {getTotalDamage(infLowPiercing)} - {getTotalDamage(infMedPiercing)} - {getTotalDamage(infHighPiercing)} - {getTotalDamage(infHeavyMedPiercing)} - {getTotalDamage(infHeavyHighPiercing)} - {getTotalDamage(commanderPiercing)} - {getTotalDamage(demonPiercing)} - {getTotalDamage(demonHighPiercing)} - {getTotalDamage(airPiercing, true)} - {getTotalDamage(vehLowPiercing)} - {getTotalDamage(vehMedPiercing)} - {getTotalDamage(vehHighPiercing)} - {getTotalDamage(buildingLowPiercing)} - {getTotalDamage(buildingMedPiercing)} - {getTotalDamage(buildingHighPiercing)} - {getMoraleDamage()} - - -
+ { this.props.mod !== undefined && this.props.mod.name.includes("Ultimate Apocalypse") ? + + + + + + + + + + + + + + + + + + {getTotalDamage(infLowPiercing)} + {getTotalDamage(infMedPiercing)} + {getTotalDamage(infHighPiercing)} + {getTotalDamage(infHeavyMedPiercing)} + {getTotalDamage(infHeavyHighPiercing)} + {getTotalDamage(commanderPiercing)} + {getTotalDamage(demonLowPiercing)} + {getTotalDamage(demonPiercing)} + {getTotalDamage(demonHighPiercing)} + {getTotalDamage(airPiercing, true)} + + + + + + + + + + + + + + + + + + + {getTotalDamage(vehLowPiercing)} + {getTotalDamage(vehMedPiercing)} + {getTotalDamage(vehHighPiercing)} + {getTotalDamage(livingMetalPiercing)} + {getTotalDamage(titanPiercing)} + {getTotalDamage(buildingLowPiercing)} + {getTotalDamage(buildingMedPiercing)} + {getTotalDamage(buildingHighPiercing)} + {getTotalDamage(buildingSuperPiercing)} + {getMoraleDamage()} + + +
: + + + + + + + + + + + + + + + + + + + + + + + + {getTotalDamage(infLowPiercing)} + {getTotalDamage(infMedPiercing)} + {getTotalDamage(infHighPiercing)} + {getTotalDamage(infHeavyMedPiercing)} + {getTotalDamage(infHeavyHighPiercing)} + {getTotalDamage(commanderPiercing)} + {getTotalDamage(demonPiercing)} + {getTotalDamage(demonHighPiercing)} + {getTotalDamage(airPiercing, true)} + {getTotalDamage(vehLowPiercing)} + {getTotalDamage(vehMedPiercing)} + {getTotalDamage(vehHighPiercing)} + {getTotalDamage(buildingLowPiercing)} + {getTotalDamage(buildingMedPiercing)} + {getTotalDamage(buildingHighPiercing)} + {getMoraleDamage()} + + +
+ } +
{weapon.filename} diff --git a/src/classes/WeaponSlot.tsx b/src/classes/WeaponSlot.tsx index 37da11d..0ea2258 100644 --- a/src/classes/WeaponSlot.tsx +++ b/src/classes/WeaponSlot.tsx @@ -1,10 +1,12 @@ import Weapon from "./Weapon"; import React from "react"; import {IWeapon} from "../types/IUnit"; +import {IMod} from "../types/Imod"; export interface WeaponSlotProps { hardpoint: number, unitWeapons: Map | undefined, + mod: IMod, showOnlyDefault?: boolean , } @@ -31,7 +33,7 @@ const WeaponSlot= (props: WeaponSlotProps) => { return (

{header}

-
+
) } @@ -41,7 +43,7 @@ const WeaponSlot= (props: WeaponSlotProps) => {

{header}

{weaponsSorted.filter(wp => !wp[1].filename.includes("dummy")).map(wp => -
+
)} ) diff --git a/src/classes/building/BuildingAddon.tsx b/src/classes/building/BuildingAddon.tsx index 938f1e6..b2eb7cb 100644 --- a/src/classes/building/BuildingAddon.tsx +++ b/src/classes/building/BuildingAddon.tsx @@ -19,6 +19,7 @@ import {ExpandMore} from "@mui/icons-material"; import {IconUrl} from "../../core/api"; import {IBuildingShort} from "../../types/IBuildingShort"; import {goToAddon} from "../../pages/BuildingPage"; +import {IMod} from "../../types/Imod"; interface IAddonModifiersProvidesTable{ modifiers: IAddonModifier[], @@ -34,10 +35,22 @@ function AddonModifiersProvidesTable (props: IAddonModifiersProvidesTable) { return 'Health'; case 'modifiers\\keen_sight_radius_modifier.lua': return 'Detect'; + case 'modifiers\\sight_radius_modifier.lua': + return 'Sight'; case 'modifiers\\garrison_requisition_modifier.lua': return 'Requisition'; + case 'modifiers\\faith_max_modifier.lua': + return 'Faith max'; + case 'modifiers\\holy_icon_cost_power.lua': + return Next icon cost ; + case 'modifiers\\holy_icon_cost_requisition.lua': + return Next icon cost ; + case 'modifiers\\enable_hardpoint_02.lua': + return 'Weapon slot 2'; + case 'modifiers\\cost_requisition_modifier.lua': + return 'Requisition cost'; default: - return mt; + return mt.replace("modifiers\\", "").replace("modifier.lua", "").replace(".lua", "").replaceAll("_", " "); } } @@ -49,23 +62,35 @@ function AddonModifiersProvidesTable (props: IAddonModifiersProvidesTable) { return ; case 'modifiers\\keen_sight_radius_modifier.lua': return ; + case 'modifiers\\sight_radius_modifier.lua': + return ; + case 'modifiers\\faith_max_modifier.lua': + return ; case 'modifiers\\garrison_requisition_modifier.lua': return ; + case 'modifiers\\cost_requisition_modifier.lua': + return ; default: - return mt; + return ""; } } - function getChangeDescription(ref: String) { + function getChangeDescription(ref: String, v: number) { switch(ref) { case 'type_modifierusagetype\\tp_mod_usage_addition.lua': - return '+'; + if(v < 0){ + return v + }else return '+' + v; case 'type_modifierusagetype\\tp_mod_usage_multiplication.lua': - return 'x'; + return 'x' + v; case 'type_modifierusagetype\\tp_mod_usage_percentage.lua': - return '%'; + return '%' + v; case 'type_modifierusagetype\\tp_mod_usage_enable.lua': - return ' enable '; + if(v === 1){ + return ' enable '; + } else { + return ' disable '; + } default: return ref; } @@ -81,7 +106,7 @@ function AddonModifiersProvidesTable (props: IAddonModifiersProvidesTable) { sx={{'&:last-child td, &:last-child th': {border: 0}}} > {getModName(m.reference)} - {getModIcon(m.reference)} {getChangeDescription(m.usageType)}{m.value} + {getModIcon(m.reference)} {getChangeDescription(m.usageType, m.value)}
)} @@ -92,7 +117,8 @@ function AddonModifiersProvidesTable (props: IAddonModifiersProvidesTable) { interface IAddonModifiersProvidesWeapons{ modifiers: IAddonModifier[], replacedAddonModifiers: IAddonModifier[], - weapons: WeaponHardpoint[] + weapons: WeaponHardpoint[], + mod: IMod, } function AddonModifiersProvidesWeapons (props: IAddonModifiersProvidesWeapons) { @@ -107,7 +133,7 @@ function AddonModifiersProvidesWeapons (props: IAddonModifiersProvidesWeapons) { let weapon = props.weapons.find(w => w.hardpoint === hardpoint && w.hardpointOrder === 1 + value )?.weapon if (weapon != null){ - return ; + return ; }else{ return "Can't find weapon, replaced by addon:" + value + " - " } @@ -126,7 +152,8 @@ function AddonModifiersProvidesWeapons (props: IAddonModifiersProvidesWeapons) { interface IBuildingAddonProps { addon: IBuildingAddon, - building: IBuilding + building: IBuilding, + mod: IMod, } function BuildingAddon(props: IBuildingAddonProps){ @@ -145,12 +172,12 @@ function BuildingAddon(props: IBuildingAddonProps){ return requirementBuildings.length > 0 && ( + {requirementBuildings[1] !== undefined && or   +  {" "} + {requirementBuildings[1].name} } ); } @@ -158,7 +185,7 @@ function BuildingAddon(props: IBuildingAddonProps){ return
{rgas.map(rga =>   Global addon: -   +   {rga.name} )}
@@ -224,7 +251,7 @@ function BuildingAddon(props: IBuildingAddonProps){ {addon.addonModifiers !== null && - + } {addon.addonRequirement !== null && @@ -244,7 +271,7 @@ function BuildingAddon(props: IBuildingAddonProps){ {addon.addonRequirement.requirementBuildings.map(b =>
  Building:   - {b.name}
) + {b.name}) } {addon.addonRequirement.requirementBuildingsEither.length !== 0 && renderRequirementBuilding(addon.addonRequirement.requirementBuildingsEither, building)} diff --git a/src/css/Unit.css b/src/css/Unit.css index ecf8391..4b2aae1 100644 --- a/src/css/Unit.css +++ b/src/css/Unit.css @@ -2,6 +2,11 @@ width: 50px; } +.unitIconSmall{ + width: 35px; + margin-left: 30px; +} + .weaponIcon{ width: 40px; } diff --git a/src/pages/BuildingPage.tsx b/src/pages/BuildingPage.tsx index e554716..533d9f9 100644 --- a/src/pages/BuildingPage.tsx +++ b/src/pages/BuildingPage.tsx @@ -79,6 +79,25 @@ function Building(building: IBuilding, mod: IMod) { {building.buildCostTime}s
}
+ {(building.requisitionIncome !== undefined && building.requisitionIncome > 0 || building.powerIncome !== undefined && building.powerIncome !== null || building.faithIncome !== undefined && building.faithIncome !== null) && + + Resource income + + {building.requisitionIncome !== undefined && building.requisitionIncome != null && +    + {building.requisitionIncome}} + {building.powerIncome !== undefined && building.powerIncome > 0 && +    + {building.powerIncome}} + {building.faithIncome !== undefined && building.faithIncome > 0 && +    + {building.faithIncome}} + + + } @@ -126,13 +145,13 @@ function Building(building: IBuilding, mod: IMod) { {building.addons.length > 0 &&

Addons

{building.addons.map(b => - + )}
} {[...mapBuildingWeapons.keys()].sort(function (a, b) { return a - b; - }).map(h => )} + }).map(h => )} {building.filename} diff --git a/src/pages/RacePageFast.tsx b/src/pages/RacePageFast.tsx index 5e6b435..19fb2e5 100644 --- a/src/pages/RacePageFast.tsx +++ b/src/pages/RacePageFast.tsx @@ -26,7 +26,7 @@ import { ToggleButtonGroup, Typography } from "@mui/material"; -import {ArrowBack, ArrowDropDown} from "@mui/icons-material"; +import {ArrowBack, ArrowDropDown, ExpandMore} from "@mui/icons-material"; import ArmorType from "../classes/ArmorType"; import Weapon from "../classes/Weapon"; import {IRaceUnits, IUnitShort} from "../types/IUnitShort"; @@ -50,15 +50,34 @@ function Unit (unit: IUnitShort, modId: number, raceId: String) { ) } +function UnitSmall (unit: IUnitShort, modId: number, raceId: String) { + + var unitName = "" + if (unit.name.length > 21) { + unitName = unit.name.substring(0, 20) + "..."; + } else { + unitName = unit.name; + } + + return ( + {unit.icon && } + {unitName} + {unit.canDetect &&  }
) +} + function Building (building: IBuildingShort, modId: number, raceId: String) { - return ( + return ( {building.icon && } {building.name} {building.canDetect &&  } - ) + + + {building.units.map(unit => UnitSmall(unit, modId, raceId))} + ) } interface UnitsProps{ @@ -108,28 +127,38 @@ class Units extends React.Component { {this.state.units != null && this.state.buildings != null ? - -

Infantry

- {this.state.units.infantry.map(unit => Unit(unit, this.props.modId, this.props.raceId))} -
- -

Tech

- - {this.state.units.tech.map(unit => Unit(unit, this.props.modId, this.props.raceId))} - -
- -

Support

- - {this.state.units.support.map(unit => Unit(unit, this.props.modId, this.props.raceId))} - -
- -

Buildings

- - {this.state.buildings.buildings.map(building => Building(building, this.props.modId, this.props.raceId))} - -
+ + + {this.state.buildings.buildings.map(building => Building(building, this.props.modId, this.props.raceId))} + + + } + aria-controls="units-accordion" + id="units-accordion" + > +

All units

+
+ + +

Infantry

+ {this.state.units.infantry.map(unit => Unit(unit, this.props.modId, this.props.raceId))} +
+ +

Tech

+ + {this.state.units.tech.map(unit => Unit(unit, this.props.modId, this.props.raceId))} + +
+ +

Support

+ + {this.state.units.support.map(unit => Unit(unit, this.props.modId, this.props.raceId))} + +
+
+
+

: "Loading"} diff --git a/src/pages/UnitPage.tsx b/src/pages/UnitPage.tsx index 8413f8e..a845c7c 100644 --- a/src/pages/UnitPage.tsx +++ b/src/pages/UnitPage.tsx @@ -156,6 +156,25 @@ function Unit(unit: IUnit, mod: IMod) {
} + {(unit.requisitionIncome !== undefined && unit.requisitionIncome !== null || unit.powerIncome !== undefined && unit.powerIncome !== null || unit.faithIncome !== undefined && unit.faithIncome !== null) && + + Resource income + + {unit.requisitionIncome !== undefined && unit.requisitionIncome > 0 && +    + {unit.requisitionIncome}} + {unit.powerIncome !== undefined && unit.powerIncome > 0 && +    + {unit.powerIncome}} + {unit.faithIncome !== undefined && unit.faithIncome > 0 && +    + {unit.faithIncome}} + + + } {unit.squadMaxSize > 1 && Squad size @@ -177,10 +196,11 @@ function Unit(unit: IUnit, mod: IMod) { > Health -   {unit.health} {unit.healthRegeneration > 0 && - +{unit.healthRegeneration}/s} + +{unit.healthRegeneration}/s} + {unit.armour !== undefined && unit.armour > 0 && {unit.armour} } } + {unit.repairSpeed !== undefined && unit.repairSpeed !== null && + + Repair speed + + {unit.repairSpeed} + + + } @@ -243,7 +271,7 @@ function Unit(unit: IUnit, mod: IMod) { 0}/> - +
@@ -252,7 +280,7 @@ function Unit(unit: IUnit, mod: IMod) { {[...mapWithUnitWeapons.keys()].sort(function (a, b) { return a - b; - }).map(h => )} + }).map(h => )} {unit.filename} diff --git a/src/types/ArmorTypeValues.ts b/src/types/ArmorTypeValues.ts index e6690cc..804ee75 100644 --- a/src/types/ArmorTypeValues.ts +++ b/src/types/ArmorTypeValues.ts @@ -8,10 +8,14 @@ enum ArmorTypeValues { VehicleLow = 'Vehicle Low', VehicleMedium = 'Vehicle Medium', VehicleHigh = 'Vehicle High', + LivingMetal = 'Living Metal', + Titan = 'Titan', Air = 'Air', BuildingLow = 'Building Low', BuildingMedium = 'Building Medium', BuildingHigh = 'Building High', + BuildingSuper = 'Building Super', + DemonLow = 'Demon Low', DemonMedium = 'Demon Medium', DemonHigh = 'Demon High', } diff --git a/src/types/IBuilding.tsx b/src/types/IBuilding.tsx index 60b75c7..c31f930 100644 --- a/src/types/IBuilding.tsx +++ b/src/types/IBuilding.tsx @@ -17,7 +17,11 @@ export interface IBuilding { buildCostFaith: number buildCostSouls: number buildCostTime: number + faithIncome?: number + powerIncome?: number + requisitionIncome?: number health: number + armour?: number healthRegeneration: number sightRadius: number detectRadius: number diff --git a/src/types/IBuildingShort.tsx b/src/types/IBuildingShort.tsx index 072837b..96b1ea6 100644 --- a/src/types/IBuildingShort.tsx +++ b/src/types/IBuildingShort.tsx @@ -1,4 +1,5 @@ import {Irace} from "./Irace"; +import {IUnitShort} from "./IUnitShort"; export interface IRaceBuildings { race: Irace @@ -9,6 +10,7 @@ export interface IBuildingShort { name: string icon: string id: number + units: IUnitShort[] canDetect: boolean armorTypeName: string } diff --git a/src/types/IUnit.tsx b/src/types/IUnit.tsx index e83cb27..2ee8326 100644 --- a/src/types/IUnit.tsx +++ b/src/types/IUnit.tsx @@ -26,6 +26,7 @@ export interface IUnit { squadMaxSize: number squadLimit?: number health: number + armour?: number healthRegeneration: number moraleDeathPenalty: number repairMax: number @@ -43,6 +44,11 @@ export interface IUnit { reinforceCostFaith ?: number reinforceCostSouls ?: number reinforceTime?: number + repairSpeed? : number + repairCostPercent?: number + faithIncome?: number + powerIncome?: number + requisitionIncome?: number icon: string modId: number sergeants: ISergeant[] @@ -62,7 +68,11 @@ export interface ISergeant { buildCostFaith: number buildCostSouls: number buildCostTime: number + faithIncome?: number + powerIncome?: number + requisitionIncome?: number health: number + armour?: number healthRegeneration: number moraleDeathPenalty: number mass: number