170 lines
7.4 KiB
Kotlin
170 lines
7.4 KiB
Kotlin
package com.dowstats.service.w40k
|
|
|
|
import com.dowstats.data.entities.ArmorType
|
|
import com.dowstats.data.entities.Weapon
|
|
import com.dowstats.data.entities.WeaponArmorPiercing
|
|
import com.dowstats.data.repositories.ArmorTypeRepository
|
|
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.LoggerFactory
|
|
import org.springframework.beans.factory.annotation.Autowired
|
|
import org.springframework.stereotype.Service
|
|
import java.io.File
|
|
import java.nio.file.Path
|
|
import kotlin.io.path.exists
|
|
|
|
@Service
|
|
class WeaponRgdExtractService @Autowired constructor(
|
|
private val armorTypeRepository: ArmorTypeRepository,
|
|
private val iconsService: IconsService,
|
|
private val modAttribPathService: ModAttribPathService,
|
|
) {
|
|
|
|
val log = LoggerFactory.getLogger(WeaponRgdExtractService::class.java)
|
|
|
|
data class BuildCost(
|
|
val requisition: Int?,
|
|
val power: Int?,
|
|
val seconds: Int?
|
|
)
|
|
|
|
data class ArmourDamage(
|
|
val minDamage: Double,
|
|
val maxDamage: Double,
|
|
val minDamageValue: Double,
|
|
val moraleDamage: Double,
|
|
val armourPiercing: List<WeaponArmorPiercing>,
|
|
)
|
|
|
|
data class WeaponUiInfo(
|
|
val name: String?,
|
|
val description: String?,
|
|
val iconPath: String?,
|
|
val haveEquipButton: Boolean
|
|
)
|
|
|
|
fun extractToWeaponEntity(weaponFileName: String, weaponData: List<RgdData>, modId: Long, modFolderData: String, modDictionary: Map<Int, String>): Weapon? {
|
|
|
|
val armorTypes = armorTypeRepository.findAll().toSet()
|
|
|
|
val weapon = Weapon()
|
|
|
|
weapon.filename = weaponFileName
|
|
val weaponUiData = getWeaponNameAndDescription(weaponData, modDictionary, modFolderData)
|
|
weapon.name = weaponUiData.name
|
|
weapon.icon = weaponUiData.iconPath
|
|
weapon.description = weaponUiData.description
|
|
weapon.haveEquipButton = weaponUiData.haveEquipButton
|
|
weapon.hotkeyName = weaponData.getStringByName("ui_hotkey_name")
|
|
|
|
val cost = getCost(weaponData)
|
|
weapon.costRequisition = cost.requisition ?: 0
|
|
weapon.costPower = cost.power ?: 0
|
|
weapon.costTimeSeconds = cost.seconds ?: 0
|
|
weapon.accuracy = weaponData.getDoubleByName("accuracy")
|
|
weapon.accuracyReductionMoving = weaponData.getDoubleByName("accuracy_reduction_when_moving")
|
|
weapon.maxRange = weaponData.getDoubleByName("max_range")
|
|
weapon.reloadTime = weaponData.getDoubleByName("reload_time")
|
|
weapon.setupTime = weaponData.getDoubleByName("setup_time")
|
|
weapon.isMeleeWeapon = weaponData.getBooleanByName("melee_weapon") ?: false
|
|
weapon.canAttackAir = weaponData.getBooleanByName("can_attack_air_units") ?: false
|
|
weapon.canAttackGround = weaponData.getBooleanByName("can_attack_ground_units") ?: false
|
|
|
|
|
|
val armourDamage = getArmourDamage(weaponData, armorTypes, weapon)
|
|
weapon.minDamageValue = armourDamage.minDamageValue
|
|
weapon.minDamage = armourDamage.minDamage
|
|
weapon.maxDamage = armourDamage.maxDamage
|
|
weapon.moraleDamage = armourDamage.moraleDamage
|
|
weapon.weaponPiercings = armourDamage.armourPiercing
|
|
weapon.modId = modId
|
|
|
|
return if(weapon.minDamage == 0.0 && weapon.maxDamage == 0.0 && weapon.moraleDamage == 0.0){
|
|
null
|
|
} else weapon
|
|
}
|
|
|
|
private fun getCost(weaponData: List<RgdData>): BuildCost {
|
|
val costTable = weaponData.getRgdTableByName("cost")
|
|
val costTime = costTable?.getIntByName("time_seconds")
|
|
val costCost = costTable?.getRgdTableByName("cost")
|
|
val power = costCost?.getIntByName("power")
|
|
val requisition = costCost?.getIntByName("requisition")
|
|
return BuildCost(requisition, power, costTime)
|
|
}
|
|
|
|
private fun getArmourDamage(weaponData: List<RgdData>, armorTypes: Set<ArmorType>, thisWeapon: Weapon): ArmourDamage {
|
|
val armourDamage = weaponData.getRgdTableByName("area_effect")
|
|
?.getRgdTableByName("weapon_damage")
|
|
?.getRgdTableByName("armour_damage")!!
|
|
val minDamage = armourDamage.getDoubleByName("min_damage")!!
|
|
val maxDamage = armourDamage.getDoubleByName("max_damage")!!
|
|
val minDamageValue = armourDamage.getDoubleByName("min_damage_value")!!
|
|
val moraleDamage = armourDamage.getDoubleByName("morale_damage")!!
|
|
|
|
val defaultArmourPiercing = armourDamage.getDoubleByName("armour_piercing")
|
|
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()
|
|
|
|
val armoursPiercing = armorTypes.map {
|
|
val weaponArmourPiercing = WeaponArmorPiercing()
|
|
weaponArmourPiercing.weapon = thisWeapon
|
|
weaponArmourPiercing.armorType = it
|
|
weaponArmourPiercing.piercingValue = (weaponDmgMap[it.id] ?: defaultArmourPiercing)?.toBigDecimal()
|
|
weaponArmourPiercing
|
|
}
|
|
|
|
return ArmourDamage(minDamage, maxDamage, minDamageValue, moraleDamage, armoursPiercing)
|
|
}
|
|
|
|
|
|
private fun getWeaponNameAndDescription(weaponData: List<RgdData>, modDictionary: Map<Int, String>, modFolderData: String): WeaponUiInfo {
|
|
val weaponUiInfo = weaponData.getRgdTableByName("ui_info")
|
|
|
|
val nameRef = weaponUiInfo?.getStringByName("screen_name_id")?.replace("$", "")
|
|
val name = nameRef?.let { try { modDictionary[it.toInt()] } catch (e: Exception) { null } }
|
|
|
|
val descriptionRefs = weaponUiInfo?.getRgdTableByName("help_text_list")
|
|
?.map{(it.value as String).replace("$", "")}
|
|
?.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) { "" } }?.joinToString ( "\n" )
|
|
} catch(e:Exception) {
|
|
log.warn("Error parsing ui description", e)
|
|
null
|
|
}
|
|
|
|
val icon = try {
|
|
val iconPath = weaponUiInfo?.getStringByName("icon_name")
|
|
?.replace("/", File.separator)
|
|
|
|
val tgaIconPath = iconPath?.let {
|
|
val modIcon = modAttribPathService.getIconPath(modFolderData, it)
|
|
if(Path.of(modIcon).exists()) modIcon else
|
|
modAttribPathService.getIconPath(modAttribPathService.pathToWanilaData, it)
|
|
}
|
|
tgaIconPath?.let { iconsService.convertTgaToJpegImage(iconPath, it) }
|
|
} catch (e: Exception) {
|
|
log.error("Error parsing ui icon path", e)
|
|
null
|
|
}
|
|
|
|
val haveUpgradeButton = weaponUiInfo?.getBooleanByName("no_button")?.let { !it } ?: false
|
|
|
|
return WeaponUiInfo(name, description, icon, haveUpgradeButton)
|
|
}
|
|
}
|