diff --git a/.env b/.env index 0a0dc3e..7890f45 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -#REACT_APP_HOST_URL=http://wiki-backend.dawn-of-war.pro +#REACT_APP_HOST_URL=https://wiki-backend.dawn-of-war.pro REACT_APP_HOST_URL=http://localhost:8082 \ No newline at end of file diff --git a/public/images/Mob_bonus.gif b/public/images/Mob_bonus.gif new file mode 100644 index 0000000..a7035f8 Binary files /dev/null and b/public/images/Mob_bonus.gif differ diff --git a/public/index.html b/public/index.html index 4411453..d730010 100644 --- a/public/index.html +++ b/public/index.html @@ -7,8 +7,9 @@ + - Wiki Soulstorm + Dawn of War Wiki diff --git a/src/classes/AbilityFull.tsx b/src/classes/AbilityFull.tsx index f90b9c2..4f3ec8d 100644 --- a/src/classes/AbilityFull.tsx +++ b/src/classes/AbilityFull.tsx @@ -25,6 +25,8 @@ import {ModifiersProvidesTable} from "./ModifiersProvideTable"; import {IAbilityFill, IAbilityShort} from "../types/IAbility"; import AvTimerOutlinedIcon from "@mui/icons-material/AvTimer"; import ability from "./Ability"; +import AbilitySpawnedObject from "./AbilitySpawnedObject"; +import DpsTable from "./DpsTable"; interface IAbilityFullState { ability?: IAbilityFill; @@ -37,8 +39,6 @@ export default function AbilityFull(props: { abilityId?: number, mod: IMod, race }); - - const StyledTableCell = styled(TableCell)(({theme}) => ({ [`&.${tableCellClasses.head}`]: { backgroundColor: "rgb(244,244,244)", @@ -80,64 +80,14 @@ export default function AbilityFull(props: { abilityId?: number, mod: IMod, race const ability = abilityFull.ability - function getPiercingK(armorType: string): number|null { - if(ability.targetFilter.length > 0 && ability.targetFilter.find(tf => tf.name == armorType) === undefined) return null - const abilityPiercing = ability.piercings.find((p) => p.armorType.name === armorType) - return (typeof abilityPiercing !== "undefined" ? abilityPiercing.piercingValue : 10) / 100 + + function isAbilityApplyTo(armorType: string) { + return (ability.targetFilter.length === 0 || ability.targetFilter.find(tf => tf.name == armorType)) !== undefined ? : - } - 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|null) => { - if(damagePiercing === null) return "" - - if(ability.minDamageValue !== undefined && ability.minDamage !== undefined && ability.maxDamage !== undefined){ - var minDamage = damagePiercing * ability.minDamage - var maxDamage = damagePiercing * ability.maxDamage - - if(ability.minDamageValue !== undefined){ - if (minDamage < ability.minDamageValue) { - minDamage = ability.minDamageValue - } - if (maxDamage < ability.minDamageValue) { - maxDamage = ability.minDamageValue - } - } - - - const averageDmg = (minDamage + maxDamage) / 2 - - return averageDmg.toFixed(2) - } - - - } - - const getMoraleDamage = () => { - if(ability.moraleDamage !== undefined) return (ability.moraleDamage / 2).toFixed(2) - } + const showDpsTable = (ability.minDamage !== undefined && ability.minDamage > 0 || ability.moraleDamage !== undefined && ability.moraleDamage > 0) + const showTargetTable = !showDpsTable && ability.abilityEnvironment == null && (ability.targetFilter.length > 0 || ability.radius !== 0) return (
@@ -189,7 +139,7 @@ export default function AbilityFull(props: { abilityId?: number, mod: IMod, race   - {ability.rechargeTime.toFixed(0)}s  + {ability.rechargeTime}s  {ability.rechargeTimerGlobal && global cooldown} @@ -251,164 +201,157 @@ export default function AbilityFull(props: { abilityId?: number, mod: IMod, race {props.isChild !== true && ability.description}
- {(ability.minDamage !== undefined && ability.minDamage > 0 || ability.moraleDamage !== undefined && ability.moraleDamage > 0) && + {showDpsTable ? {(ability.refreshTime !== undefined && ability.durationTime !== undefined && ability.refreshTime * 2 < ability.durationTime) && Every {ability.refreshTime.toFixed(1)}s deal damege:} - - { props.mod !== undefined && 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)} - - - - - - - - - - - - - - -
- Morale
-
-
-
- - - {getTotalDamage(vehLowPiercing)} - {getTotalDamage(vehMedPiercing)} - {getTotalDamage(vehHighPiercing)} - {getTotalDamage(livingMetalPiercing)} - {getTotalDamage(titanPiercing)} - {getTotalDamage(buildingLowPiercing)} - {getTotalDamage(buildingMedPiercing)} - {getTotalDamage(buildingHighPiercing)} - {getTotalDamage(buildingSuperPiercing)} - {getMoraleDamage()} - - -
: - - - - - - - - - - - - - - - - - - - -
- Morale
-
-
-
- - - {getTotalDamage(infLowPiercing)} - {getTotalDamage(infMedPiercing)} - {getTotalDamage(infHighPiercing)} - {getTotalDamage(infHeavyMedPiercing)} - {getTotalDamage(infHeavyHighPiercing)} - {getTotalDamage(commanderPiercing)} - {getTotalDamage(demonPiercing)} - {getTotalDamage(demonHighPiercing)} - {getTotalDamage(airPiercing)} - {getTotalDamage(vehLowPiercing)} - {getTotalDamage(vehMedPiercing)} - {getTotalDamage(vehHighPiercing)} - {getTotalDamage(buildingLowPiercing)} - {getTotalDamage(buildingMedPiercing)} - {getTotalDamage(buildingHighPiercing)} - {getMoraleDamage()} - - -
- } -
-
} + + : showTargetTable ? + + + { props.mod !== undefined && props.mod.technicalName === 'UltimateApocalypse' ? + + + + + + + + + + + + + + + + + + {isAbilityApplyTo(ArmorTypeNames.InfantryLow)} + {isAbilityApplyTo(ArmorTypeNames.InfantryMedium)} + {isAbilityApplyTo(ArmorTypeNames.InfantryHigh)} + {isAbilityApplyTo(ArmorTypeNames.InfantryHeavyMedium)} + {isAbilityApplyTo(ArmorTypeNames.InfantryHeavyHigh)} + {isAbilityApplyTo(ArmorTypeNames.Commander)} + {isAbilityApplyTo(ArmorTypeNames.DemonLow)} + {isAbilityApplyTo(ArmorTypeNames.DemonMedium)} + {isAbilityApplyTo(ArmorTypeNames.DemonHigh)} + {isAbilityApplyTo(ArmorTypeNames.Air)} + + + + + + + + + + + + + + + + + + + {isAbilityApplyTo(ArmorTypeNames.VehicleLow)} + {isAbilityApplyTo(ArmorTypeNames.VehicleMedium)} + {isAbilityApplyTo(ArmorTypeNames.VehicleHigh)} + {isAbilityApplyTo(ArmorTypeNames.LivingMetal)} + {isAbilityApplyTo(ArmorTypeNames.Titan)} + {isAbilityApplyTo(ArmorTypeNames.BuildingLow)} + {isAbilityApplyTo(ArmorTypeNames.BuildingMedium)} + {isAbilityApplyTo(ArmorTypeNames.BuildingHigh)} + {isAbilityApplyTo(ArmorTypeNames.BuildingSuper)} + + + +
: + + + + + + + + + + + + + + + + + + + + + + + {isAbilityApplyTo(ArmorTypeNames.InfantryLow)} + {isAbilityApplyTo(ArmorTypeNames.InfantryMedium)} + {isAbilityApplyTo(ArmorTypeNames.InfantryHigh)} + {isAbilityApplyTo(ArmorTypeNames.InfantryHeavyMedium)} + {isAbilityApplyTo(ArmorTypeNames.InfantryHeavyHigh)} + {isAbilityApplyTo(ArmorTypeNames.Commander)} + {isAbilityApplyTo(ArmorTypeNames.DemonMedium)} + {isAbilityApplyTo(ArmorTypeNames.DemonHigh)} + {isAbilityApplyTo(ArmorTypeNames.Air)} + {isAbilityApplyTo(ArmorTypeNames.VehicleLow)} + {isAbilityApplyTo(ArmorTypeNames.VehicleMedium)} + {isAbilityApplyTo(ArmorTypeNames.VehicleHigh)} + {isAbilityApplyTo(ArmorTypeNames.BuildingLow)} + {isAbilityApplyTo(ArmorTypeNames.BuildingMedium)} + {isAbilityApplyTo(ArmorTypeNames.BuildingHigh)} + + +
+ } +
+
: } - {/*TODO: spawnedEntityName not parsing correctly, fix it*/} - {ability.spawnedEntityName !== undefined && ability.spawnedEntityName !== null && Spawn {ability.spawnedEntityName}} + {(ability.abilityEnvironment != null) && } {ability.childAbility !== undefined && ability.childAbility !== null && } {props.isChild !== true && ability.requirements !== undefined && ability.requirements !== null && - - - } + + + } {ability.activation !== "Passive ability" && props.isChild !== true && Hotkey: {ability.hotkey}} ) diff --git a/src/classes/AbilitySpawnedObject.tsx b/src/classes/AbilitySpawnedObject.tsx new file mode 100644 index 0000000..4060721 --- /dev/null +++ b/src/classes/AbilitySpawnedObject.tsx @@ -0,0 +1,135 @@ +import { + Accordion, + AccordionDetails, + AccordionSummary, Grid2, Paper, + Table, + TableBody, + TableCell, TableContainer, + TableRow, + Tooltip +} from "@mui/material"; +import {ExpandMore} from "@mui/icons-material"; +import React from "react"; +import {IAbilityShort} from "../types/IAbility"; +import {getIcon} from "./ModifiersProvideTable"; +import {IMod} from "../types/Imod"; +import AbilityFull from "./AbilityFull"; +import {Irace} from "../types/Irace"; +import {IAbilityEnvironment} from "../types/IAbilityEnvironment"; +import AvTimerOutlinedIcon from "@mui/icons-material/AvTimer"; +import ArmorType from "./ArmorType"; +import Vision from "./Vision"; +import Ability from "./Ability"; +import DeathExplosion from "./DeathExplosion"; + + +interface AbilityEnvironmentProps { + abilityEnvironment: IAbilityEnvironment, + race: Irace, + mod: IMod, +} + +function AbilitySpawnedObject(props: AbilityEnvironmentProps) { + + const abilityEnvironment = props.abilityEnvironment + + return
+

{props.abilityEnvironment.name ?? props.abilityEnvironment.filename.charAt(0).toUpperCase() + props.abilityEnvironment.filename.slice(1).replaceAll('_', ' ').replace('.rgd', '')} + (Spawned object) +

+ + + + + + {abilityEnvironment.armorType !== null && + + Armor type + + {abilityEnvironment.armorType2 == null ? + : + } + + + } + {abilityEnvironment.health !== null && + + Health + +   + {abilityEnvironment.health} {abilityEnvironment.healthRegeneration != null && abilityEnvironment.healthRegeneration > 0 && + +{abilityEnvironment.healthRegeneration}/s} + {abilityEnvironment.armour !== undefined && abilityEnvironment.armour !== 0 && + {abilityEnvironment.armour} } + + + } + {abilityEnvironment.moveSpeed != null && + + Move speed + + {abilityEnvironment.moveSpeed} + + + } + {abilityEnvironment.sightRadius != null && + + Vision + + + + + } + {abilityEnvironment.lifetime != null && + + Lifetime + +   + {abilityEnvironment.lifetime.toFixed(0)}s  + + + } + +
+
+
+ +
+ {abilityEnvironment.description} +
+
+ {abilityEnvironment.abilities.length > 0 && + {abilityEnvironment.abilities.map(a => + + )} + } + {abilityEnvironment.deathExplosions.length > 0 && + + {abilityEnvironment.deathExplosions.map(da => + + )} + + } +
+
+ +} + + +export default AbilitySpawnedObject; + diff --git a/src/classes/ArmorType.tsx b/src/classes/ArmorType.tsx index 19aa082..9f87dbe 100644 --- a/src/classes/ArmorType.tsx +++ b/src/classes/ArmorType.tsx @@ -61,7 +61,7 @@ class ArmorType extends React.Component { render() { if(this.props.compact){ return ( {this.props.compact ? -
{this.props.name} +

{this.props.name}
: {this.props.name}} ); } else diff --git a/src/classes/DeathExplosion.tsx b/src/classes/DeathExplosion.tsx new file mode 100644 index 0000000..4486b0c --- /dev/null +++ b/src/classes/DeathExplosion.tsx @@ -0,0 +1,97 @@ +import { + Accordion, + AccordionDetails, + AccordionSummary, Grid2, Paper, + Table, + TableBody, + TableCell, TableContainer, TableHead, + TableRow, + Tooltip +} from "@mui/material"; +import {ExpandMore} from "@mui/icons-material"; +import React from "react"; +import {IAbilityShort} from "../types/IAbility"; +import {getIcon, ModifiersProvidesTable} from "./ModifiersProvideTable"; +import {IMod} from "../types/Imod"; +import AbilityFull from "./AbilityFull"; +import {Irace} from "../types/Irace"; +import {IAbilityEnvironment} from "../types/IAbilityEnvironment"; +import AvTimerOutlinedIcon from "@mui/icons-material/AvTimer"; +import ArmorType from "./ArmorType"; +import Vision from "./Vision"; +import Ability from "./Ability"; +import {IDeathExplosion} from "../types/IDeathExplosion"; +import Required from "./Required"; +import ArmorTypeNames from "../types/ArmorTypeValues"; +import DpsTable from "./DpsTable"; + + +interface DeathExpProps { + deathExplosion: IDeathExplosion, + mod: IMod, +} + +function DeathExplosion(props: DeathExpProps) { + + const deathExplosion = props.deathExplosion + const chanceTotalNotZero = deathExplosion.globalChance * deathExplosion.chance != 0 + + return chanceTotalNotZero ? +
+ } + aria-controls="panel1-content" + > + + Death Explosion + + + + + + + + + + Chance + + {deathExplosion.globalChance * deathExplosion.chance}% + + + + Damage radius + + {deathExplosion.damageRadius} + + + + Throw force + + {deathExplosion.throwForceMin} - {deathExplosion.throwForceMax} + + + +
+
+
+ + + +
+
+
: + +} + + +export default DeathExplosion; + diff --git a/src/classes/DpsTable.tsx b/src/classes/DpsTable.tsx new file mode 100644 index 0000000..fa59665 --- /dev/null +++ b/src/classes/DpsTable.tsx @@ -0,0 +1,238 @@ +import React from "react"; +import ArmorTypeNames from "../types/ArmorTypeValues"; +import { + styled, + Table, + TableBody, + TableCell, + tableCellClasses, + TableContainer, + TableHead, + TableRow +} from "@mui/material"; +import ArmorType from "./ArmorType"; +import {IMod} from "../types/Imod"; +import {IPiercing} from "../types/IPiercing"; +import {IArmorType} from "../types/IArmorType"; + +export default function DpsTable(props: { mod: IMod, minDamageValue?: number, minDamage?: number, maxDamage?: number, piercings: IPiercing[], targetFilter: IArmorType[], moraleDamage?: number }) { + + const StyledTableCell = styled(TableCell)(({theme}) => ({ + [`&.${tableCellClasses.head}`]: { + backgroundColor: "rgb(244,244,244)", + marginRight: 'auto', + marginLeft: 'auto', + paddingLeft: 10 + }, + [`&.${tableCellClasses.body}`]: { + fontSize: 12, + textAlign: 'center', + paddingRight: 18, + paddingLeft: 10 + }, + })); + + function getPiercingK(armorType: string): number|null { + if(props.targetFilter.length > 0 && props.targetFilter.find(tf => tf.name == armorType) === undefined) return null + const piercing = props.piercings.find((p) => p.armorType.name === armorType) + return (typeof piercing !== "undefined" ? piercing.piercingValue : 10) / 100 + } + + 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|null) => { + if(damagePiercing === null) return "" + + if(props.minDamageValue !== undefined && props.minDamage !== undefined && props.maxDamage !== undefined){ + var minDamage = damagePiercing * props.minDamage + var maxDamage = damagePiercing * props.maxDamage + + if(props.minDamageValue !== undefined){ + if (minDamage < props.minDamageValue) { + minDamage = props.minDamageValue + } + if (maxDamage < props.minDamageValue) { + maxDamage = props.minDamageValue + } + } + + const averageDmg = (minDamage + maxDamage) / 2 + + return averageDmg.toFixed(2) + } + + + } + + const getMoraleDamage = () => { + if(props.moraleDamage !== undefined) return (props.moraleDamage / 2).toFixed(2) + } + + return ( + + { props.mod !== undefined && 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)} + + + + + + + + + + + + + + +
+ Morale
+
+
+
+ + + {getTotalDamage(vehLowPiercing)} + {getTotalDamage(vehMedPiercing)} + {getTotalDamage(vehHighPiercing)} + {getTotalDamage(livingMetalPiercing)} + {getTotalDamage(titanPiercing)} + {getTotalDamage(buildingLowPiercing)} + {getTotalDamage(buildingMedPiercing)} + {getTotalDamage(buildingHighPiercing)} + {getTotalDamage(buildingSuperPiercing)} + {getMoraleDamage()} + + +
: + + + + + + + + + + + + + + + + + + + +
+ Morale
+
+
+
+ + + {getTotalDamage(infLowPiercing)} + {getTotalDamage(infMedPiercing)} + {getTotalDamage(infHighPiercing)} + {getTotalDamage(infHeavyMedPiercing)} + {getTotalDamage(infHeavyHighPiercing)} + {getTotalDamage(commanderPiercing)} + {getTotalDamage(demonPiercing)} + {getTotalDamage(demonHighPiercing)} + {getTotalDamage(airPiercing)} + {getTotalDamage(vehLowPiercing)} + {getTotalDamage(vehMedPiercing)} + {getTotalDamage(vehHighPiercing)} + {getTotalDamage(buildingLowPiercing)} + {getTotalDamage(buildingMedPiercing)} + {getTotalDamage(buildingHighPiercing)} + {getMoraleDamage()} + + +
+ } +
+ ) +} diff --git a/src/classes/ModifiersProvideTable.tsx b/src/classes/ModifiersProvideTable.tsx index fb4a136..7892d19 100644 --- a/src/classes/ModifiersProvideTable.tsx +++ b/src/classes/ModifiersProvideTable.tsx @@ -7,19 +7,19 @@ import {IAffectedData} from "../types/IAffectedData"; import {IMod} from "../types/Imod"; import AvTimerOutlinedIcon from "@mui/icons-material/AvTimer"; -interface IModifiersProvidesTable{ +interface IModifiersProvidesTable { modifiers: IModifier[], } -interface IModifiersProvidesResearchTable{ +interface IModifiersProvidesResearchTable { modifiers: IModifier[], affectedData: IAffectedData | null, modId: number, race: Irace, } -function getModName(mt: String){ - switch(mt) { +function getModName(mt: String) { + switch (mt) { case 'modifiers\\armour_modifier.lua': return 'Armor'; case 'modifiers\\health_maximum_modifier.lua': @@ -35,7 +35,8 @@ function getModName(mt: String){ case 'modifiers\\holy_icon_cost_power.lua': return Next icon cost ; case 'modifiers\\holy_icon_cost_requisition.lua': - return Next icon cost ; + return Next icon cost ; case 'modifiers\\enable_hardpoint_02.lua': return 'Weapon slot 2'; case 'modifiers\\default_weapon_modifier_hardpoint1.lua': @@ -68,15 +69,19 @@ function getModName(mt: String){ return 'Power cost'; case 'modifiers\\cost_time_modifier.lua': return 'Cost time'; + case 'modifiers\\income_requisition_player_modifier.lua': + return 'Global income requisition'; + case 'modifiers\\income_power_player_modifier.lua': + return 'Global income power'; default: return mt.replace("modifiers\\", "").replace("modifier.lua", "").replace(".lua", "").replaceAll("_", " "); } } -function getModIcon(mt: String){ - switch(mt) { +function getModIcon(mt: String) { + switch (mt) { case 'modifiers\\armour_modifier.lua': - return ; + return ; case 'modifiers\\health_maximum_modifier.lua': return ; case 'modifiers\\keen_sight_radius_modifier.lua': @@ -99,6 +104,10 @@ function getModIcon(mt: String){ return ; case 'modifiers\\population_cap_player_modifier.lua': return ; + case 'modifiers\\income_requisition_player_modifier.lua': + return ; + case 'modifiers\\income_power_player_modifier.lua': + return ; case 'modifiers\\cost_time_modifier.lua': return ; @@ -108,17 +117,17 @@ function getModIcon(mt: String){ } function getChangeDescription(ref: String, v: number) { - switch(ref) { + switch (ref) { case 'type_modifierusagetype\\tp_mod_usage_addition.lua': - if(v < 0){ + if (v < 0) { return v - }else return '+' + v; + } else return '+' + v; case 'type_modifierusagetype\\tp_mod_usage_multiplication.lua': return 'x' + v; case 'type_modifierusagetype\\tp_mod_usage_percentage.lua': return '%' + v; case 'type_modifierusagetype\\tp_mod_usage_enable.lua': - if(v === 1){ + if (v === 1) { return ' enable '; } else { return ' disable '; @@ -128,19 +137,20 @@ function getChangeDescription(ref: String, v: number) { } } -export function ModifiersProvidesAddonTable (props: IModifiersProvidesTable) { +export function ModifiersProvidesAddonTable(props: IModifiersProvidesTable) { let noWeaponMods = props.modifiers.filter(m => !m.reference.includes("default_weapon_modifier_hardpoint")) return ( - +
{noWeaponMods.map(m => {getModName(m.reference)} - {getModIcon(m.reference)} {getChangeDescription(m.usageType, m.value)} + {getModIcon(m.reference)} {getChangeDescription(m.usageType, m.value)} )}
@@ -148,15 +158,15 @@ export function ModifiersProvidesAddonTable (props: IModifiersProvidesTable) { ) } -export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable) { +export function ModifiersProvidesTable(props: IModifiersProvidesResearchTable) { let mods = props.modifiers function getTarget(target: String) { - if(props.affectedData !== null){ + if (props.affectedData !== null) { console.log(props.affectedData.affectedUnits.map(au => au.filename)) var affectedUnit = props.affectedData.affectedUnits.find(au => au.filename.replaceAll('.rgd', '').split(";")[0] === target || au.filename.replaceAll('.rgd', '').split(";")[1] === target); - if(affectedUnit != null) { + if (affectedUnit != null) { return @@ -164,16 +174,17 @@ export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable) } var affectedSergeant = props.affectedData.affectedSergeants.find(as => as.filename.replaceAll('.rgd', '') === target); - if(affectedSergeant != null) { + if (affectedSergeant != null) { return {affectedSergeant.name} at {affectedSergeant.name} at {affectedSergeant.unit.name} } var affectedBuilding = props.affectedData.affectedBuildings.find(ab => ab.filename.replaceAll('.rgd', '') === target); - if(affectedBuilding != null) { + if (affectedBuilding != null) { return {affectedBuilding.name} @@ -184,7 +195,7 @@ export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable) if (affectedWeapon != null) { return {affectedWeapon.name ? affectedWeapon.name : affectedWeapon.filename.replaceAll('_', ' ').replace('.rgd', '')} at { affectedWeapon.units.map(unit => - {affectedWeapon != null && affectedWeapon.units.length + affectedWeapon.sergeants.length > 1 ?
: }
{unit.name}
@@ -192,11 +203,11 @@ export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable) } { affectedWeapon.sergeants.map(affectedSergeant => - {affectedSergeant.name} at {affectedWeapon != null && affectedWeapon.units.length + affectedWeapon.sergeants.length > 1 ?
: }{affectedSergeant.name} at + href={`/mod/${props.modId}/race/${props.race.id}/unit/${affectedSergeant.unit.id}`}> {affectedSergeant.unit.name}
) @@ -204,7 +215,7 @@ export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable) { affectedWeapon.buildings.map(affectedBuilding => + href={`/mod/${props.modId}/race/${props.race.id}/building/${affectedBuilding.id}`}> {affectedBuilding.name} ) @@ -224,10 +235,18 @@ export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable) sx={{'&:last-child td, &:last-child th': {border: 0}}} > {getTarget(m.target)} - {getModName(m.reference)} - {getModIcon(m.reference)} {getChangeDescription(m.usageType, m.value)} - {m.maxLifeTime !== undefined && m.maxLifeTime > 0 && {m.maxLifeTime}s - }{m.exclusive ? " does not stuck" : " does stuck"} + {getModName(m.reference)} + {getModIcon(m.reference)} {getChangeDescription(m.usageType, m.value)} + {m.maxLifeTime !== undefined && m.maxLifeTime > 0 && + {m.maxLifeTime}s + } + {m.exclusive ? " does not stuck" : " does stuck"} + {m.probabilityOfApplying !== undefined && m.probabilityOfApplying !== 1.0 && + ({m.probabilityOfApplying * 100}% chance) + } + )} @@ -235,8 +254,8 @@ export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable) ) } -export function getIcon(icon?: string): string{ - if(icon !== null && icon !== undefined){ +export function getIcon(icon?: string): string { + if (icon !== null && icon !== undefined) { return IconUrl + icon.replaceAll('\\', '/') } else return '/images/NoImg.gif' } diff --git a/src/classes/Required.tsx b/src/classes/Required.tsx index c568d9e..7fe3d0c 100644 --- a/src/classes/Required.tsx +++ b/src/classes/Required.tsx @@ -3,7 +3,8 @@ import {IBuildingShort} from "../types/IBuildingShort"; import {IBuildingAddonShort} from "../types/IBuilding"; import {IconUrl} from "../core/api"; import {IResearchRequirements} from "../types/IResearchRequirements"; -import {IRequirement, IRequirementLimitByBuildingDto} from "../types/IRequirement"; +import {IRequirement, IRequirementLimitByBuildingDto, IRequirementSquadsDto} from "../types/IRequirement"; +import {IUnitShort} from "../types/IUnitShort"; interface IRequiredProps{ requirement: IRequirement, @@ -25,7 +26,7 @@ function Required (props: IRequiredProps) { )}
} - function renderRequirementBuilding(requirementBuildings: IBuildingShort[],) { + function renderRequirementBuildingEither(requirementBuildings: IBuildingShort[],) { return requirementBuildings.length > 0 && (
  Buildings: @@ -38,6 +39,22 @@ function Required (props: IRequiredProps) { ); } + function renderRequiremenStructureExclusive(buildingExclusive: IBuildingShort) { + return
  Can't be build with: +  {" "} + {buildingExclusive.name} +
+ } + + function renderRequiremenAddonExclusive(addonShort: IBuildingAddonShort) { + return
  Can't be build with: +   + {addonShort.name} +
+ } + function renderRequirementOwnership(requirementOwnership: string[],) { return requirementOwnership.length > 0 &&   Owner: {requirementOwnership.map(o => { switch(o) { @@ -68,6 +85,31 @@ function Required (props: IRequiredProps) { )}
} + function renderRequirementSquads(requirementSquads: IRequirementSquadsDto[],) { + return
{requirementSquads.map(rs => + +   Squad: {rs.count} +   + {rs.squad.name} + + )}
+ } + + function renderRequirementResearchesEither(requirementResearches: IResearchRequirements[],) { + console.log(requirementResearches); + return requirementResearches.length > 0 && ( + + ); + } + const requirement = props.requirement @@ -79,6 +121,11 @@ function Required (props: IRequiredProps) { src="/images/Resource_orksquadcap.gif"/>  {requirement.requiredTotalPop} } + {requirement.mobBonus !== null && requirement.mobBonus !== undefined && +
  Mob requirement:   + {requirement.mobBonus.mobvalueRequired} in radius {requirement.mobBonus.proximityRequired}
+ } {requirement.requireAddon !== null &&
  Addon:   @@ -88,6 +135,8 @@ function Required (props: IRequiredProps) { {requirement.replaceWhenDone && (old provides replace)}
} + {requirement.requirementAddonExclusive != null && + renderRequiremenAddonExclusive(requirement.requirementAddonExclusive,)} {requirement.requirementBuildings.map(b =>
  Building:   @@ -95,8 +144,14 @@ function Required (props: IRequiredProps) { } {requirement.requirementResearches.length !== 0 && renderRequirementResearches(requirement.requirementResearches,)} + {requirement.requirementSquads.length !== 0 && + renderRequirementSquads(requirement.requirementSquads,)} + {requirement.requirementResearchesEither.length !== 0 && + renderRequirementResearchesEither(requirement.requirementResearchesEither,)} {requirement.requirementBuildingsEither.length !== 0 && - renderRequirementBuilding(requirement.requirementBuildingsEither,)} + renderRequirementBuildingEither(requirement.requirementBuildingsEither,)} + {requirement.requirementStructureExclusive != null && + renderRequiremenStructureExclusive(requirement.requirementStructureExclusive,)} {requirement.limitByBuilding !== undefined && requirement.limitByBuilding !== null && renderLimitPerBuilding(requirement.limitByBuilding)} {requirement.requirementsGlobalAddons.length !== 0 && renderRequirementGlobalAddons(requirement.requirementsGlobalAddons,)} diff --git a/src/classes/Sergeant.tsx b/src/classes/Sergeant.tsx index 542cec5..bcaff19 100644 --- a/src/classes/Sergeant.tsx +++ b/src/classes/Sergeant.tsx @@ -11,6 +11,7 @@ import {Irace} from "../types/Irace"; import Required from "./Required"; import {ModifiersProvidesTable} from "./ModifiersProvideTable"; import Ability from "./Ability"; +import DeathExplosion from "./DeathExplosion"; export interface SergeantProps { @@ -120,6 +121,14 @@ const Sergeant = (props: SergeantProps) => { src="/images/Kills_icon.webp"/> -{sergeant.moraleDeathPenalty} + + Mass + + {sergeant.mass} + + @@ -128,6 +137,14 @@ const Sergeant = (props: SergeantProps) => { + {sergeant.mobValue != null && + + Mob value + + {sergeant.mobValue} + + + } @@ -157,6 +174,13 @@ const Sergeant = (props: SergeantProps) => { return a - b; }).map(h => )} + {sergeant.deathExplosions.length > 0 && + + {sergeant.deathExplosions.map(da => + + )} + + } {renderAffectedResearches(sergeant.affectedResearches, props.mod.id, props.race.id)} diff --git a/src/classes/WeaponFull.tsx b/src/classes/WeaponFull.tsx index f34f083..c6fb4c3 100644 --- a/src/classes/WeaponFull.tsx +++ b/src/classes/WeaponFull.tsx @@ -264,7 +264,7 @@ export default function WeaponFull(props: {weaponId: number, isDefault: Boolean, One hit average damage - { props.mod !== undefined && props.mod.name.includes("Ultimate Apocalypse") ? + { props.mod !== undefined && props.mod.technicalName === 'UltimateApocalypse' ? diff --git a/src/pages/BuildingPage.tsx b/src/pages/BuildingPage.tsx index eea1603..f47cf85 100644 --- a/src/pages/BuildingPage.tsx +++ b/src/pages/BuildingPage.tsx @@ -30,6 +30,7 @@ import Research, {renderAffectedResearches} from "../classes/building/Research"; import Required from "../classes/Required"; import {ModifiersProvidesTable} from "../classes/ModifiersProvideTable"; import Ability from "../classes/Ability"; +import DeathExplosion from "../classes/DeathExplosion"; interface UintPageState { building: IBuilding, @@ -198,6 +199,13 @@ function Building(building: IBuilding, mod: IMod) { )} } + {building.deathExplosions.length > 0 && + + {building.deathExplosions.map(da => + + )} + + } {building.addons.length > 0 &&

Addons

{building.addons.map(b => diff --git a/src/pages/ModsPage.tsx b/src/pages/ModsPage.tsx index adc6063..a211010 100644 --- a/src/pages/ModsPage.tsx +++ b/src/pages/ModsPage.tsx @@ -26,8 +26,7 @@ function Mods (mods: IMod[]) { return(

{modName}

- - {modName == "Unification new races" && } + {modName == "Unification new races" && } {sameMods.filter((m) => !m.isBeta).map(mod =>
    {mod.version}
)} {sameMods.find((m) => m.isBeta) != null &&
Beta versions:
} diff --git a/src/pages/UnitPage.tsx b/src/pages/UnitPage.tsx index 20ceff0..c83c38d 100644 --- a/src/pages/UnitPage.tsx +++ b/src/pages/UnitPage.tsx @@ -29,6 +29,7 @@ import Required from "../classes/Required"; import {renderAffectedResearches} from "../classes/building/Research"; import {ModifiersProvidesTable} from "../classes/ModifiersProvideTable"; import Ability from "../classes/Ability"; +import DeathExplosion from "../classes/DeathExplosion"; interface UintPageState { unit: IUnit, @@ -254,6 +255,14 @@ function Unit(unit: IUnit, mod: IMod) { } + {unit.mobValue != null && + + Mob value + + {unit.mobValue} + + + } {unit.squadLimit !== undefined && unit.squadLimit !== null && Limit @@ -292,6 +301,15 @@ function Unit(unit: IUnit, mod: IMod) { )} + + {unit.moraleMax !== null && !(unit.moraleBrakeModifiers.find(m => m.reference.includes("accuracy_weapon_modifier") && m.value === 0.2) !== undefined && + unit.moraleBrakeModifiers.find(m => m.reference.includes("speed_maximum_modifier") && m.value === 1.2) !== undefined && + unit.moraleBrakeModifiers.length === 2) + && +

Morale broken unusual behavior

+ +
} + {unit.modifiers.length > 0 &&

Affected on

@@ -309,6 +327,13 @@ function Unit(unit: IUnit, mod: IMod) { return a - b; }).map(h => )}
+ {unit.deathExplosions.length > 0 && + + {unit.deathExplosions.map(da => + + )} + + } {renderAffectedResearches(unit.affectedResearches, mod.id, unit.race.id)} diff --git a/src/types/ArmorTypeValues.ts b/src/types/ArmorTypeValues.ts index 70ebdb9..706a74a 100644 --- a/src/types/ArmorTypeValues.ts +++ b/src/types/ArmorTypeValues.ts @@ -1,4 +1,4 @@ -enum ArmorTypeValues { +enum ArmorTypeValues { InfantryLow = 'Infantry Low', InfantryMedium = 'Infantry Medium', InfantryHigh = 'Infantry High', diff --git a/src/types/IAbility.tsx b/src/types/IAbility.tsx index c10e650..f4a19c8 100644 --- a/src/types/IAbility.tsx +++ b/src/types/IAbility.tsx @@ -2,6 +2,8 @@ import {IModifier} from "./IModifier"; import {IRequirement} from "./IRequirement"; import {IArmorType} from "./IArmorType"; import {IAffectedData} from "./IAffectedData"; +import {IPiercing} from "./IPiercing"; +import {IAbilityEnvironment} from "./IAbilityEnvironment"; export interface IAbilityShort { id: number; @@ -32,7 +34,6 @@ export interface IAbilityFill { rechargeTimerGlobal?: boolean; refreshTime?: number; durationTime?: number; - spawnedEntityName?: string; radius?: number; minDamage?: number; minDamageValue?: number; @@ -47,10 +48,6 @@ export interface IAbilityFill { requirements?: IRequirement; affectedData: IAffectedData, targetFilter: IArmorType[]; - piercings: IAbilityPiercing[]; -} - -export interface IAbilityPiercing { - armorType: IArmorType - piercingValue: number + piercings: IPiercing[]; + abilityEnvironment: IAbilityEnvironment; } diff --git a/src/types/IAbilityEnvironment.tsx b/src/types/IAbilityEnvironment.tsx new file mode 100644 index 0000000..2bc0e4f --- /dev/null +++ b/src/types/IAbilityEnvironment.tsx @@ -0,0 +1,26 @@ +import {IModifier} from "./IModifier"; +import {IRequirement} from "./IRequirement"; +import {IArmorType} from "./IArmorType"; +import {IAffectedData} from "./IAffectedData"; +import {IAbilityShort} from "./IAbility"; +import {IDeathExplosion} from "./IDeathExplosion"; + +export interface IAbilityEnvironment { + id: number; + modId: number; + filename: string; + name?: string | null; + description?: string | null; + icon?: string | null; + health?: number | null; + armour?: number | null; + healthRegeneration?: number | null; + moveSpeed?: number | null; + sightRadius?: number | null; + detectRadius?: number | null; + lifetime?: number | null; + armorType: IArmorType | null; + armorType2: IArmorType | null; + abilities: IAbilityShort[]; + deathExplosions: IDeathExplosion[]; +} \ No newline at end of file diff --git a/src/types/IBuilding.tsx b/src/types/IBuilding.tsx index 449c81c..aaa3e2f 100644 --- a/src/types/IBuilding.tsx +++ b/src/types/IBuilding.tsx @@ -7,6 +7,7 @@ import {IRequirement} from "./IRequirement"; import {IResearchShort} from "./IResearchShort"; import {IAffectedData} from "./IAffectedData"; import {IAbilityShort} from "./IAbility"; +import {IDeathExplosion} from "./IDeathExplosion"; export interface IBuilding { id: number @@ -42,6 +43,7 @@ export interface IBuilding { units: IUnitShort[] affectedResearches: IResearchShort[], requirements: IRequirement, + deathExplosions: IDeathExplosion[], hotkey: string } diff --git a/src/types/IDeathExplosion.tsx b/src/types/IDeathExplosion.tsx new file mode 100644 index 0000000..d01824b --- /dev/null +++ b/src/types/IDeathExplosion.tsx @@ -0,0 +1,22 @@ +import {IModifier} from "./IModifier"; +import {IRequirement} from "./IRequirement"; +import {IArmorType} from "./IArmorType"; +import {IAffectedData} from "./IAffectedData"; +import {IAbilityShort} from "./IAbility"; +import {IPiercing} from "./IPiercing"; + +export interface IDeathExplosion { + id?: number | null; + globalChance: number; + chance: number; + minDamage?: number ; + maxDamage?: number ; + minDamageValue?: number; + moraleDamage?: number; + damageRadius?: number | null; + throwForceMin?: number | null; + throwForceMax?: number | null; + modId?: number | null; + modifiers: IModifier[]; + armorPiercing: IPiercing[]; +} \ No newline at end of file diff --git a/src/types/IPiercing.tsx b/src/types/IPiercing.tsx new file mode 100644 index 0000000..95dbcca --- /dev/null +++ b/src/types/IPiercing.tsx @@ -0,0 +1,7 @@ +import {IArmorType} from "./IArmorType"; + +export interface IPiercing { + armorType: IArmorType + piercingValue: number +} + diff --git a/src/types/IRequirement.tsx b/src/types/IRequirement.tsx index d898ecc..91a6608 100644 --- a/src/types/IRequirement.tsx +++ b/src/types/IRequirement.tsx @@ -1,21 +1,37 @@ import {IBuildingShort} from "./IBuildingShort"; import {IBuildingAddonShort} from "./IBuilding"; import {IResearchRequirements} from "./IResearchRequirements"; +import {IUnitShort} from "./IUnitShort"; export interface IRequirement { requirementBuildings: IBuildingShort[]; requirementBuildingsEither: IBuildingShort[]; requirementsGlobalAddons: IBuildingAddonShort[]; requirementResearches: IResearchRequirements[]; + requirementSquads: IRequirementSquadsDto[]; + requirementResearchesEither: IResearchRequirements[]; replaceWhenDone: Boolean; requireAddon: IBuildingAddonShort; requiredTotalPop?: number; limitSquad?:number; limitTech?:number; limitByBuilding ?: IRequirementLimitByBuildingDto; + mobBonus?: IRequirementMobBonusDto; + requirementStructureExclusive?: IBuildingShort; + requirementAddonExclusive?: IBuildingAddonShort; requiredOwnership: string[]; } +export interface IRequirementSquadsDto{ + squad: IUnitShort; + count: number; +} + +export interface IRequirementMobBonusDto{ + mobvalueRequired: number; + proximityRequired: number; +} + export interface IRequirementLimitByBuildingDto{ building: IBuildingShort; limit: number; diff --git a/src/types/IUnit.tsx b/src/types/IUnit.tsx index 39d8efd..fae88a4 100644 --- a/src/types/IUnit.tsx +++ b/src/types/IUnit.tsx @@ -5,6 +5,8 @@ import {IRequirement} from "./IRequirement"; import {IModifier} from "./IModifier"; import {IAffectedData} from "./IAffectedData"; import {IAbilityShort} from "./IAbility"; +import {IPiercing} from "./IPiercing"; +import {IDeathExplosion} from "./IDeathExplosion"; export interface IUnitResponse { race: string @@ -54,6 +56,7 @@ export interface IUnit { faithIncome?: number powerIncome?: number requisitionIncome?: number + mobValue?: number icon: string modId: number requirements: IRequirement @@ -61,9 +64,11 @@ export interface IUnit { sergeants: ISergeant[] weapons: WeaponHardpoint[] modifiers: IModifier[] + moraleBrakeModifiers: IModifier[] abilities: IAbilityShort[] affectedData: IAffectedData, affectedResearches: IResearchShort[], + deathExplosions: IDeathExplosion[], hotkey?: string, } @@ -83,6 +88,7 @@ export interface ISergeant { faithIncome?: number powerIncome?: number requisitionIncome?: number + mobValue?: number health: number armour?: number healthRegeneration: number @@ -100,6 +106,7 @@ export interface ISergeant { weapons: WeaponHardpoint[] abilities: IAbilityShort[] affectedResearches: IResearchShort[], + deathExplosions: IDeathExplosion[], hotkey?: string, } @@ -147,13 +154,8 @@ export interface IWeapon { modId: number requirements: IRequirement modifiers: IModifier[] - weaponArmorPiercing: IWeaponPiercing[] + weaponArmorPiercing: IPiercing[] affectedResearches: IResearchShort[], hotkey?: string, } -export interface IWeaponPiercing { - armorType: IArmorType - piercingValue: number -} -