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.ArmorType 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?.getPureReference()) { 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_REQUIRED_RESEARCH_EITHER -> rTable.getStringByName("research_name_either") + ";" + rTable.getStringByName("research_name_or") 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() Requirements.REFERENCE_REQUIREMENT_MOB_BONUS -> rTable.getDoubleByName("mobvalue_required").toString() + ";" + rTable.getIntByName("proximity_required").toString() Requirements.REFERENCE_REQUIREMENT_STRUCTURE_EXCLUSIVE -> rTable.getStringByName("structure_name_exclusive") Requirements.REFERENCE_LOCAL_REQUIRED_ADDON_EXCLUSIVE -> rTable.getStringByName("mutually_exclusive_with") Requirements.REFERENCE_REQUIREMENT_SQUAD -> rTable.getStringByName("squad_name") + ";" + rTable.getIntByName("min_count") 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") ) } 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 getArmorType( entityData: List, armorTypes: Iterable, armorTypeTableName: String ): ArmorType? { val armorType = entityData.getRgdTableByName("type_ext") ?.getRgdTableByName(armorTypeTableName) ?.getStringByName("\$REF") return armorTypes.find { it.id == armorType ?.replace("TYPE_Armour\\tp_", "") ?.replace("type_armour\\tp_", "") ?.replace(".lua", "") } } 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(entityData: List?, abilities: Set): List = entityData ?.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() fun String.getPureReference(): String = this.split("\\").last() .replace(".lua", "") .replace(".rgd", "") }