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, 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?): 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?): 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, modDictionary: Map, 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): 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 = armourDamage?.getRgdTableByName("armour_piercing_types")?.mapNotNull { armour_piercing -> if (armour_piercing.name.contains("entry")) { val entry = armour_piercing.value as List 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?, abilities: Set): List = 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() }