- Add death explosions info

- Add mob bonus info
- Reworked abilities, add child objects
- Add unit morale break behaviour
- Rework UA mod frontend
This commit is contained in:
anibus
2026-03-14 15:05:45 +03:00
parent e0fe94b8ca
commit 9d4bb49713
23 changed files with 882 additions and 266 deletions
+52 -33
View File
@@ -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 <span>Next icon cost <img style={{verticalAlign: "top"}} src='/images/Resource_power.gif'/></span>;
case 'modifiers\\holy_icon_cost_requisition.lua':
return <span>Next icon cost <img style={{verticalAlign: "top"}} src='/images/Resource_requisition.gif'/></span>;
return <span>Next icon cost <img style={{verticalAlign: "top"}}
src='/images/Resource_requisition.gif'/></span>;
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 <img style={{height: 20, verticalAlign: "top"}} src='/images/defence.png'/>;
return <img style={{height: 20, verticalAlign: "top"}} src='/images/defence.png'/>;
case 'modifiers\\health_maximum_modifier.lua':
return <img style={{verticalAlign: "top"}} src='/images/Health_icon.webp'/>;
case 'modifiers\\keen_sight_radius_modifier.lua':
@@ -99,6 +104,10 @@ function getModIcon(mt: String){
return <img style={{verticalAlign: "top"}} src='/images/Resource_cap_infantry.gif'/>;
case 'modifiers\\population_cap_player_modifier.lua':
return <img style={{verticalAlign: "top"}} src='/images/Resource_orksquadcap.gif'/>;
case 'modifiers\\income_requisition_player_modifier.lua':
return <img style={{verticalAlign: "top"}} src='/images/Resource_requisition.gif'/>;
case 'modifiers\\income_power_player_modifier.lua':
return <img style={{verticalAlign: "top"}} src='/images/Resource_power.gif'/>;
case 'modifiers\\cost_time_modifier.lua':
return <AvTimerOutlinedIcon
style={{verticalAlign: "top", fontSize: "18px"}}/>;
@@ -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 (
<TableContainer component={Paper}>
<Table size="small" aria-label="a dense table">
<Table size="small" aria-label="a dense table">
{noWeaponMods.map(m =>
<TableRow
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell component="th" scope="row">{getModName(m.reference)}</TableCell>
<TableCell component="th" scope="row">{getModIcon(m.reference)} {getChangeDescription(m.usageType, m.value)}</TableCell>
<TableCell component="th"
scope="row">{getModIcon(m.reference)} {getChangeDescription(m.usageType, m.value)}</TableCell>
</TableRow>
)}
</Table>
@@ -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 <span><img style={{verticalAlign: "top", height: 25}}
src={getIcon(affectedUnit.icon)}/><a
href={`/mod/${props.modId}/race/${props.race.id}/unit/${affectedUnit.id}`}>
@@ -164,16 +174,17 @@ export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable)
</a></span>
}
var affectedSergeant = props.affectedData.affectedSergeants.find(as => as.filename.replaceAll('.rgd', '') === target);
if(affectedSergeant != null) {
if (affectedSergeant != null) {
return <span><img style={{verticalAlign: "top", height: 25}}
src={getIcon(affectedSergeant.icon)}/>{affectedSergeant.name} at <img style={{verticalAlign: "top", height: 25}}
src={getIcon(affectedSergeant.unit.icon)}/><a
src={getIcon(affectedSergeant.icon)}/>{affectedSergeant.name} at <img
style={{verticalAlign: "top", height: 25}}
src={getIcon(affectedSergeant.unit.icon)}/><a
href={`/mod/${props.modId}/race/${props.race.id}/unit/${affectedSergeant.unit.id}`}>
{affectedSergeant.unit.name}
</a></span>
}
var affectedBuilding = props.affectedData.affectedBuildings.find(ab => ab.filename.replaceAll('.rgd', '') === target);
if(affectedBuilding != null) {
if (affectedBuilding != null) {
return <span><img style={{verticalAlign: "top", height: 25}} src={getIcon(affectedBuilding.icon)}/><a
href={`/mod/${props.modId}/race/${props.race.id}/building/${affectedBuilding.id}`}>
{affectedBuilding.name}
@@ -184,7 +195,7 @@ export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable)
if (affectedWeapon != null) {
return <span>{affectedWeapon.name ? affectedWeapon.name : affectedWeapon.filename.replaceAll('_', ' ').replace('.rgd', '')} at {
affectedWeapon.units.map(unit =>
<span><img style={{verticalAlign: "top", height: 25}} src={getIcon(unit.icon)}/><a
<span>{affectedWeapon != null && affectedWeapon.units.length + affectedWeapon.sergeants.length > 1 ? <br/> : <span></span>}<img style={{verticalAlign: "top", height: 25}} src={getIcon(unit.icon)}/><a
href={`/mod/${props.modId}/race/${props.race.id}/unit/${unit.id}`}>
{unit.name}
</a> </span>
@@ -192,11 +203,11 @@ export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable)
}
{
affectedWeapon.sergeants.map(affectedSergeant =>
<span><img style={{verticalAlign: "top", height: 25}}
src={getIcon(affectedSergeant.icon)}/>{affectedSergeant.name} at <img
<span>{affectedWeapon != null && affectedWeapon.units.length + affectedWeapon.sergeants.length > 1 ? <br/> : <span></span>}<img style={{verticalAlign: "top", height: 25}}
src={getIcon(affectedSergeant.icon)}/>{affectedSergeant.name} at <img
style={{verticalAlign: "top", height: 25}}
src={getIcon(affectedSergeant.unit.icon)}/><a
href={`/mod//${props.modId}/race/${props.race.id}/unit/${affectedSergeant.unit.id}`}>
href={`/mod/${props.modId}/race/${props.race.id}/unit/${affectedSergeant.unit.id}`}>
{affectedSergeant.unit.name}
</a> </span>
)
@@ -204,7 +215,7 @@ export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable)
{
affectedWeapon.buildings.map(affectedBuilding =>
<span><img style={{verticalAlign: "top", height: 25}} src={getIcon(affectedBuilding.icon)}/><a
href={`/mod//${props.modId}/race/${props.race.id}/building/${affectedBuilding.id}`}>
href={`/mod/${props.modId}/race/${props.race.id}/building/${affectedBuilding.id}`}>
{affectedBuilding.name}
</a> </span>
)
@@ -224,10 +235,18 @@ export function ModifiersProvidesTable (props: IModifiersProvidesResearchTable)
sx={{'&:last-child td, &:last-child th': {border: 0}}}
>
<TableCell component="th" scope="row">{getTarget(m.target)}</TableCell>
<TableCell style={{minWidth: 120}} component="th" scope="row">{getModName(m.reference)}</TableCell>
<TableCell component="th" scope="row">{getModIcon(m.reference)} {getChangeDescription(m.usageType, m.value)}
{m.maxLifeTime !== undefined && m.maxLifeTime > 0 && <span><img style={{verticalAlign: "top"}} src='/images/Time_icon.webp'/>{m.maxLifeTime}s
</span> }<i style={{fontSize: 11}}>{m.exclusive ? " does not stuck" : " does stuck"}</i></TableCell>
<TableCell style={{minWidth: 120}} component="th"
scope="row">{getModName(m.reference)}</TableCell>
<TableCell component="th"
scope="row">{getModIcon(m.reference)} {getChangeDescription(m.usageType, m.value)}
{m.maxLifeTime !== undefined && m.maxLifeTime > 0 &&
<span><img style={{verticalAlign: "top"}} src='/images/Time_icon.webp'/>{m.maxLifeTime}s
</span>}
<i style={{fontSize: 11}}>{m.exclusive ? " does not stuck" : " does stuck"}</i>
{m.probabilityOfApplying !== undefined && m.probabilityOfApplying !== 1.0 &&
<span><i style={{fontSize: 11}}> ({m.probabilityOfApplying * 100}% chance)</i>
</span>}
</TableCell>
</TableRow>
)}
</Table>
@@ -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'
}