2026-01-11 21:29:12 +03:00

181 lines
7.9 KiB
Kotlin

package com.dowstats.service.w40k
import com.dowstats.Metadata.Requirements
import com.dowstats.data.dto.AreaEffect
import com.dowstats.data.dto.BuildCost
import com.dowstats.data.dto.ResourceIncome
import com.dowstats.data.dto.UiInfo
import com.dowstats.data.entities.Mod
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
import com.dowstats.data.rgd.RgdDataUtil.getIntByName
import com.dowstats.data.rgd.RgdDataUtil.getRgdTableByName
import com.dowstats.data.rgd.RgdDataUtil.getStringByName
import org.slf4j.Logger
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
@Service
class CommonParseRgdService @Autowired constructor(
private val modAttribPathService: ModAttribPathService,
private val iconsService: IconsService,
) {
fun getRequirementReference(ref: String?, rTable: List<RgdData>, fileName: String, log: Logger): String? = when (ref) {
Requirements.REFERENCE_REQUIREMENT_POP -> rTable.getDoubleByName("population_required").toString()
Requirements.REFERENCE_REQUIREMENT_ADDON -> rTable.getStringByName("addon_name")
Requirements.REFERENCE_GLOBAL_REQUIREMENT_ADDON -> rTable.getStringByName("global_addon_name")
Requirements.REFERENCE_REQUIREMENT_STRUCTURE_EITHER -> rTable.getStringByName("structure_name_or") + ";" +
rTable.getStringByName("structure_name_either")
Requirements.REFERENCE_REQUIREMENT_STRUCTURE -> rTable.getStringByName("structure_name")
Requirements.REFERENCE_REQUIREMENT_RESEARCH -> rTable.getStringByName("research_name") + ";" +
rTable.getBooleanByName("research_must_not_be_complete")
Requirements.REFERENCE_REQUIREMENT_OWNERSHIP -> rTable.getStringByName("own_name")
Requirements.REFERENCE_REQUIREMENT_CAP -> rTable.getIntByName("max_cap").toString()
Requirements.REFERENCE_REQUIREMENT_SQUAD_CAP -> rTable.getIntByName("max_squad_cap").toString()
Requirements.REFERENCE_REQUIREMENT_CUM_SQUAD_CAP -> rTable.getIntByName("max_cumulative_squad_cap").toString()
Requirements.REFERENCE_REQUIREMENT_STRUCTURE_RATIO -> rTable.getStringByName("required_structure_name") + ";" +
rTable.getIntByName("this_structure_count").toString()
else -> {
log.warn("Unknown requirement reference $ref at $fileName")
null
}
}
fun getBuildCost(cost: List<RgdData>?): BuildCost {
val costResources = cost?.getRgdTableByName("cost")
return BuildCost(
costResources?.getDoubleByName("requisition"),
costResources?.getDoubleByName("power"),
costResources?.getDoubleByName("population"),
costResources?.getDoubleByName("faith"),
costResources?.getDoubleByName("souls"),
cost?.getDoubleByName("time_seconds")?.toInt()
)
}
fun getResourceIncome(resourceExt: List<RgdData>?): ResourceIncome {
return ResourceIncome(
resourceExt?.getDoubleByName("faith_per_second")?.let { it * 10 },
resourceExt?.getDoubleByName("power_per_second")?.let { it * 10 },
resourceExt?.getDoubleByName("requisition_per_second")?.let { it * 10 },
)
}
fun getUiInfo(uiInfoRgdData: List<RgdData>, modDictionary: Map<Int, String>, modFolderData: String, mod: Mod, log: Logger, isOnOfAbility: Boolean = false): UiInfo {
val nameRef = uiInfoRgdData?.getStringByName("screen_name_id")?.replace("$", "")
val name = nameRef?.let { try { modDictionary[it.toInt()] } catch (e: Exception) { it } }
val descriptionRefs = uiInfoRgdData.getRgdTableByName("help_text_list")
?.mapNotNull{try {
(it.value as String).replace("$", "")
} catch (e: Exception) {
log.error("Error parsing ui help_text weapon $name", e)
null
}}
?.filter{it != "0" && it != "tables\\text_table.lua" && it != ""}
?.sortedBy { try { it.toInt() } catch (e: Exception) { 0 } }
val description = try {
descriptionRefs?.map { try { modDictionary[it.toInt()] } catch (e: Exception) { it } }?.joinToString ( "\n" )
} catch(e:Exception) {
log.warn("Error parsing ui description weapon $name", e)
null
}
val icon = try {
val iconPath = if (isOnOfAbility) {
uiInfoRgdData.getStringByName("icon_name") + "_off"
} else uiInfoRgdData.getStringByName("icon_name")
iconPath?.let { modAttribPathService.getIconPath(modFolderData, iconPath) }
?.let { iconsService.convertTgaToJpegImage(iconPath, it, mod.name) }
} catch (e: Exception) {
log.error("Error parsing ui icon path for $name", e)
null
}
return UiInfo(name, description, icon)
}
fun getAreaEffectData(areaEffectData: List<RgdData>): AreaEffect {
val areaEffectInformation = areaEffectData.getRgdTableByName("area_effect_information")
val areaType = areaEffectInformation?.getRgdTableByName("area_type")
?.getStringByName("\$REF")
?.replace("type_areaeffect\\tp_","")
?.replace(".lua","")
val filterType = areaEffectInformation?.getRgdTableByName("filter_type")
?.getStringByName("\$REF")
?.replace("type_areafilter\\tp_","")
?.replace(".lua","")
val cantHaveRadius = areaEffectInformation?.equals("area_effect_point") == true
val damageRadius = if(cantHaveRadius) 0.0 else areaEffectInformation?.getDoubleByName("radius") ?: 0.0
val throwData = areaEffectData.getRgdTableByName("throw_data")
val forceMin = throwData?.getDoubleByName("force_min") ?: 0.0
val forceMax = throwData?.getDoubleByName("force_max") ?: 0.0
val armourDamage = areaEffectData
.getRgdTableByName("weapon_damage")
?.getRgdTableByName("armour_damage")
val minDamage = armourDamage?.getDoubleByName("min_damage") ?: 0.0
val maxDamage = armourDamage?.getDoubleByName("max_damage") ?: 0.0
val minDamageValue = armourDamage?.getDoubleByName("min_damage_value") ?: 0.0
val moraleDamage = armourDamage?.getDoubleByName("morale_damage") ?: 0.0
val defaultArmourPiercing = armourDamage?.getDoubleByName("armour_piercing") ?: 0.0
val weaponDmgMap: Map<String, Double> =
armourDamage?.getRgdTableByName("armour_piercing_types")?.mapNotNull { armour_piercing ->
if (armour_piercing.name.contains("entry")) {
val entry = armour_piercing.value as List<RgdData>
val dmgType = entry.getRgdTableByName("armour_type")?.getStringByName("\$REF")?.replace("type_armour\\tp_","")?.replace(".lua","")
val dmgValue = entry.getDoubleByName("armour_piercing_value")
dmgType!! to dmgValue!!
} else null
}?.toMap() ?: emptyMap()
return AreaEffect(
minDamage,
maxDamage,
damageRadius,
forceMin,
forceMax,
minDamageValue,
moraleDamage,
weaponDmgMap,
defaultArmourPiercing,
areaType,
filterType
)
}
fun getAbilities(modelData: List<RgdData>?, abilities: Set<Ability>): List<Ability> = modelData
?.getRgdTableByName("ability_ext")
?.getRgdTableByName("abilities")
?.mapNotNull { ability ->
if (ability.name.contains("ability_")) {
val abilityFileName = (ability.value as String?)?.let{
it.replace("abilities\\", "").replace(".lua", "").replace(".rgd", "")
}
abilities.find { it.filename?.replace(".rgd", "") == abilityFileName }
} else null
} ?: emptyList()
}