Add abilities support

This commit is contained in:
Anibus 2026-01-11 21:29:12 +03:00
parent c637580255
commit 42283639fa
108 changed files with 3968 additions and 153 deletions

View File

@ -0,0 +1,31 @@
package com.dowstats.controllers
import com.dowstats.data.dto.controllers.WeaponDto
import com.dowstats.data.dto.controllers.ability.AbilityDto
import com.dowstats.data.dto.controllers.building.BuildingFullDto
import com.dowstats.data.dto.controllers.building.RaceBuildings
import com.dowstats.data.dto.controllers.research.ResearchDto
import com.dowstats.data.repositories.BuildingRepository
import com.dowstats.service.datamaps.AbilityService
import com.dowstats.service.datamaps.DowBuildingMappingService
import com.dowstats.service.datamaps.ResearchService
import com.dowstats.service.datamaps.WeaponService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("api/v1/ability")
class AbilityController @Autowired constructor(
val abilityService: AbilityService,
) {
@GetMapping("/{modId}/{abilityId}")
fun getById(@PathVariable abilityId: Long, @PathVariable modId: Long): AbilityDto {
return abilityService.getAbilityDto(abilityId, modId)
}
}

View File

@ -2,7 +2,6 @@ package com.dowstats.controllers
import com.dowstats.data.dto.controllers.RaceUnits import com.dowstats.data.dto.controllers.RaceUnits
import com.dowstats.data.dto.controllers.UnitFullDto import com.dowstats.data.dto.controllers.UnitFullDto
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.repositories.UnitRepository import com.dowstats.data.repositories.UnitRepository
import com.dowstats.service.datamaps.DowUnitMappingService import com.dowstats.service.datamaps.DowUnitMappingService
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired

View File

@ -1,5 +1,7 @@
package com.dowstats.data.dto package com.dowstats.data.dto
import com.dowstats.data.entities.weapon.WeaponModifiers
data class AreaEffect( data class AreaEffect(
val minDamage: Double, val minDamage: Double,
val maxDamage: Double, val maxDamage: Double,
@ -10,4 +12,6 @@ data class AreaEffect(
val moraleDamage: Double, val moraleDamage: Double,
val weaponDmgMap: Map<String, Double>, val weaponDmgMap: Map<String, Double>,
val defaultArmorPiercing: Double, val defaultArmorPiercing: Double,
val areaType: String?,
val filterType: String?,
) )

View File

@ -1,7 +1,7 @@
package com.dowstats.data.dto package com.dowstats.data.dto
import com.dowstats.data.entities.building.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.weapon.Weapon
data class BuildingDataToSave( data class BuildingDataToSave(
val building: Building, val building: Building,

View File

@ -1,8 +1,8 @@
package com.dowstats.data.dto package com.dowstats.data.dto
import com.dowstats.data.entities.DowUnit import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.Sergeant import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.weapon.Weapon
data class WeaponsData( data class WeaponsData(
val hardpoint: Int, val hardpoint: Int,

View File

@ -0,0 +1,8 @@
package com.dowstats.data.dto.controllers
import java.math.BigDecimal
data class AbilityArmorPiercingDto(
val armorType: ArmorTypeDto?,
val piercingValue: BigDecimal,
)

View File

@ -1,9 +1,9 @@
package com.dowstats.data.dto.controllers package com.dowstats.data.dto.controllers
import com.dowstats.data.entities.building.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnit import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.Sergeant import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.weapon.Weapon
data class EntityCompressDto( data class EntityCompressDto(

View File

@ -6,4 +6,8 @@ data class ModifierDto (
val usageType: String?, val usageType: String?,
val value: Double?, val value: Double?,
val target: String? = null, val target: String? = null,
val maxLifeTime: Double? = null,
val applicationType: String? = null,
val probabilityOfApplying: Double? = null,
val exclusive: Boolean? = null,
) )

View File

@ -1,5 +1,6 @@
package com.dowstats.data.dto.controllers package com.dowstats.data.dto.controllers
import com.dowstats.data.dto.controllers.ability.AbilityShortDto
import com.dowstats.data.dto.controllers.research.ResearchShortDto import com.dowstats.data.dto.controllers.research.ResearchShortDto
@ -23,12 +24,18 @@ data class SergeantDto(
val armour: Double?, val armour: Double?,
val healthRegeneration: Double?, val healthRegeneration: Double?,
val moraleDeathPenalty: Int?, val moraleDeathPenalty: Int?,
val moraleIncomeMax: Double?,
val moraleIncomeRate: Double?,
val mass: Int?, val mass: Int?,
val upTime: Double?, val upTime: Double?,
val sightRadius: Int?, val sightRadius: Int?,
val detectRadius: Int?, val detectRadius: Int?,
val icon: String?, val icon: String?,
val weapons: List<WeaponSlotDto>?, val weapons: List<WeaponSlotDto>?,
val abilities: Set<AbilityShortDto>?,
val affectedResearches: Set<ResearchShortDto>, val affectedResearches: Set<ResearchShortDto>,
val modifiers: List<ModifierDto>,
var affectedData: AffectedDataDto,
val requirements: RequirementDto?, val requirements: RequirementDto?,
val hotkey: String?,
) )

View File

@ -1,7 +1,7 @@
package com.dowstats.data.dto.controllers package com.dowstats.data.dto.controllers
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
import com.dowstats.data.entities.Sergeant import com.dowstats.data.entities.sergant.Sergeant
data class SergeantUnitShortDto( data class SergeantUnitShortDto(
val id: Long?, val id: Long?,

View File

@ -1,7 +1,9 @@
package com.dowstats.data.dto.controllers package com.dowstats.data.dto.controllers
import com.dowstats.data.dto.controllers.ability.AbilityShortDto
import com.dowstats.data.dto.controllers.building.BuildingAddonShortDto import com.dowstats.data.dto.controllers.building.BuildingAddonShortDto
import com.dowstats.data.dto.controllers.research.ResearchShortDto import com.dowstats.data.dto.controllers.research.ResearchShortDto
import com.dowstats.data.entities.ability.Ability
data class UnitFullDto( data class UnitFullDto(
@ -52,8 +54,12 @@ data class UnitFullDto(
val modId: Long, val modId: Long,
val sergeants: Set<SergeantDto>?, val sergeants: Set<SergeantDto>?,
val weapons: Set<WeaponSlotDto>?, val weapons: Set<WeaponSlotDto>?,
val abilities: Set<AbilityShortDto>?,
val haveReinforceMenu: Boolean, val haveReinforceMenu: Boolean,
val affectedResearches: Set<ResearchShortDto>, val affectedResearches: Set<ResearchShortDto>,
val affectedAddons: Set<BuildingAddonShortDto>, val affectedAddons: Set<BuildingAddonShortDto>,
val modifiers: List<ModifierDto>,
var affectedData: AffectedDataDto,
val requirements: RequirementDto?, val requirements: RequirementDto?,
val hotkey: String?,
) )

View File

@ -33,5 +33,7 @@ data class WeaponDto(
val weaponArmorPiercing: List<WeaponArmorPiercingDto>, val weaponArmorPiercing: List<WeaponArmorPiercingDto>,
val affectedResearches: Set<ResearchShortDto>, val affectedResearches: Set<ResearchShortDto>,
val affectedAddons: Set<BuildingAddonShortDto>, val affectedAddons: Set<BuildingAddonShortDto>,
val modifiers: List<ModifierDto>,
val requirements: RequirementDto?, val requirements: RequirementDto?,
val hotkey: String?,
) )

View File

@ -1,7 +1,7 @@
package com.dowstats.data.dto.controllers package com.dowstats.data.dto.controllers
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.weapon.Weapon
data class WeaponUnitShortDto( data class WeaponUnitShortDto(
val id: Long?, val id: Long?,

View File

@ -0,0 +1,45 @@
package com.dowstats.data.dto.controllers.ability
import com.dowstats.data.dto.controllers.AbilityArmorPiercingDto
import com.dowstats.data.dto.controllers.AffectedDataDto
import com.dowstats.data.dto.controllers.ArmorTypeDto
import com.dowstats.data.dto.controllers.ModifierDto
import com.dowstats.data.dto.controllers.RequirementDto
data class AbilityDto(
val id: Long?,
val modId: Long?,
val filename: String?,
val name: String?,
val description: String?,
val costRequisition: Double?,
val costPower: Double?,
val costFaith: Double?,
val costSouls: Double?,
val icon: String?,
val uiIndexHint: Int,
val hotkey: String?,
val childAbility: AbilityDto?,
val initialDelayTime: Double?,
val range: Double?,
val rechargeTime: Double?,
val rechargeTimerGlobal: Boolean?,
val refreshTime: Double?,
val durationTime: Double?,
val spawnedEntityName: String?,
val radius: Double?,
val minDamage: Double?,
val minDamageValue: Double?,
val maxDamage: Double?,
val moraleDamage: Double?,
val throwForceMin: Double?,
val throwForceMax: Double?,
val activation: String?,
val areaEffect: String?,
val areaFilter: String?,
val modifiers: List<ModifierDto>,
val requirements: RequirementDto?,
var affectedData: AffectedDataDto,
val targetFilter: List<ArmorTypeDto>,
val piercings: List<AbilityArmorPiercingDto>
)

View File

@ -0,0 +1,10 @@
package com.dowstats.data.dto.controllers.ability
data class AbilityShortDto(
val id: Long?,
val name: String?,
val fileName: String?,
val icon: String?,
val uiIndexHint: Int?,
val activationType: String?,
)

View File

@ -17,6 +17,7 @@ data class BuildingAddonDto(
val affectedData: AffectedDataDto, val affectedData: AffectedDataDto,
val addonRequirement: RequirementDto?, val addonRequirement: RequirementDto?,
val icon: String?, val icon: String?,
val hotkey: String?,
) )
data class BuildingAddonShortDto( data class BuildingAddonShortDto(

View File

@ -1,7 +1,9 @@
package com.dowstats.data.dto.controllers.building package com.dowstats.data.dto.controllers.building
import com.dowstats.data.dto.controllers.* import com.dowstats.data.dto.controllers.*
import com.dowstats.data.dto.controllers.ability.AbilityShortDto
import com.dowstats.data.dto.controllers.research.ResearchShortDto import com.dowstats.data.dto.controllers.research.ResearchShortDto
import com.dowstats.data.entities.ability.Ability
data class BuildingFullDto( data class BuildingFullDto(
var id: Long?, var id: Long?,
@ -29,6 +31,7 @@ data class BuildingFullDto(
var icon: String?, var icon: String?,
var modId: Long?, var modId: Long?,
var addons: List<BuildingAddonDto>?, var addons: List<BuildingAddonDto>?,
val abilities: Set<AbilityShortDto>?,
var researches: List<ResearchShortDto>?, var researches: List<ResearchShortDto>?,
var modifiers: List<ModifierDto>, var modifiers: List<ModifierDto>,
var affectedData: AffectedDataDto, var affectedData: AffectedDataDto,
@ -36,4 +39,5 @@ data class BuildingFullDto(
val weapons: Set<WeaponSlotDto>, val weapons: Set<WeaponSlotDto>,
val requirements: RequirementDto?, val requirements: RequirementDto?,
val affectedResearches: Set<ResearchShortDto>, val affectedResearches: Set<ResearchShortDto>,
val hotkey: String?,
) )

View File

@ -19,4 +19,5 @@ data class ResearchDto(
val icon: String?, val icon: String?,
val uiIndexHint : Int, val uiIndexHint : Int,
val modId: Long?, val modId: Long?,
val hotkey: String?
) )

View File

@ -0,0 +1,15 @@
package com.dowstats.data.entities
import jakarta.persistence.*
@Entity
@Table(name = "activation")
class Activation {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
var id: String? = null
var name: String? = null
}

View File

@ -0,0 +1,15 @@
package com.dowstats.data.entities
import jakarta.persistence.*
@Entity
@Table(name = "area_effect")
class AreaEffect {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
var id: String? = null
var name: String? = null
}

View File

@ -0,0 +1,15 @@
package com.dowstats.data.entities
import jakarta.persistence.*
@Entity
@Table(name = "area_filter")
class AreaFilter {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
var id: String? = null
var name: String? = null
}

View File

@ -1,7 +1,11 @@
package com.dowstats.data.entities package com.dowstats.data.entities
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto import com.dowstats.data.dto.controllers.ModifierDto
import com.dowstats.data.dto.controllers.SergeantUnitShortDto 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.getRgdTableByName
import com.dowstats.data.rgd.RgdDataUtil.getStringByName
import jakarta.persistence.GeneratedValue import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType import jakarta.persistence.GenerationType
import jakarta.persistence.Id import jakarta.persistence.Id
@ -17,6 +21,22 @@ open class ModifiersBase {
var target: String? = null var target: String? = null
var usageType: String? = null var usageType: String? = null
var value: Double? = null var value: Double? = null
var applicationType: String? = null
var probabilityOfApplying: Double? = null
var exclusive: Boolean? = null
fun toDto(): ModifierDto {
return ModifierDto(
id = id!!,
reference = reference,
usageType = usageType,
value = value,
target = target,
applicationType = applicationType,
probabilityOfApplying = probabilityOfApplying,
exclusive = exclusive
)
}
companion object ModifiersBaseCompanion { companion object ModifiersBaseCompanion {
@ -26,6 +46,17 @@ open class ModifiersBase {
it.usageType == "type_modifierusagetype\\tp_mod_usage_multiplication.lua" && it.value == 1.0 it.usageType == "type_modifierusagetype\\tp_mod_usage_multiplication.lua" && it.value == 1.0
} }
fun <T : ModifiersBase> T.fillDataFromRgdTable(rgdData: List<RgdData>): T {
this.reference = rgdData.getStringByName("\$REF")
this.target = rgdData.getStringByName("target_type_name")
this.usageType = rgdData.getRgdTableByName("usage_type")?.getStringByName("\$REF")
this.value = try{ rgdData.getDoubleByName("value") } catch (e: Exception) { null }
this.applicationType = rgdData.getRgdTableByName("application_type")?.getStringByName("\$REF")
this.exclusive = try { rgdData.getBooleanByName("exclusive") } catch (e: Exception) { false }
this.probabilityOfApplying = rgdData.getDoubleByName("probability_of_applying")
return this
}
} }
} }

View File

@ -0,0 +1,166 @@
package com.dowstats.data.entities.ability
import com.dowstats.data.dto.controllers.AbilityArmorPiercingDto
import com.dowstats.data.dto.controllers.AffectedDataDto
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.SergeantUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.WeaponUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.ability.AbilityDto
import com.dowstats.data.dto.controllers.ability.AbilityShortDto
import com.dowstats.data.entities.Activation
import com.dowstats.data.entities.AreaEffect
import com.dowstats.data.entities.AreaFilter
import com.dowstats.data.entities.ArmorType
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.weapon.Weapon
import jakarta.persistence.*
import java.math.BigDecimal
@Entity
@Table(name = "abilities")
class Ability {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
var modId: Long? = null
var filename: String? = null
var name: String? = null
var description: String? = null
var costRequisition: Double? = null
var costPower: Double? = null
var costFaith: Double? = null
var costSouls: Double? = null
var icon: String? = null
var uiIndexHint: Int = 0
var uiHotkeyName: String? = null
var childAbilityName: String? = null
var initialDelayTime: Double? = null
var radius: Double? = null
var minDamage: Double? = null
var minDamageValue: Double? = null
var maxDamage: Double? = null
var moraleDamage: Double? = null
var throwForceMin: Double? = null
var throwForceMax: Double? = null
var range: Double? = null
var rechargeTime: Double? = null
var rechargeTimerGlobal: Boolean? = null
var refreshTime: Double? = null
var durationTime: Double? = null
var spawnedEntityName: String? = null
@ManyToOne
@JoinColumn(name = "activation_id")
var activation: Activation? = null
@ManyToOne
@JoinColumn(name = "area_effect_id")
var areaEffect: AreaEffect? = null
@ManyToOne
@JoinColumn(name = "area_filter_id")
var areaFilter: AreaFilter? = null
@ManyToMany
@JoinTable(name = "unit_abilities",
joinColumns = [JoinColumn(name = "ability_id")],
inverseJoinColumns = [JoinColumn(name = "unit_id")])
var unitsUse: MutableSet<DowUnit>? = null
@OneToMany(mappedBy = "ability", cascade = [CascadeType.ALL])
var abilityModifiers: MutableSet<AbilityModifiers> = mutableSetOf()
@OneToMany(mappedBy = "ability", cascade = [CascadeType.ALL])
var abilityRequirements: MutableSet<AbilityRequirements> = mutableSetOf()
@OneToMany(mappedBy = "ability", cascade = [CascadeType.ALL])
var abilityPiercings: MutableSet<AbilityArmorPiercing> = mutableSetOf()
@ManyToMany
@JoinTable(name = "ability_affected_units",
joinColumns = [JoinColumn(name = "ability_id")],
inverseJoinColumns = [JoinColumn(name = "unit_id")])
var affectedOnUnits: MutableSet<DowUnit> = mutableSetOf()
@ManyToMany
@JoinTable(name = "ability_affected_sergeants",
joinColumns = [JoinColumn(name = "ability_id")],
inverseJoinColumns = [JoinColumn(name = "sergeant_id")])
var affectedOnSergeants: MutableSet<Sergeant> = mutableSetOf()
@ManyToMany
@JoinTable(name = "ability_affected_buildings",
joinColumns = [JoinColumn(name = "ability_id")],
inverseJoinColumns = [JoinColumn(name = "building_id")])
var affectedOnBuildings: MutableSet<Building> = mutableSetOf()
@ManyToMany
@JoinTable( name = "ability_affected_weapons",
joinColumns = [JoinColumn(name = "ability_id")],
inverseJoinColumns = [JoinColumn(name = "weapon_id")])
var affectedOnWeapons: MutableSet<Weapon> = mutableSetOf()
@ManyToMany
@JoinTable(name = "ability_target_filter",
joinColumns = [JoinColumn(name = "ability_id")],
inverseJoinColumns = [JoinColumn(name = "armor_type_id")])
var abilityTargetFilters: MutableSet<ArmorType> = mutableSetOf()
fun toShortDto() = AbilityShortDto(id, name, filename, icon, uiIndexHint, activation?.name)
fun toDto(requirements: RequirementDto?, childAbility: AbilityDto?): AbilityDto = AbilityDto(
id = id,
modId = modId,
filename = filename,
name = name,
description = description,
costRequisition = costRequisition,
costPower = costPower,
costFaith = costFaith,
costSouls = costSouls,
icon = icon,
uiIndexHint = uiIndexHint,
hotkey = uiHotkeyName,
childAbility = childAbility,
initialDelayTime = initialDelayTime,
range = range,
rechargeTime = rechargeTime,
rechargeTimerGlobal = rechargeTimerGlobal,
refreshTime = refreshTime,
durationTime = durationTime,
spawnedEntityName = spawnedEntityName,
radius = radius,
minDamage = minDamage,
minDamageValue = minDamageValue,
maxDamage = maxDamage,
moraleDamage = moraleDamage,
throwForceMin = throwForceMin,
throwForceMax = throwForceMax,
activation = activation?.name,
areaEffect = areaEffect?.name,
areaFilter = areaFilter?.name,
modifiers = abilityModifiers.map { it.toDto().copy(maxLifeTime = it.maxLifeTime) }.sortedBy { it.target },
requirements = requirements,
affectedData = AffectedDataDto(
affectedOnUnits.map { it.compressDto() }.toSet(),
affectedOnSergeants.toShortDtoSet(),
affectedOnBuildings.map { it.compressDto() }.toSet(),
affectedOnWeapons.toShortDtoSet(),
),
targetFilter = abilityTargetFilters.map { it.toDto() },
piercings = abilityPiercings.map { AbilityArmorPiercingDto(it.armorType?.toDto(), it.piercingValue ?: BigDecimal.ZERO) }
)
}

View File

@ -0,0 +1,26 @@
package com.dowstats.data.entities.ability
import com.dowstats.data.entities.ArmorType
import com.fasterxml.jackson.annotation.JsonIgnore
import java.math.BigDecimal
import jakarta.persistence.*
@Entity
@Table(name = "ability_armors_piercing")
class AbilityArmorPiercing {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
@ManyToOne
@JsonIgnore
@JoinColumn(name = "ability_id")
var ability: Ability? = null
@ManyToOne
@JoinColumn(name = "armor_type_id")
var armorType: ArmorType? = null
var piercingValue: BigDecimal? = null
}

View File

@ -0,0 +1,17 @@
package com.dowstats.data.entities.ability
import com.dowstats.data.entities.ModifiersBase
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@Entity
@Table(name = "ability_modifiers")
class AbilityModifiers : ModifiersBase() {
@ManyToOne
@JoinColumn(name = "ability_id", nullable = false)
@JsonIgnore
var ability: Ability? = null
var maxLifeTime: Double? = null
}

View File

@ -0,0 +1,15 @@
package com.dowstats.data.entities.ability
import com.dowstats.data.entities.RequirementBase
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@Entity
@Table(name = "ability_requirements")
class AbilityRequirements : RequirementBase() {
@ManyToOne
@JoinColumn(name = "ability_id", nullable = false)
@JsonIgnore
var ability: Ability? = null
}

View File

@ -14,14 +14,4 @@ class AddonModifiers : ModifiersBase() {
@JoinColumn(name = "addon_id", nullable = false) @JoinColumn(name = "addon_id", nullable = false)
@JsonIgnore @JsonIgnore
var addon: BuildingAddon? = null var addon: BuildingAddon? = null
fun toDto(): ModifierDto {
return ModifierDto(
id = id!!,
reference = reference,
usageType = usageType,
value = value,
target = target,
)
}
} }

View File

@ -8,9 +8,9 @@ import com.dowstats.data.dto.controllers.WeaponUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.building.BuildingAddonDto import com.dowstats.data.dto.controllers.building.BuildingAddonDto
import com.dowstats.data.dto.controllers.building.BuildingAddonShortDto import com.dowstats.data.dto.controllers.building.BuildingAddonShortDto
import com.dowstats.data.entities.building.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnit import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.Sergeant import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.weapon.Weapon
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.* import jakarta.persistence.*
@ -69,6 +69,7 @@ class BuildingAddon {
var affectedWeapons: MutableSet<Weapon> = mutableSetOf() var affectedWeapons: MutableSet<Weapon> = mutableSetOf()
var uiIndexHint: Int = 0 var uiIndexHint: Int = 0
var uiHotkeyName: String? = null
var icon: String? = null var icon: String? = null
var modId: Long? = null var modId: Long? = null
@ -91,7 +92,9 @@ class BuildingAddon {
affectedWeapons.toShortDtoSet(), affectedWeapons.toShortDtoSet(),
), ),
addonRequirement = addonRequirementDto, addonRequirement = addonRequirementDto,
icon = icon icon = icon,
hotkey = uiHotkeyName
) )
fun toShortDto(): BuildingAddonShortDto = BuildingAddonShortDto( fun toShortDto(): BuildingAddonShortDto = BuildingAddonShortDto(

View File

@ -10,12 +10,13 @@ import com.dowstats.data.dto.controllers.building.BuildingAddonDto
import com.dowstats.data.dto.controllers.building.BuildingFullDto import com.dowstats.data.dto.controllers.building.BuildingFullDto
import com.dowstats.data.dto.controllers.research.ResearchShortDto import com.dowstats.data.dto.controllers.research.ResearchShortDto
import com.dowstats.data.entities.ArmorType import com.dowstats.data.entities.ArmorType
import com.dowstats.data.entities.DowUnit import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.DowUnitObject.toUnitDto import com.dowstats.data.entities.unit.DowUnitObject.toUnitDto
import com.dowstats.data.entities.Race import com.dowstats.data.entities.Race
import com.dowstats.data.entities.Sergeant import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.Weapon.HardpointPosition import com.dowstats.data.entities.weapon.Weapon
import com.dowstats.data.entities.weapon.Weapon.HardpointPosition
import com.dowstats.data.entities.addon.BuildingAddon import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import jakarta.persistence.* import jakarta.persistence.*
@ -59,6 +60,7 @@ class Building {
var detectRadius: Int? = null var detectRadius: Int? = null
var repairMax: Int? = null var repairMax: Int? = null
var uiIndexHint: Int = 0 var uiIndexHint: Int = 0
var uiHotkeyName: String? = null
var advancedBuildOption: Boolean = false var advancedBuildOption: Boolean = false
var icon: String? = null var icon: String? = null
var modId: Long? = null var modId: Long? = null
@ -130,6 +132,30 @@ class Building {
inverseJoinColumns = [JoinColumn(name = "building_id")]) inverseJoinColumns = [JoinColumn(name = "building_id")])
var affectedBuildings: MutableSet<Building> = mutableSetOf() var affectedBuildings: MutableSet<Building> = mutableSetOf()
@ManyToMany
@JoinTable(name = "ability_affected_buildings",
joinColumns = [JoinColumn(name = "building_id")],
inverseJoinColumns = [JoinColumn(name = "ability_id")])
var affectedAbilities: MutableSet<Ability> = mutableSetOf()
@ManyToMany
@JoinTable(name = "sergeant_affected_buildings",
joinColumns = [JoinColumn(name = "building_id")],
inverseJoinColumns = [JoinColumn(name = "sergeant_id")])
var affectedSergeants: MutableSet<Sergeant> = mutableSetOf()
@ManyToMany
@JoinTable(name = "unit_affected_buildings",
joinColumns = [JoinColumn(name = "building_id")],
inverseJoinColumns = [JoinColumn(name = "unit_id")])
var affectedUnits: MutableSet<DowUnit> = mutableSetOf()
@ManyToMany
@JoinTable(name = "building_abilities",
joinColumns = [JoinColumn(name = "building_id")],
inverseJoinColumns = [JoinColumn(name = "ability_id")])
var abilities: MutableSet<Ability> = mutableSetOf()
@OneToMany(mappedBy = "building", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "building", cascade = [CascadeType.ALL])
var buildingRequirements: MutableSet<BuildingRequirements> = mutableSetOf() var buildingRequirements: MutableSet<BuildingRequirements> = mutableSetOf()
@ -163,6 +189,7 @@ class Building {
icon, icon,
modId!!, modId!!,
buildingAddons, buildingAddons,
abilities.map { it.toShortDto() }.toSet(),
researches, researches,
modifiers.map { it.toDto() }, modifiers.map { it.toDto() },
AffectedDataDto( AffectedDataDto(
@ -175,6 +202,7 @@ class Building {
weapons, weapons,
requirement, requirement,
affectedResearches.map { it.toResearchShortDto() }.toSet(), affectedResearches.map { it.toResearchShortDto() }.toSet(),
uiHotkeyName,
) )

View File

@ -15,13 +15,4 @@ class BuildingModifiers : ModifiersBase() {
@JsonIgnore @JsonIgnore
var building: Building? = null var building: Building? = null
fun toDto(): ModifierDto {
return ModifierDto(
id = id!!,
reference = reference,
usageType = usageType,
value = value,
target = target,
)
}
} }

View File

@ -1,7 +1,7 @@
package com.dowstats.data.entities.building package com.dowstats.data.entities.building
import com.dowstats.data.dto.controllers.WeaponSlotDto import com.dowstats.data.dto.controllers.WeaponSlotDto
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.weapon.Weapon
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.* import jakarta.persistence.*
import java.io.Serializable import java.io.Serializable

View File

@ -9,9 +9,9 @@ import com.dowstats.data.dto.controllers.WeaponUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.research.ResearchDto import com.dowstats.data.dto.controllers.research.ResearchDto
import com.dowstats.data.dto.controllers.research.ResearchShortDto import com.dowstats.data.dto.controllers.research.ResearchShortDto
import com.dowstats.data.entities.building.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnit import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.Sergeant import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.Weapon import com.dowstats.data.entities.weapon.Weapon
import jakarta.persistence.* import jakarta.persistence.*
@ -32,6 +32,7 @@ class Research {
var costSouls: Double? = null var costSouls: Double? = null
var costTime: Int? = null var costTime: Int? = null
var uiIndexHint: Int = 0 var uiIndexHint: Int = 0
var uiHotkeyName: String? = null
var icon: String? = null var icon: String? = null
var modId: Long? = null var modId: Long? = null
@ -91,15 +92,7 @@ class Research {
costFaith = costFaith, costFaith = costFaith,
costSouls = costSouls, costSouls = costSouls,
costTime = costTime, costTime = costTime,
modifiers = researchModifiers.map { modifiers = researchModifiers.map { it.toDto() }.sortedBy { it.target },
ModifierDto(
it.id!!,
it.reference,
it.usageType,
it.value,
it.target,
)
}.sortedBy { it.target },
requirements = requirements, requirements = requirements,
affectedData = AffectedDataDto( affectedData = AffectedDataDto(
affectedUnits.map { it.compressDto() }.toSet(), affectedUnits.map { it.compressDto() }.toSet(),
@ -108,5 +101,6 @@ class Research {
affectedWeapons.toShortDtoSet(), affectedWeapons.toShortDtoSet(),
), ),
modId = modId, modId = modId,
hotkey = uiHotkeyName
) )
} }

View File

@ -15,13 +15,4 @@ class ResearchModifiers : ModifiersBase() {
@JsonIgnore @JsonIgnore
var research: Research? = null var research: Research? = null
fun toDto(): ModifierDto {
return ModifierDto(
id = id!!,
reference = reference,
usageType = usageType,
value = value,
target = target,
)
}
} }

View File

@ -1,12 +1,20 @@
package com.dowstats.data.entities package com.dowstats.data.entities.sergant
import com.dowstats.data.dto.controllers.AffectedDataDto
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
import com.dowstats.data.dto.controllers.RequirementDto import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.SergeantDto import com.dowstats.data.dto.controllers.SergeantDto
import com.dowstats.data.dto.controllers.SergeantUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.WeaponSlotDto import com.dowstats.data.dto.controllers.WeaponSlotDto
import com.dowstats.data.entities.Weapon.HardpointPosition import com.dowstats.data.dto.controllers.WeaponUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.entities.ArmorType
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.weapon.Weapon.HardpointPosition
import com.dowstats.data.entities.addon.BuildingAddon import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.weapon.Weapon
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.* import jakarta.persistence.*
@ -44,25 +52,33 @@ class Sergeant {
var health: Int? = null var health: Int? = null
var armour: Double? = null var armour: Double? = null
var healthRegeneration: Double? = null var healthRegeneration: Double? = null
var moraleIncomeMax: Double? = null
var moraleIncomeRate: Double? = null
var moraleDeathPenalty: Int? = null var moraleDeathPenalty: Int? = null
var mass: Int? = null var mass: Int? = null
var upTime: Double? = null var upTime: Double? = null
var sightRadius: Int? = null var sightRadius: Int? = null
var detectRadius: Int? = null var detectRadius: Int? = null
var icon: String? = null var icon: String? = null
var uiHotkeyName: String? = null
var faithIncome: Double? = null var faithIncome: Double? = null
var powerIncome: Double? = null var powerIncome: Double? = null
var requisitionIncome: Double? = null var requisitionIncome: Double? = null
var modId: Long? = null var modId: Long? = null
@Transient @Transient
var weaponHardpoints: MutableSet<HardpointPosition> = mutableSetOf() var weaponHardpoints: MutableSet<HardpointPosition> = mutableSetOf()
@OneToMany(mappedBy = "sergeant", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "sergeant", cascade = [CascadeType.ALL])
var weapons: MutableSet<SergeantWeapon>? = null var weapons: MutableSet<SergeantWeapon>? = null
@ManyToMany
@JoinTable(name = "sergeant_abilities",
joinColumns = [JoinColumn(name = "sergeant_id")],
inverseJoinColumns = [JoinColumn(name = "ability_id")])
var abilities: MutableSet<Ability> = mutableSetOf()
@ManyToMany @ManyToMany
@JoinTable(name = "researches_affected_sergeants", @JoinTable(name = "researches_affected_sergeants",
joinColumns = [JoinColumn(name = "sergeant_id")], joinColumns = [JoinColumn(name = "sergeant_id")],
@ -81,6 +97,52 @@ class Sergeant {
inverseJoinColumns = [JoinColumn(name = "building_id")]) inverseJoinColumns = [JoinColumn(name = "building_id")])
var affectedBuildings: MutableSet<Building> = mutableSetOf() var affectedBuildings: MutableSet<Building> = mutableSetOf()
@ManyToMany
@JoinTable(name = "ability_affected_sergeants",
joinColumns = [JoinColumn(name = "sergeant_id")],
inverseJoinColumns = [JoinColumn(name = "ability_id")])
var affectedAbilities: MutableSet<Ability> = mutableSetOf()
@ManyToMany
@JoinTable(name = "sergeant_affected_sergeants",
joinColumns = [JoinColumn(name = "sergeant_id_affected")],
inverseJoinColumns = [JoinColumn(name = "sergeant_id")])
var affectedSergeants: MutableSet<Sergeant> = mutableSetOf()
@ManyToMany
@JoinTable(name = "units_affected_sergeants",
joinColumns = [JoinColumn(name = "sergeant_id")],
inverseJoinColumns = [JoinColumn(name = "unit_id")])
var affectedUnits: MutableSet<DowUnit> = mutableSetOf()
@ManyToMany
@JoinTable(name = "sergeant_affected_units",
joinColumns = [JoinColumn(name = "sergeant_id")],
inverseJoinColumns = [JoinColumn(name = "unit_id")])
var affectedOnUnits: MutableSet<DowUnit> = mutableSetOf()
@ManyToMany
@JoinTable(name = "sergeant_affected_sergeants",
joinColumns = [JoinColumn(name = "sergeant_id")],
inverseJoinColumns = [JoinColumn(name = "sergeant_id_affected")])
var affectedOnSergeants: MutableSet<Sergeant> = mutableSetOf()
@ManyToMany
@JoinTable(name = "sergeant_affected_buildings",
joinColumns = [JoinColumn(name = "sergeant_id")],
inverseJoinColumns = [JoinColumn(name = "building_id")])
var affectedOnBuildings: MutableSet<Building> = mutableSetOf()
@ManyToMany
@JoinTable( name = "sergeant_affected_weapons",
joinColumns = [JoinColumn(name = "sergeant_id")],
inverseJoinColumns = [JoinColumn(name = "weapon_id")])
var affectedOnWeapons: MutableSet<Weapon> = mutableSetOf()
@OneToMany(mappedBy = "sergeant", cascade = [CascadeType.ALL])
var sergeantModifiers: MutableSet<SergeantModifiers> = mutableSetOf()
@OneToMany(mappedBy = "sergeant", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "sergeant", cascade = [CascadeType.ALL])
var sergeantRequirements: MutableSet<SergeantRequirements> = mutableSetOf() var sergeantRequirements: MutableSet<SergeantRequirements> = mutableSetOf()
@ -105,13 +167,24 @@ class Sergeant {
armour, armour,
healthRegeneration, healthRegeneration,
moraleDeathPenalty, moraleDeathPenalty,
moraleIncomeMax,
moraleIncomeRate,
mass, mass,
upTime, upTime,
sightRadius, sightRadius,
detectRadius, detectRadius,
icon, icon,
weapons.toList(), weapons.toList(),
abilities.sortedWith ( compareBy<Ability> { it.activation?.id }.thenBy{ it.uiIndexHint.let { 0 - it } }).map { it.toShortDto() }.toSet(),
affectedResearches.map { it.toResearchShortDto() }.toSet(), affectedResearches.map { it.toResearchShortDto() }.toSet(),
requirements sergeantModifiers.map { it.toDto() }.sortedBy { it.target },
AffectedDataDto(
affectedOnUnits.map { it.compressDto() }.toSet(),
affectedOnSergeants.toShortDtoSet(),
affectedOnBuildings.map { it.compressDto() }.toSet(),
affectedOnWeapons.toShortDtoSet(),
),
requirements,
uiHotkeyName,
) )
} }

View File

@ -1,7 +1,7 @@
package com.dowstats.data.entities package com.dowstats.data.entities.sergant
import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.WeaponSlotDto import com.dowstats.data.dto.controllers.WeaponSlotDto
import com.dowstats.data.entities.weapon.Weapon
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import java.io.Serializable import java.io.Serializable
import jakarta.persistence.* import jakarta.persistence.*

View File

@ -0,0 +1,20 @@
package com.dowstats.data.entities.sergant
import com.dowstats.data.dto.controllers.ModifierDto
import com.dowstats.data.entities.ModifiersBase
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.unit.DowUnit
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@Entity
@Table(name = "sergeant_modifiers")
class SergeantModifiers : ModifiersBase() {
@ManyToOne
@JoinColumn(name = "sergeant_id", nullable = false)
@JsonIgnore
var sergeant: Sergeant? = null
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities package com.dowstats.data.entities.sergant
import com.dowstats.data.entities.RequirementBase
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.Entity import jakarta.persistence.Entity
import jakarta.persistence.JoinColumn import jakarta.persistence.JoinColumn

View File

@ -1,9 +1,18 @@
package com.dowstats.data.entities package com.dowstats.data.entities.unit
import com.dowstats.data.dto.controllers.* import com.dowstats.data.dto.controllers.*
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
import com.dowstats.data.dto.controllers.SergeantUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.dto.controllers.WeaponUnitShortDtoObject.toShortDtoSet
import com.dowstats.data.entities.ArmorType
import com.dowstats.data.entities.Race
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.addon.BuildingAddon import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.research.ResearchModifiers
import com.dowstats.data.entities.weapon.Weapon
import jakarta.persistence.* import jakarta.persistence.*
@ -72,6 +81,7 @@ class DowUnit {
var requisitionIncome: Double? = null var requisitionIncome: Double? = null
var haveReinforceMenu: Boolean = false var haveReinforceMenu: Boolean = false
var uiIndexHint: Int = 0 var uiIndexHint: Int = 0
var uiHotkeyName: String? = null
var icon: String? = null var icon: String? = null
var modId: Long? = null var modId: Long? = null
@ -81,6 +91,12 @@ class DowUnit {
@OneToMany(mappedBy = "unit", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "unit", cascade = [CascadeType.ALL])
var weapons: MutableSet<UnitWeapon>? = null var weapons: MutableSet<UnitWeapon>? = null
@ManyToMany
@JoinTable(name = "unit_abilities",
joinColumns = [JoinColumn(name = "unit_id")],
inverseJoinColumns = [JoinColumn(name = "ability_id")])
var abilities: MutableSet<Ability> = mutableSetOf()
@ManyToMany @ManyToMany
@JoinTable(name = "researches_affected_units", @JoinTable(name = "researches_affected_units",
joinColumns = [JoinColumn(name = "unit_id")], joinColumns = [JoinColumn(name = "unit_id")],
@ -99,6 +115,52 @@ class DowUnit {
inverseJoinColumns = [JoinColumn(name = "building_id")]) inverseJoinColumns = [JoinColumn(name = "building_id")])
var affectedBuildings: MutableSet<Building> = mutableSetOf() var affectedBuildings: MutableSet<Building> = mutableSetOf()
@ManyToMany
@JoinTable(name = "unit_affected_units",
joinColumns = [JoinColumn(name = "unit_id_affected")],
inverseJoinColumns = [JoinColumn(name = "unit_id")])
var affectedUnits: MutableSet<DowUnit> = mutableSetOf()
@ManyToMany
@JoinTable(name = "sergeant_affected_units",
joinColumns = [JoinColumn(name = "unit_id")],
inverseJoinColumns = [JoinColumn(name = "sergeant_id")])
var affectedSergeants: MutableSet<Sergeant> = mutableSetOf()
@ManyToMany
@JoinTable(name = "ability_affected_units",
joinColumns = [JoinColumn(name = "unit_id")],
inverseJoinColumns = [JoinColumn(name = "ability_id")])
var affectedAbilities: MutableSet<Ability> = mutableSetOf()
@ManyToMany
@JoinTable(name = "unit_affected_units",
joinColumns = [JoinColumn(name = "unit_id")],
inverseJoinColumns = [JoinColumn(name = "unit_id_affected")])
var affectedOnUnits: MutableSet<DowUnit> = mutableSetOf()
@ManyToMany
@JoinTable(name = "units_affected_sergeants",
joinColumns = [JoinColumn(name = "unit_id")],
inverseJoinColumns = [JoinColumn(name = "sergeant_id")])
var affectedOnSergeants: MutableSet<Sergeant> = mutableSetOf()
@ManyToMany
@JoinTable(name = "unit_affected_buildings",
joinColumns = [JoinColumn(name = "unit_id")],
inverseJoinColumns = [JoinColumn(name = "building_id")])
var affectedOnBuildings: MutableSet<Building> = mutableSetOf()
@ManyToMany
@JoinTable( name = "unit_affected_weapons",
joinColumns = [JoinColumn(name = "unit_id")],
inverseJoinColumns = [JoinColumn(name = "weapon_id")])
var affectedOnWeapons: MutableSet<Weapon> = mutableSetOf()
@OneToMany(mappedBy = "unit", cascade = [CascadeType.ALL])
var unitModifiers: MutableSet<UnitModifiers> = mutableSetOf()
@OneToMany(mappedBy = "unit", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "unit", cascade = [CascadeType.ALL])
var unitRequirements: MutableSet<UnitRequirements> = mutableSetOf() var unitRequirements: MutableSet<UnitRequirements> = mutableSetOf()
@ -151,10 +213,19 @@ class DowUnit {
modId!!, modId!!,
sergeantsDtos, sergeantsDtos,
weapons, weapons,
abilities.sortedWith ( compareBy<Ability> { it.activation?.id }.thenBy{ it.uiIndexHint.let { 0 - it } }).map { it.toShortDto() }.toSet(),
haveReinforceMenu, haveReinforceMenu,
affectedResearches.map { it.toResearchShortDto() }.toSet(), affectedResearches.map { it.toResearchShortDto() }.toSet(),
affectedAddons.map { it.toShortDto() }.toSet(), affectedAddons.map { it.toShortDto() }.toSet(),
unitModifiers.map { it.toDto() }.sortedBy { it.target },
AffectedDataDto(
affectedOnUnits.map { it.compressDto() }.toSet(),
affectedOnSergeants.toShortDtoSet(),
affectedOnBuildings.map { it.compressDto() }.toSet(),
affectedOnWeapons.toShortDtoSet(),
),
requirementDto, requirementDto,
uiHotkeyName,
) )
} }

View File

@ -0,0 +1,21 @@
package com.dowstats.data.entities.unit
import com.dowstats.data.dto.controllers.ModifierDto
import com.dowstats.data.entities.ModifiersBase
import com.dowstats.data.entities.building.Building
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@Entity
@Table(name = "unit_modifiers")
class UnitModifiers : ModifiersBase() {
@ManyToOne
@JoinColumn(name = "unit_id", nullable = false)
@JsonIgnore
var unit: DowUnit? = null
var maxLifeTime: Double? = null
}

View File

@ -1,12 +1,12 @@
package com.dowstats.data.entities package com.dowstats.data.entities.unit
import com.dowstats.data.entities.RequirementBase
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.Entity import jakarta.persistence.Entity
import jakarta.persistence.JoinColumn import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne import jakarta.persistence.ManyToOne
import jakarta.persistence.Table import jakarta.persistence.Table
@Entity @Entity
@Table(name = "unit_requirements") @Table(name = "unit_requirements")
class UnitRequirements: RequirementBase() { class UnitRequirements: RequirementBase() {

View File

@ -1,7 +1,7 @@
package com.dowstats.data.entities package com.dowstats.data.entities.unit
import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.WeaponSlotDto import com.dowstats.data.dto.controllers.WeaponSlotDto
import com.dowstats.data.entities.weapon.Weapon
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import java.io.Serializable import java.io.Serializable
import jakarta.persistence.* import jakarta.persistence.*

View File

@ -1,12 +1,17 @@
package com.dowstats.data.entities package com.dowstats.data.entities.weapon
import com.dowstats.data.dto.controllers.RequirementDto import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.WeaponDto import com.dowstats.data.dto.controllers.WeaponDto
import com.dowstats.data.dto.controllers.WeaponShortDto import com.dowstats.data.dto.controllers.WeaponShortDto
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.sergant.SergeantWeapon
import com.dowstats.data.entities.addon.BuildingAddon import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.building.BuildingWeapon import com.dowstats.data.entities.building.BuildingWeapon
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.unit.UnitWeapon
import jakarta.persistence.* import jakarta.persistence.*
@ -39,6 +44,7 @@ class Weapon {
var isMeleeWeapon: Boolean = true var isMeleeWeapon: Boolean = true
var canAttackAir: Boolean = true var canAttackAir: Boolean = true
var canAttackGround: Boolean = true var canAttackGround: Boolean = true
var uiHotkeyName: String? = null
var icon: String? = null var icon: String? = null
var showInReinforce: Boolean = true var showInReinforce: Boolean = true
var modId: Long? = null var modId: Long? = null
@ -61,6 +67,24 @@ class Weapon {
inverseJoinColumns = [JoinColumn(name = "building_id")]) inverseJoinColumns = [JoinColumn(name = "building_id")])
var affectedBuildings: MutableSet<Building> = mutableSetOf() var affectedBuildings: MutableSet<Building> = mutableSetOf()
@ManyToMany
@JoinTable(name = "ability_affected_weapons",
joinColumns = [JoinColumn(name = "weapon_id")],
inverseJoinColumns = [JoinColumn(name = "ability_id")])
var affectedAbilities: MutableSet<Ability> = mutableSetOf()
@ManyToMany
@JoinTable(name = "sergeant_affected_weapons",
joinColumns = [JoinColumn(name = "weapon_id")],
inverseJoinColumns = [JoinColumn(name = "sergeant_id")])
var affectedSergeants: MutableSet<Sergeant> = mutableSetOf()
@ManyToMany
@JoinTable(name = "unit_affected_weapons",
joinColumns = [JoinColumn(name = "weapon_id")],
inverseJoinColumns = [JoinColumn(name = "unit_id")])
var affectedUnits: MutableSet<DowUnit> = mutableSetOf()
@OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
var unitsUse: MutableSet<UnitWeapon>? = null var unitsUse: MutableSet<UnitWeapon>? = null
@ -73,6 +97,9 @@ class Weapon {
// for many-to-many persistance // for many-to-many persistance
data class HardpointPosition(val weaponId: Long, val hardpoint: Int, val order: Int) data class HardpointPosition(val weaponId: Long, val hardpoint: Int, val order: Int)
@OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
var weaponModifiers: MutableSet<WeaponModifiers> = mutableSetOf()
@OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL]) @OneToMany(mappedBy = "weapon", cascade = [CascadeType.ALL])
var weaponRequirements: MutableSet<WeaponRequirements> = mutableSetOf() var weaponRequirements: MutableSet<WeaponRequirements> = mutableSetOf()
@ -110,7 +137,9 @@ class Weapon {
weaponPiercings.map { it.toDto() }, weaponPiercings.map { it.toDto() },
affectedResearches.map { it.toResearchShortDto() }.toSet(), affectedResearches.map { it.toResearchShortDto() }.toSet(),
affectedAddons.map { it.toShortDto() }.toSet(), affectedAddons.map { it.toShortDto() }.toSet(),
weaponModifiers.map { mod -> mod.toDto().copy(maxLifeTime = mod.maxLifeTime) },
requirementDto, requirementDto,
uiHotkeyName,
) )
fun toShortDto() = WeaponShortDto( fun toShortDto() = WeaponShortDto(

View File

@ -1,6 +1,7 @@
package com.dowstats.data.entities package com.dowstats.data.entities.weapon
import com.dowstats.data.dto.controllers.WeaponArmorPiercingDto import com.dowstats.data.dto.controllers.WeaponArmorPiercingDto
import com.dowstats.data.entities.ArmorType
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import java.math.BigDecimal import java.math.BigDecimal
import jakarta.persistence.* import jakarta.persistence.*

View File

@ -0,0 +1,22 @@
package com.dowstats.data.entities.weapon
import com.dowstats.data.dto.controllers.ModifierDto
import com.dowstats.data.entities.ModifiersBase
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.unit.DowUnit
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@Entity
@Table(name = "weapon_modifiers")
class WeaponModifiers : ModifiersBase() {
@ManyToOne
@JoinColumn(name = "weapon_id", nullable = false)
@JsonIgnore
var weapon: Weapon? = null
var maxLifeTime: Double? = null
}

View File

@ -1,5 +1,6 @@
package com.dowstats.data.entities package com.dowstats.data.entities.weapon
import com.dowstats.data.entities.RequirementBase
import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.Entity import jakarta.persistence.Entity
import jakarta.persistence.JoinColumn import jakarta.persistence.JoinColumn

View File

@ -0,0 +1,14 @@
package com.dowstats.data.repositories
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.Race
import com.dowstats.data.entities.ability.Ability
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.*
interface AbilityRepository : CrudRepository<Ability, Long> {
fun findAllByModId(modId: Long): List<Ability>
fun deleteAllByModId(modId: Long)
}

View File

@ -0,0 +1,10 @@
package com.dowstats.data.repositories
import com.dowstats.data.entities.Activation
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.Race
import com.dowstats.data.entities.ability.Ability
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.*
interface ActivationRepository : CrudRepository<Activation, Long>

View File

@ -0,0 +1,6 @@
package com.dowstats.data.repositories
import com.dowstats.data.entities.AreaEffect
import org.springframework.data.repository.CrudRepository
interface AreaEffectRepository : CrudRepository<AreaEffect, Long>

View File

@ -0,0 +1,6 @@
package com.dowstats.data.repositories
import com.dowstats.data.entities.AreaFilter
import org.springframework.data.repository.CrudRepository
interface AreaFilterRepository : CrudRepository<AreaFilter, Long>

View File

@ -1,8 +1,5 @@
package com.dowstats.data.repositories package com.dowstats.data.repositories
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Weapon
import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import org.springframework.data.repository.* import org.springframework.data.repository.*

View File

@ -1,7 +1,6 @@
package com.dowstats.data.repositories package com.dowstats.data.repositories
import com.dowstats.data.entities.Sergeant import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.Weapon
import org.springframework.data.repository.CrudRepository import org.springframework.data.repository.CrudRepository
interface SergeantRepository : CrudRepository<Sergeant, Long>{ interface SergeantRepository : CrudRepository<Sergeant, Long>{

View File

@ -1,6 +1,6 @@
package com.dowstats.data.repositories package com.dowstats.data.repositories
import com.dowstats.data.entities.DowUnit import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.Race import com.dowstats.data.entities.Race
import org.springframework.data.jpa.repository.Query import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.* import org.springframework.data.repository.*

View File

@ -1,8 +1,6 @@
package com.dowstats.data.repositories package com.dowstats.data.repositories
import com.dowstats.data.entities.DowUnit import com.dowstats.data.entities.weapon.Weapon
import com.dowstats.data.entities.Weapon
import com.dowstats.data.entities.research.Research
import org.springframework.data.repository.* import org.springframework.data.repository.*
interface WeaponRepository : CrudRepository<Weapon, Long>{ interface WeaponRepository : CrudRepository<Weapon, Long>{

View File

@ -0,0 +1,36 @@
package com.dowstats.service.datamaps
import com.dowstats.data.dto.controllers.RequirementDto
import com.dowstats.data.dto.controllers.ability.AbilityDto
import com.dowstats.data.dto.controllers.research.ResearchDto
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.repositories.AbilityRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
@Service
class AbilityService @Autowired constructor(
val abilityRepository: AbilityRepository,
val requirementsMappingComponent: RequirementsMappingComponent,
) {
fun getAbilityDto(id: Long, modId: Long): AbilityDto {
val ability = abilityRepository.findById(id).get()
val requirements = requirementsMappingComponent
.getRequirements(ability.abilityRequirements.toList() ,
modId)
if(ability.childAbilityName == null) return ability.toDto(requirements, null) else {
val allAbilities = abilityRepository.findAllByModId(modId)
return toDtoWithChild(requirements, allAbilities, ability)
}
}
fun toDtoWithChild(requirements: RequirementDto?, allAbilities: List<Ability>, ability: Ability): AbilityDto =
if(ability.childAbilityName == null || ability.childAbilityName == "") ability.toDto(requirements, null) else {
ability.toDto(requirements,
toDtoWithChild(requirements, allAbilities,
allAbilities.first { it.filename?.replace(".rgd", "") == ability.childAbilityName })
)
}
}

View File

@ -2,7 +2,7 @@ package com.dowstats.service.datamaps
import com.dowstats.data.dto.controllers.building.BuildingShortDto import com.dowstats.data.dto.controllers.building.BuildingShortDto
import com.dowstats.data.entities.building.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnitObject.toUnitDto import com.dowstats.data.entities.unit.DowUnitObject.toUnitDto
object CommonMapping { object CommonMapping {
fun List<Building>.toBuildingShortDto(withoutUnits: Boolean = false): List<BuildingShortDto> = fun List<Building>.toBuildingShortDto(withoutUnits: Boolean = false): List<BuildingShortDto> =

View File

@ -3,10 +3,10 @@ package com.dowstats.service.datamaps
import com.dowstats.data.dto.controllers.RaceUnits import com.dowstats.data.dto.controllers.RaceUnits
import com.dowstats.data.dto.controllers.SergeantDto import com.dowstats.data.dto.controllers.SergeantDto
import com.dowstats.data.dto.controllers.UnitFullDto import com.dowstats.data.dto.controllers.UnitFullDto
import com.dowstats.data.entities.DowUnit import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.DowUnitObject.toUnitDto import com.dowstats.data.entities.unit.DowUnitObject.toUnitDto
import com.dowstats.data.entities.Race import com.dowstats.data.entities.Race
import com.dowstats.data.entities.Sergeant import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.repositories.RaceRepository import com.dowstats.data.repositories.RaceRepository
import com.dowstats.data.repositories.UnitRepository import com.dowstats.data.repositories.UnitRepository
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired

View File

@ -1,15 +1,6 @@
package com.dowstats.service.datamaps package com.dowstats.service.datamaps
import com.dowstats.data.dto.controllers.RaceUnits
import com.dowstats.data.dto.controllers.SergeantDto
import com.dowstats.data.dto.controllers.UnitFullDto
import com.dowstats.data.dto.controllers.WeaponDto import com.dowstats.data.dto.controllers.WeaponDto
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.DowUnitObject.toUnitDto
import com.dowstats.data.entities.Race
import com.dowstats.data.entities.Sergeant
import com.dowstats.data.repositories.RaceRepository
import com.dowstats.data.repositories.UnitRepository
import com.dowstats.data.repositories.WeaponRepository import com.dowstats.data.repositories.WeaponRepository
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service import org.springframework.stereotype.Service

View File

@ -1,9 +1,13 @@
package com.dowstats.service.postparsing package com.dowstats.service.postparsing
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.addon.BuildingAddon import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.weapon.Weapon
import com.dowstats.data.repositories.* import com.dowstats.data.repositories.*
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
@ -15,6 +19,7 @@ class PostParsingService @Autowired constructor(
val researchRepository: ResearchRepository, val researchRepository: ResearchRepository,
val addonRepository: AddonRepository, val addonRepository: AddonRepository,
val unitRepository: UnitRepository, val unitRepository: UnitRepository,
val abilityRepository: AbilityRepository,
val sergeantRepository: SergeantRepository, val sergeantRepository: SergeantRepository,
val buildingRepository: BuildingRepository, val buildingRepository: BuildingRepository,
val weaponRepository: WeaponRepository, val weaponRepository: WeaponRepository,
@ -27,6 +32,7 @@ class PostParsingService @Autowired constructor(
val modId = mod.id!! val modId = mod.id!!
val researches = researchRepository.findAllByModId(modId) val researches = researchRepository.findAllByModId(modId)
val addons = addonRepository.findAllByModId(modId) val addons = addonRepository.findAllByModId(modId)
val abilities = abilityRepository.findAllByModId(modId)
val units = unitRepository.findByModIdAndRace(modId, null) val units = unitRepository.findByModIdAndRace(modId, null)
val sergeants = sergeantRepository.findAllByModId(modId) val sergeants = sergeantRepository.findAllByModId(modId)
val buildings = buildingRepository.findByModIdAndRace(modId, null) val buildings = buildingRepository.findByModIdAndRace(modId, null)
@ -47,6 +53,21 @@ class PostParsingService @Autowired constructor(
bindBuildingToAffectedBuildings(buildings) bindBuildingToAffectedBuildings(buildings)
bindBuildingWeapons(weapons, buildings) bindBuildingWeapons(weapons, buildings)
bindAbilityUnits(units, abilities)
bindAbilitySergeants(sergeants, abilities)
bindAbilityBuildings(buildings, abilities)
bindAbilityWeapons(weapons, abilities)
bindSergeantUnits(units, sergeants)
bindSergeantSergeants(sergeants)
bindSergeantBuildings(buildings, sergeants)
bindSergeantWeapons(weapons, sergeants)
bindUnitUnits(units)
bindUnitSergeants(sergeants, units)
bindUnitBuildings(buildings, units)
bindUnitWeapons(weapons, units)
} catch (e: Exception) { } catch (e: Exception) {
log.warn("Error occurred during bind researches", e) log.warn("Error occurred during bind researches", e)
} }
@ -232,4 +253,181 @@ class PostParsingService @Autowired constructor(
weaponRepository.saveAll(weaponsWithBindings) weaponRepository.saveAll(weaponsWithBindings)
log.info("Successfully bind buildings to weapons") log.info("Successfully bind buildings to weapons")
} }
// ------------------------------------------------------------
private fun bindAbilityUnits(units: List<DowUnit>, abilities: List<Ability>) {
val unitsWithBindings: List<DowUnit> = abilities.flatMap { ability ->
ability.abilityModifiers.mapNotNull { modifier ->
units.find {
it.filenameSquad?.replace(".rgd", "") == modifier.target ||
it.filenameUnit?.replace(".rgd", "") == modifier.target
}
?.let {
it.affectedAbilities.add(ability)
it
}
}
}
unitRepository.saveAll(unitsWithBindings)
log.info("Successfully bind abilities to units")
}
private fun bindAbilitySergeants(sergeants: List<Sergeant>, abilities: List<Ability>) {
val sergeantsWithBindings: List<Sergeant> = abilities.flatMap { ability ->
ability.abilityModifiers.mapNotNull { modifier ->
sergeants.find { it.filename.replace(".rgd", "") == modifier.target }?.let {
it.affectedAbilities.add(ability)
it
}
}
}
sergeantRepository.saveAll(sergeantsWithBindings)
log.info("Successfully bind abilities to sergeants")
}
private fun bindAbilityBuildings(buildings: List<Building>, abilities: List<Ability>) {
val buildingsWithBindings: List<Building> = abilities.flatMap { ability ->
ability.abilityModifiers.mapNotNull { modifier ->
buildings.find { it.filename?.replace(".rgd", "") == modifier.target }?.let {
it.affectedAbilities.add(ability)
it
}
}
}
buildingRepository.saveAll(buildingsWithBindings)
log.info("Successfully bind abilities to buildings")
}
private fun bindAbilityWeapons(weapons: List<Weapon>, abilities: List<Ability>) {
val weaponsWithBindings: List<Weapon> = abilities.flatMap { ability ->
ability.abilityModifiers.mapNotNull { modifier ->
weapons.find { it.filename?.replace(".rgd", "") == modifier.target }?.let {
it.affectedAbilities.add(ability)
it
}
}
}
weaponRepository.saveAll(weaponsWithBindings)
log.info("Successfully bind abilities to weapons")
}
// ------------------------------------------------------------
private fun bindSergeantUnits(units: List<DowUnit>, sergeants: List<Sergeant>) {
val unitsWithBindings: List<DowUnit> = sergeants.flatMap { sergeant ->
sergeant.sergeantModifiers.mapNotNull { modifier ->
units.find {
it.filenameSquad?.replace(".rgd", "") == modifier.target ||
it.filenameUnit?.replace(".rgd", "") == modifier.target
}
?.let {
it.affectedSergeants.add(sergeant)
it
}
}
}
unitRepository.saveAll(unitsWithBindings)
log.info("Successfully bind sergeants to units")
}
private fun bindSergeantSergeants(sergeants: List<Sergeant>) {
val sergeantsWithBindings: List<Sergeant> = sergeants.flatMap { sergeant ->
sergeant.sergeantModifiers.mapNotNull { modifier ->
sergeants.find { it.filename.replace(".rgd", "") == modifier.target }?.let {
it.affectedSergeants.add(sergeant)
it
}
}
}
sergeantRepository.saveAll(sergeantsWithBindings)
log.info("Successfully bind sergeants to sergeants")
}
private fun bindSergeantBuildings(buildings: List<Building>, sergeants: List<Sergeant>) {
val buildingsWithBindings: List<Building> = sergeants.flatMap { sergeant ->
sergeant.sergeantModifiers.mapNotNull { modifier ->
buildings.find { it.filename?.replace(".rgd", "") == modifier.target }?.let {
it.affectedSergeants.add(sergeant)
it
}
}
}
buildingRepository.saveAll(buildingsWithBindings)
log.info("Successfully bind sergeants to buildings")
}
private fun bindSergeantWeapons(weapons: List<Weapon>, sergeants: List<Sergeant>) {
val weaponsWithBindings: List<Weapon> = sergeants.flatMap { sergeant ->
sergeant.sergeantModifiers.mapNotNull { modifier ->
weapons.find { it.filename?.replace(".rgd", "") == modifier.target }?.let {
it.affectedSergeants.add(sergeant)
it
}
}
}
weaponRepository.saveAll(weaponsWithBindings)
log.info("Successfully bind sergeants to weapons")
}
// ------------------------------------------------------------
private fun bindUnitUnits(units: List<DowUnit>) {
val unitsWithBindings: List<DowUnit> = units.flatMap { unit ->
unit.unitModifiers.mapNotNull { modifier ->
units.find {
it.filenameSquad?.replace(".rgd", "") == modifier.target ||
it.filenameUnit?.replace(".rgd", "") == modifier.target
}
?.let {
it.affectedUnits.add(unit)
it
}
}
}
unitRepository.saveAll(unitsWithBindings)
log.info("Successfully bind units to units")
}
private fun bindUnitSergeants(sergeants: List<Sergeant>, units: List<DowUnit>) {
val sergeantsWithBindings: List<Sergeant> = units.flatMap { unit ->
unit.unitModifiers.mapNotNull { modifier ->
sergeants.find { it.filename.replace(".rgd", "") == modifier.target }?.let {
it.affectedUnits.add(unit)
it
}
}
}
sergeantRepository.saveAll(sergeantsWithBindings)
log.info("Successfully bind units to sergeants")
}
private fun bindUnitBuildings(buildings: List<Building>, units: List<DowUnit>) {
val buildingsWithBindings: List<Building> = units.flatMap { unit ->
unit.unitModifiers.mapNotNull { modifier ->
buildings.find { it.filename?.replace(".rgd", "") == modifier.target }?.let {
it.affectedUnits.add(unit)
it
}
}
}
buildingRepository.saveAll(buildingsWithBindings)
log.info("Successfully bind units to buildings")
}
private fun bindUnitWeapons(weapons: List<Weapon>, units: List<DowUnit>) {
val weaponsWithBindings: List<Weapon> = units.flatMap { unit ->
unit.unitModifiers.mapNotNull { modifier ->
weapons.find { it.filename?.replace(".rgd", "") == modifier.target }?.let {
it.affectedUnits.add(unit)
it
}
}
}
weaponRepository.saveAll(weaponsWithBindings)
log.info("Successfully bind units to weapons")
}
} }

View File

@ -0,0 +1,166 @@
package com.dowstats.service.w40k
import com.dowstats.Metadata
import com.dowstats.data.dto.BuildCost
import com.dowstats.data.entities.Activation
import com.dowstats.data.entities.AreaEffect
import com.dowstats.data.entities.AreaFilter
import com.dowstats.data.entities.ArmorType
import com.dowstats.data.entities.Mod
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.fillDataFromRgdTable
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.ability.AbilityArmorPiercing
import com.dowstats.data.entities.ability.AbilityModifiers
import com.dowstats.data.entities.ability.AbilityRequirements
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.math.BigDecimal
@Service
class AbilityRgdExtractService @Autowired constructor(
private val commonParseRgdService: CommonParseRgdService,
) {
val log = LoggerFactory.getLogger(AbilityRgdExtractService::class.java)
fun extractToAbilityEntity(
fileName: String,
abilityData: List<RgdData>,
mod: Mod,
activations: Set<Activation>,
areaEffects: Set<AreaEffect>,
areaFilters: Set<AreaFilter>,
armorTypes: Set<ArmorType>,
modFolderData: String,
modDictionary: Map<Int, String>
): Ability? {
val ability = Ability()
ability.filename = fileName
ability.modId = mod.id
val activationValue = abilityData.getRgdTableByName("activation")?.getStringByName("\$REF")?.replace("type_abilityactivation\\tp_","")?.replace(".lua","")
ability.activation = activations.firstOrNull { it.id == activationValue }
// UI Info & Basic Data
val uiInfo = abilityData.getRgdTableByName("ui_info")
val uiData = uiInfo?.let{ commonParseRgdService.getUiInfo(uiInfo, modDictionary, modFolderData, mod, log, ability.activation?.id == "ability_activation_toggled")}
ability.name = uiData?.name
ability.description = uiData?.description
ability.icon = uiData?.iconPath
ability.uiIndexHint = abilityData.getIntByName("ui_index_hint") ?: 0
ability.uiHotkeyName = abilityData.getStringByName("ui_hotkey_name")
// Costs
val fireCost = abilityData.getRgdTableByName("fire_cost")
ability.costRequisition = fireCost?.getDoubleByName("requisition")
ability.costPower = fireCost?.getDoubleByName("power")
ability.costFaith = fireCost?.getDoubleByName("faith")
ability.costSouls = fireCost?.getDoubleByName("souls")
// Ability Specific Params
ability.childAbilityName = abilityData.getStringByName("child_ability_name")
ability.initialDelayTime = abilityData.getDoubleByName("initial_delay_time")
ability.range = abilityData.getDoubleByName("range")
ability.rechargeTime = abilityData.getDoubleByName("recharge_time")
ability.rechargeTimerGlobal = abilityData.getBooleanByName("recharge_timer_global")
ability.refreshTime = abilityData.getDoubleByName("refresh_time")
ability.durationTime = abilityData.getDoubleByName("duration_time")
ability.spawnedEntityName = abilityData.getStringByName("spawn_entity_name")
// Damage & Area Effect
val areaEffectTable = abilityData.getRgdTableByName("area_effect")
if (areaEffectTable != null) {
val areaEffectData = commonParseRgdService.getAreaEffectData(areaEffectTable)
val targetFilter = areaEffectTable
.getRgdTableByName("area_effect_information")
?.getRgdTableByName("target_filter")
?.mapNotNull { m ->
if (m.name.contains("entry_")) {
val target = m.value as List<RgdData>
val armorType = target.getStringByName("\$REF")?.replace("type_armour\\tp_","")?.replace(".lua","")
armorTypes.firstOrNull { it.id == armorType }
} else null
} ?: emptyList()
ability.abilityTargetFilters = targetFilter.toMutableSet()
ability.radius = areaEffectData.damageRadius
ability.minDamage = areaEffectData.minDamage
ability.minDamageValue = areaEffectData.minDamageValue
ability.maxDamage = areaEffectData.maxDamage
ability.moraleDamage = areaEffectData.moraleDamage
ability.throwForceMin = areaEffectData.throwForceMin
ability.throwForceMax = areaEffectData.throwForceMax
ability.areaEffect = areaEffects.firstOrNull { it.id == areaEffectData.areaType }
ability.areaFilter = areaFilters.firstOrNull { it.id == areaEffectData.filterType }
// Armor Piercings
ability.abilityPiercings = armorTypes.map { armorType ->
AbilityArmorPiercing().also {
it.ability = ability
it.armorType = armorType
val piercingValue = (areaEffectData.weaponDmgMap[armorType.id] ?: areaEffectData.defaultArmorPiercing)?.toBigDecimal()
it.piercingValue = piercingValue?.let { pv -> if (pv <= BigDecimal(100)) pv else BigDecimal(100) }
}
}.toMutableSet()
}
// Modifiers & Requirements
ability.abilityModifiers = getAbilityModifiers(ability, abilityData).toMutableSet()
ability.abilityRequirements = getAbilityRequirements(ability, abilityData).toMutableSet()
return ability
}
private fun getAbilityModifiers(ability: Ability, abilityData: List<RgdData>): List<AbilityModifiers> {
return abilityData
.getRgdTableByName("area_effect")
?.getRgdTableByName("weapon_damage")
?.getRgdTableByName("modifiers")?.mapNotNull { m ->
if (m.name.contains("modifier_")) {
val mTable = m.value as List<RgdData>
if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua") null else {
val mTable = m.value as List<RgdData>
val modifier = mTable.getRgdTableByName("modifier")
val maxLifetime = mTable.getDoubleByName("max_lifetime")
if (modifier?.getStringByName("\$REF") == "modifiers\\no_modifier.lua" || modifier == null) null else {
AbilityModifiers().also {
it.ability = ability
it.maxLifeTime = maxLifetime
}.fillDataFromRgdTable(modifier)
}
}
} else null
}?.filterUseless() ?: emptyList()
}
private fun getAbilityRequirements(ability: Ability, abilityData: List<RgdData>): List<AbilityRequirements> {
return abilityData.getRgdTableByName("requirements")?.mapNotNull { r ->
if (r.name.contains("required_")) {
val rTable = r.value as List<RgdData>
if (rTable.getStringByName("\$REF") == Metadata.Requirements.REFERENCE_REQUIREMENT_NONE) null else {
AbilityRequirements().also {
it.ability = ability
it.reference = rTable.getStringByName("\$REF")
it.value = commonParseRgdService.getRequirementReference(it.reference, rTable, ability.filename!!, log)
}
}
} else null
} ?: emptyList()
}
}

View File

@ -2,6 +2,7 @@ package com.dowstats.service.w40k
import com.dowstats.Metadata import com.dowstats.Metadata
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.fillDataFromRgdTable
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.addon.AddonModifiers import com.dowstats.data.entities.addon.AddonModifiers
import com.dowstats.data.entities.addon.AddonRequirements import com.dowstats.data.entities.addon.AddonRequirements
@ -40,6 +41,7 @@ class BuildingAddonRgdExtractService @Autowired constructor(
addon.name = uiInfo.name addon.name = uiInfo.name
addon.description = uiInfo.description addon.description = uiInfo.description
addon.uiIndexHint = addonRgdData.getIntByName("ui_index_hint") ?: 0 addon.uiIndexHint = addonRgdData.getIntByName("ui_index_hint") ?: 0
addon.uiHotkeyName = addonRgdData.getStringByName("ui_hotkey_name")
addon.icon = uiInfo.iconPath addon.icon = uiInfo.iconPath
addon.filename = fileName addon.filename = fileName
@ -66,11 +68,7 @@ class BuildingAddonRgdExtractService @Autowired constructor(
if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua") null else { if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua") null else {
AddonModifiers().also { AddonModifiers().also {
it.addon = addon it.addon = addon
it.reference = mTable.getStringByName("\$REF") }.fillDataFromRgdTable(mTable)
it.target = mTable.getStringByName("target_type_name")
it.usageType = mTable.getRgdTableByName("usage_type")?.getStringByName("\$REF")
it.value = mTable.getDoubleByName("value")
}
} }
} else null } else null
}?.filterUseless() ?: emptyList() }?.filterUseless() ?: emptyList()

View File

@ -3,11 +3,15 @@ package com.dowstats.service.w40k
import com.dowstats.Metadata import com.dowstats.Metadata
import com.dowstats.data.dto.BuildingDataToSave import com.dowstats.data.dto.BuildingDataToSave
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.fillDataFromRgdTable
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.building.Building import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.building.BuildingModifiers import com.dowstats.data.entities.building.BuildingModifiers
import com.dowstats.data.entities.building.BuildingRequirements import com.dowstats.data.entities.building.BuildingRequirements
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.weapon.Weapon
import com.dowstats.data.rgd.RgdData import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
@ -44,6 +48,7 @@ class BuildingRgdExtractService @Autowired constructor(
modDictionary: Map<Int, String>, modDictionary: Map<Int, String>,
buildingData: List<RgdData>, buildingData: List<RgdData>,
weapons: Set<Weapon>, weapons: Set<Weapon>,
abilities: Set<Ability>,
researches: Set<Research>, researches: Set<Research>,
units: List<DowUnit>, units: List<DowUnit>,
race: Race, race: Race,
@ -61,13 +66,14 @@ class BuildingRgdExtractService @Autowired constructor(
building.armorType2 = getBuildingArmourType(buildingData, armorTypes, "type_armour_2") building.armorType2 = getBuildingArmourType(buildingData, armorTypes, "type_armour_2")
building.filename = fileName building.filename = fileName
val buildingUiInfo = buildingData.getRgdTableByName("ui_ext") val uiExt = buildingData.getRgdTableByName("ui_ext") ?: throw Exception("Could not find ui_ext at $fileName")
?.getRgdTableByName("ui_info") ?: throw Exception("Could not find ui_info at $fileName") val buildingUiInfo = uiExt.getRgdTableByName("ui_info") ?: throw Exception("Could not find ui_info at $fileName")
val buildingUiData = commonParseRgdService.getUiInfo(buildingUiInfo, modDictionary, modFolderData, mod, log) val buildingUiData = commonParseRgdService.getUiInfo(buildingUiInfo, modDictionary, modFolderData, mod, log)
building.name = buildingUiData.name building.name = buildingUiData.name
building.description = buildingUiData.description building.description = buildingUiData.description
building.icon = buildingUiData.iconPath building.icon = buildingUiData.iconPath
building.uiIndexHint = buildingData.getRgdTableByName("ui_ext")?.getIntByName("ui_index_hint") ?: 0 building.uiIndexHint = uiExt.getIntByName("ui_index_hint") ?: 0
building.uiHotkeyName = uiExt.getStringByName("ui_hotkey_name")
building.advancedBuildOption = buildingData.getRgdTableByName("structure_buildable_ext")?.getBooleanByName("advanced_build_option") ?: false building.advancedBuildOption = buildingData.getRgdTableByName("structure_buildable_ext")?.getBooleanByName("advanced_build_option") ?: false
val buildCost = commonParseRgdService.getBuildCost(buildingData.getRgdTableByName("cost_ext")?.getRgdTableByName("time_cost")) val buildCost = commonParseRgdService.getBuildCost(buildingData.getRgdTableByName("cost_ext")?.getRgdTableByName("time_cost"))
@ -101,6 +107,8 @@ class BuildingRgdExtractService @Autowired constructor(
building.buildingRequirements = getBuildingRequirements(building, buildingData).toMutableSet() building.buildingRequirements = getBuildingRequirements(building, buildingData).toMutableSet()
building.abilities = commonParseRgdService.getAbilities(buildingData, abilities).toMutableSet()
val addons = getAddons(buildingData) val addons = getAddons(buildingData)
building.addons = addons?.mapNotNull {addonFileName -> building.addons = addons?.mapNotNull {addonFileName ->
val addonRgdData = addonsRgdData[addonFileName] val addonRgdData = addonsRgdData[addonFileName]
@ -172,7 +180,7 @@ class BuildingRgdExtractService @Autowired constructor(
if (it != "") { if (it != "") {
WeaponsData(hardpointValue, WeaponsData(hardpointValue,
weapon.name.replace("weapon_", "").toInt(), weapon.name.replace("weapon_", "").toInt(),
it.replace("weapon\\", "").replace(".lua", "")) it.replace("weapon\\", "").replace(".lua", "").replace(".rgd", ""))
} else null } else null
} }
} }
@ -226,11 +234,7 @@ class BuildingRgdExtractService @Autowired constructor(
if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua" || mTable.getStringByName("\$REF") == "modifiers\\enable_infiltration.lua" ) null else { if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua" || mTable.getStringByName("\$REF") == "modifiers\\enable_infiltration.lua" ) null else {
BuildingModifiers().also { BuildingModifiers().also {
it.building = building it.building = building
it.reference = mTable.getStringByName("\$REF") }.fillDataFromRgdTable(mTable)
it.target = mTable.getStringByName("target_type_name")
it.usageType = mTable.getRgdTableByName("usage_type")?.getStringByName("\$REF")
it.value = mTable.getDoubleByName("value")
}
} }
} else null } else null
}.filterUseless() }.filterUseless()

View File

@ -6,6 +6,7 @@ import com.dowstats.data.dto.BuildCost
import com.dowstats.data.dto.ResourceIncome import com.dowstats.data.dto.ResourceIncome
import com.dowstats.data.dto.UiInfo import com.dowstats.data.dto.UiInfo
import com.dowstats.data.entities.Mod import com.dowstats.data.entities.Mod
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.rgd.RgdData import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
@ -67,7 +68,7 @@ class CommonParseRgdService @Autowired constructor(
} }
fun getUiInfo(uiInfoRgdData: List<RgdData>, modDictionary: Map<Int, String>, modFolderData: String, mod: Mod, log: Logger): UiInfo { 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 nameRef = uiInfoRgdData?.getStringByName("screen_name_id")?.replace("$", "")
val name = nameRef?.let { try { modDictionary[it.toInt()] } catch (e: Exception) { it } } val name = nameRef?.let { try { modDictionary[it.toInt()] } catch (e: Exception) { it } }
@ -89,7 +90,9 @@ class CommonParseRgdService @Autowired constructor(
} }
val icon = try { val icon = try {
val iconPath = uiInfoRgdData.getStringByName("icon_name") val iconPath = if (isOnOfAbility) {
uiInfoRgdData.getStringByName("icon_name") + "_off"
} else uiInfoRgdData.getStringByName("icon_name")
iconPath?.let { modAttribPathService.getIconPath(modFolderData, iconPath) } iconPath?.let { modAttribPathService.getIconPath(modFolderData, iconPath) }
?.let { iconsService.convertTgaToJpegImage(iconPath, it, mod.name) } ?.let { iconsService.convertTgaToJpegImage(iconPath, it, mod.name) }
@ -101,19 +104,29 @@ class CommonParseRgdService @Autowired constructor(
return UiInfo(name, description, icon) return UiInfo(name, description, icon)
} }
fun getAreaEffectData(weaponData: List<RgdData>): AreaEffect { fun getAreaEffectData(areaEffectData: List<RgdData>): AreaEffect {
val areaEffect = weaponData.getRgdTableByName("area_effect")
val areaEffectInformation = areaEffect?.getRgdTableByName("area_effect_information") val areaEffectInformation = areaEffectData.getRgdTableByName("area_effect_information")
val cantHaveRadius = areaEffectInformation?.getRgdTableByName("area_type")?.getStringByName("\$REF")?.contains("tp_area_effect_point") == true
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 damageRadius = if(cantHaveRadius) 0.0 else areaEffectInformation?.getDoubleByName("radius") ?: 0.0
val throwData = areaEffect?.getRgdTableByName("throw_data") val throwData = areaEffectData.getRgdTableByName("throw_data")
val forceMin = throwData?.getDoubleByName("force_min") ?: 0.0 val forceMin = throwData?.getDoubleByName("force_min") ?: 0.0
val forceMax = throwData?.getDoubleByName("force_max") ?: 0.0 val forceMax = throwData?.getDoubleByName("force_max") ?: 0.0
val armourDamage = areaEffect val armourDamage = areaEffectData
?.getRgdTableByName("weapon_damage") .getRgdTableByName("weapon_damage")
?.getRgdTableByName("armour_damage") ?.getRgdTableByName("armour_damage")
val minDamage = armourDamage?.getDoubleByName("min_damage") ?: 0.0 val minDamage = armourDamage?.getDoubleByName("min_damage") ?: 0.0
val maxDamage = armourDamage?.getDoubleByName("max_damage") ?: 0.0 val maxDamage = armourDamage?.getDoubleByName("max_damage") ?: 0.0
@ -121,6 +134,7 @@ class CommonParseRgdService @Autowired constructor(
val moraleDamage = armourDamage?.getDoubleByName("morale_damage") ?: 0.0 val moraleDamage = armourDamage?.getDoubleByName("morale_damage") ?: 0.0
val defaultArmourPiercing = armourDamage?.getDoubleByName("armour_piercing") ?: 0.0 val defaultArmourPiercing = armourDamage?.getDoubleByName("armour_piercing") ?: 0.0
val weaponDmgMap: Map<String, Double> = val weaponDmgMap: Map<String, Double> =
armourDamage?.getRgdTableByName("armour_piercing_types")?.mapNotNull { armour_piercing -> armourDamage?.getRgdTableByName("armour_piercing_types")?.mapNotNull { armour_piercing ->
@ -134,9 +148,33 @@ class CommonParseRgdService @Autowired constructor(
return AreaEffect(minDamage, maxDamage, damageRadius, forceMin, forceMax, minDamageValue, moraleDamage, weaponDmgMap, defaultArmourPiercing) 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()
} }

View File

@ -26,6 +26,9 @@ class ModAttribPathService @Autowired constructor(
fun getWeaponAttribsPath(modFolderData: String): String = fun getWeaponAttribsPath(modFolderData: String): String =
"$modFolderData${File.separator}attrib${File.separator}weapon" "$modFolderData${File.separator}attrib${File.separator}weapon"
fun getAbilitiesAttribsPath(modFolderData: String): String =
"$modFolderData${File.separator}attrib${File.separator}abilities"
fun getResearchAttribsPath(modFolderData: String): String = fun getResearchAttribsPath(modFolderData: String): String =
"$modFolderData${File.separator}attrib${File.separator}research" "$modFolderData${File.separator}attrib${File.separator}research"

View File

@ -1,9 +1,15 @@
package com.dowstats.service.w40k package com.dowstats.service.w40k
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.building.BuildingWeapon import com.dowstats.data.entities.building.BuildingWeapon
import com.dowstats.data.entities.building.BuildingWeaponKey import com.dowstats.data.entities.building.BuildingWeaponKey
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.sergant.SergeantWeapon
import com.dowstats.data.entities.sergant.SergeantWeaponKey
import com.dowstats.data.entities.unit.UnitWeapon
import com.dowstats.data.entities.unit.UnitWeaponKey
import com.dowstats.data.entities.weapon.Weapon
import com.dowstats.data.repositories.* import com.dowstats.data.repositories.*
import com.dowstats.data.rgd.RgdData import com.dowstats.data.rgd.RgdData
import com.dowstats.service.postparsing.PostParsingService import com.dowstats.service.postparsing.PostParsingService
@ -24,8 +30,13 @@ class ModParserService @Autowired constructor(
val researchRgdExtractService: ResearchRgdExtractService, val researchRgdExtractService: ResearchRgdExtractService,
val raceRepository: RaceRepository, val raceRepository: RaceRepository,
val armorTypeRepository: ArmorTypeRepository, val armorTypeRepository: ArmorTypeRepository,
val areaEffectRepository: AreaEffectRepository,
val areaFilterRepository: AreaFilterRepository,
val activationRepository: ActivationRepository,
val unitRepository: UnitRepository, val unitRepository: UnitRepository,
val sergeantRepository: SergeantRepository, val sergeantRepository: SergeantRepository,
val abilityRgdExtractService: AbilityRgdExtractService,
val abilityRepository: AbilityRepository,
val weaponRgdExtractService: WeaponRgdExtractService, val weaponRgdExtractService: WeaponRgdExtractService,
val weaponRepository: WeaponRepository, val weaponRepository: WeaponRepository,
val modAttribPathService: ModAttribPathService, val modAttribPathService: ModAttribPathService,
@ -76,6 +87,10 @@ class ModParserService @Autowired constructor(
armorTypeRepository.findByIsUa(true).toSet() armorTypeRepository.findByIsUa(true).toSet()
else armorTypeRepository.findByIsClassic(true).toSet() else armorTypeRepository.findByIsClassic(true).toSet()
val areaEffects = areaEffectRepository.findAll().toSet()
val areaFilters = areaFilterRepository.findAll().toSet()
val activations = activationRepository.findAll().toSet()
racesList.forEach { racesList.forEach {
unitRepository.deleteAllByModIdAndRaceId(mod.id!!, it) unitRepository.deleteAllByModIdAndRaceId(mod.id!!, it)
} }
@ -87,9 +102,10 @@ class ModParserService @Autowired constructor(
val enrichedModDictionary = defaultDictionary + modDictionary val enrichedModDictionary = defaultDictionary + modDictionary
val weapons = saveWeapons(modFolderData, mod, armorTypes, enrichedModDictionary) val weapons = saveWeapons(modFolderData, mod, armorTypes, enrichedModDictionary)
val abilities = saveAbilities(modFolderData, mod, activations, areaEffects, areaFilters, armorTypes, enrichedModDictionary)
val researches = saveResearches(modFolderData, mod, enrichedModDictionary) val researches = saveResearches(modFolderData, mod, enrichedModDictionary)
saveUnits(modFolderData, weapons, racesList, armorTypes, mod, enrichedModDictionary) saveUnits(modFolderData, weapons, abilities, racesList, armorTypes, mod, enrichedModDictionary)
saveBuildings(modFolderData, weapons, researches, racesList, armorTypes, mod, enrichedModDictionary) saveBuildings(modFolderData, weapons, abilities, researches, racesList, armorTypes, mod, enrichedModDictionary)
modRepository.removeCampaignEntities(mod.id!!) modRepository.removeCampaignEntities(mod.id!!)
postParsingService.bindResearch(mod) postParsingService.bindResearch(mod)
@ -170,6 +186,7 @@ class ModParserService @Autowired constructor(
private fun saveUnits( private fun saveUnits(
modFolderData: String, modFolderData: String,
weapons: Set<Weapon>, weapons: Set<Weapon>,
abilities: Set<Ability>,
racesList: List<String>, racesList: List<String>,
armorTypes: Set<ArmorType>, armorTypes: Set<ArmorType>,
mod: Mod, mod: Mod,
@ -235,6 +252,7 @@ class ModParserService @Autowired constructor(
squadRgdData.value, squadRgdData.value,
unitRgdData, unitRgdData,
weapons, weapons,
abilities,
raceFolder, raceFolder,
modFolderData, modFolderData,
mod, mod,
@ -298,6 +316,7 @@ class ModParserService @Autowired constructor(
private fun saveBuildings( private fun saveBuildings(
modFolderData: String, modFolderData: String,
weapons: Set<Weapon>, weapons: Set<Weapon>,
abilities: Set<Ability>,
researches: Set<Research>, researches: Set<Research>,
racesList: List<String>, racesList: List<String>,
armorTypes: Set<ArmorType>, armorTypes: Set<ArmorType>,
@ -342,6 +361,7 @@ class ModParserService @Autowired constructor(
modDictionary, modDictionary,
structure.value, structure.value,
weapons, weapons,
abilities,
researches, researches,
raceUnits, raceUnits,
race, race,
@ -417,6 +437,39 @@ class ModParserService @Autowired constructor(
} }
} }
private fun saveAbilities(modFolderData: String,
mod: Mod,
activations: Set<Activation>,
areaEffects: Set<AreaEffect>,
areaFilters: Set<AreaFilter>,
armorTypes: Set<ArmorType>, modDictionary: Map<Int, String>): Set<Ability> {
val classicAbilities =
rgdParserService.parseFolderToRgdFiles("${modAttribPathService.pathToWanilaData}/attrib/abilities")
val modAbilities =
rgdParserService.parseFolderToRgdFiles(modAttribPathService.getAbilitiesAttribsPath(modFolderData))
val allAbilities = classicAbilities + modAbilities
val abilitiesToSave = allAbilities.mapNotNull {
abilityRgdExtractService.extractToAbilityEntity(it.key, it.value, mod,
activations,
areaEffects,
areaFilters,
armorTypes,
modFolderData,
modDictionary
)
}
return try {
abilityRepository.saveAll(abilitiesToSave).toSet()
} catch (e: Exception) {
throw e
}
}
} }

View File

@ -2,11 +2,13 @@ package com.dowstats.service.w40k
import com.dowstats.Metadata import com.dowstats.Metadata
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.fillDataFromRgdTable
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.research.Research import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.research.ResearchModifiers import com.dowstats.data.entities.research.ResearchModifiers
import com.dowstats.data.entities.research.ResearchRequirements import com.dowstats.data.entities.research.ResearchRequirements
import com.dowstats.data.rgd.RgdData 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.getDoubleByName
import com.dowstats.data.rgd.RgdDataUtil.getIntByName import com.dowstats.data.rgd.RgdDataUtil.getIntByName
import com.dowstats.data.rgd.RgdDataUtil.getRgdTableByName import com.dowstats.data.rgd.RgdDataUtil.getRgdTableByName
@ -38,6 +40,7 @@ class ResearchRgdExtractService @Autowired constructor(
research.name = researchUiInfo.name research.name = researchUiInfo.name
research.description = researchUiInfo.description research.description = researchUiInfo.description
research.uiIndexHint = researchData.getIntByName("ui_index_hint") ?: 0 research.uiIndexHint = researchData.getIntByName("ui_index_hint") ?: 0
research.uiHotkeyName = researchData.getStringByName("ui_hotkey_name")
research.icon = researchUiInfo.iconPath research.icon = researchUiInfo.iconPath
val cost = commonParseRgdService.getBuildCost(researchData.getRgdTableByName("time_cost")) val cost = commonParseRgdService.getBuildCost(researchData.getRgdTableByName("time_cost"))
@ -63,11 +66,7 @@ class ResearchRgdExtractService @Autowired constructor(
if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua") null else { if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua") null else {
ResearchModifiers().also { ResearchModifiers().also {
it.research = research it.research = research
it.reference = mTable.getStringByName("\$REF") }.fillDataFromRgdTable(mTable)
it.usageType = mTable.getRgdTableByName("usage_type")?.getStringByName("\$REF")
it.target = mTable.getStringByName("target_type_name")
it.value = mTable.getDoubleByName("value")
}
} }
} else null } else null
}?.filterUseless() ?: emptyList() }?.filterUseless() ?: emptyList()

View File

@ -3,6 +3,13 @@ package com.dowstats.service.w40k
import com.dowstats.Metadata import com.dowstats.Metadata
import com.dowstats.data.dto.BuildCost import com.dowstats.data.dto.BuildCost
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.fillDataFromRgdTable
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.sergant.SergeantModifiers
import com.dowstats.data.entities.sergant.SergeantRequirements
import com.dowstats.data.entities.weapon.Weapon
import com.dowstats.data.rgd.RgdData import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
import com.dowstats.data.rgd.RgdDataUtil.getIntByName import com.dowstats.data.rgd.RgdDataUtil.getIntByName
@ -44,6 +51,7 @@ class SergeantRgdExtractService @Autowired constructor(
mod: Mod, mod: Mod,
sergeantData: List<RgdData>, sergeantData: List<RgdData>,
weapons: Set<Weapon>, weapons: Set<Weapon>,
abilities: Set<Ability>,
modFolderData: String, modFolderData: String,
buildCost: BuildCost, buildCost: BuildCost,
armorTypes: Set<ArmorType>, armorTypes: Set<ArmorType>,
@ -62,13 +70,14 @@ class SergeantRgdExtractService @Autowired constructor(
sergeant.armorType2 = getUnitArmorType(sergeantData, armorTypes, "type_armour_2") sergeant.armorType2 = getUnitArmorType(sergeantData, armorTypes, "type_armour_2")
sergeant.filename = fileName sergeant.filename = fileName
val sergeantUiRgd = sergeantData.getRgdTableByName("ui_ext") val uiExt = sergeantData.getRgdTableByName("ui_ext") ?: throw Exception("Could not find ui_ext at $fileName")
?.getRgdTableByName("ui_info") ?: throw Exception("$fileName") val sergeantUiRgd = uiExt.getRgdTableByName("ui_info") ?: throw Exception("Could not find ui_info at $fileName")
val sergeantUiInfo = commonParseRgdService.getUiInfo(sergeantUiRgd, modDictionary, modFolderData, mod, log) val sergeantUiInfo = commonParseRgdService.getUiInfo(sergeantUiRgd, modDictionary, modFolderData, mod, log)
sergeant.name = sergeantUiInfo.name sergeant.name = sergeantUiInfo.name
sergeant.description = sergeantUiInfo.description sergeant.description = sergeantUiInfo.description
sergeant.icon = sergeantUiInfo.iconPath sergeant.icon = sergeantUiInfo.iconPath
sergeant.uiHotkeyName = uiExt.getStringByName("ui_hotkey_name")
val healthData = getHealthAndMoraleDeathPenaltyData(sergeantData) val healthData = getHealthAndMoraleDeathPenaltyData(sergeantData)
sergeant.health = healthData.hitpoints?.toInt() sergeant.health = healthData.hitpoints?.toInt()
@ -76,6 +85,10 @@ class SergeantRgdExtractService @Autowired constructor(
sergeant.healthRegeneration = healthData.regeneration sergeant.healthRegeneration = healthData.regeneration
sergeant.moraleDeathPenalty = healthData.moraleDeathPenalty?.toInt() sergeant.moraleDeathPenalty = healthData.moraleDeathPenalty?.toInt()
val moraleInc = sergeantData.getRgdTableByName("morale_add_ext")
sergeant.moraleIncomeMax = moraleInc?.getDoubleByName("inc_morale_max")
sergeant.moraleIncomeRate = moraleInc?.getDoubleByName("inc_morale_rate")
val incomeData = commonParseRgdService.getResourceIncome(sergeantData.getRgdTableByName("resource_ext")) val incomeData = commonParseRgdService.getResourceIncome(sergeantData.getRgdTableByName("resource_ext"))
sergeant.faithIncome = incomeData.faith sergeant.faithIncome = incomeData.faith
sergeant.powerIncome = incomeData.power sergeant.powerIncome = incomeData.power
@ -90,8 +103,11 @@ class SergeantRgdExtractService @Autowired constructor(
sergeant.modId = mod.id!! sergeant.modId = mod.id!!
sergeant.sergeantModifiers = getSergeantModifiers(sergeant, sergeantData).toMutableSet()
sergeant.sergeantRequirements = getSergeantRequirements(sergeant, sergeantData).toMutableSet() sergeant.sergeantRequirements = getSergeantRequirements(sergeant, sergeantData).toMutableSet()
sergeant.abilities = commonParseRgdService.getAbilities(sergeantData, abilities).toMutableSet()
val sergeantWeapons = getSergeantWeapons(sergeantData)?.mapNotNull { weaponData -> val sergeantWeapons = getSergeantWeapons(sergeantData)?.mapNotNull { weaponData ->
weapons.find { weapons.find {
it.filename == weaponData.weaponFilename + ".rgd" it.filename == weaponData.weaponFilename + ".rgd"
@ -166,6 +182,18 @@ class SergeantRgdExtractService @Autowired constructor(
} else null } else null
}?.flatten() }?.flatten()
private fun getSergeantModifiers(sergeant: Sergeant, sergeantData: List<RgdData>): List<SergeantModifiers> =
sergeantData.getRgdTableByName("modifier_apply_ext")?.getRgdTableByName("modifiers")?.mapNotNull { m ->
if (m.name.contains("modifier_")) {
val mTable = m.value as List<RgdData>
if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua") null else {
SergeantModifiers().also {
it.sergeant = sergeant
}.fillDataFromRgdTable(mTable)
}
} else null
}?.filterUseless() ?: emptyList()
private fun getSergeantRequirements(sergeant: Sergeant, sergeantData: List<RgdData>): List<SergeantRequirements> { private fun getSergeantRequirements(sergeant: Sergeant, sergeantData: List<RgdData>): List<SergeantRequirements> {
val requirements = sergeantData.getRgdTableByName("requirement_ext")?.getRgdTableByName("requirements") val requirements = sergeantData.getRgdTableByName("requirement_ext")?.getRgdTableByName("requirements")
return requirements?.mapNotNull { r -> return requirements?.mapNotNull { r ->

View File

@ -5,6 +5,15 @@ import com.dowstats.data.dto.BuildCost
import com.dowstats.data.dto.UnitDataToSave import com.dowstats.data.dto.UnitDataToSave
import com.dowstats.data.dto.WeaponsData import com.dowstats.data.dto.WeaponsData
import com.dowstats.data.entities.* import com.dowstats.data.entities.*
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.fillDataFromRgdTable
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.unit.UnitModifiers
import com.dowstats.data.entities.unit.UnitRequirements
import com.dowstats.data.entities.weapon.Weapon
import com.dowstats.data.entities.weapon.WeaponModifiers
import com.dowstats.data.rgd.RgdData import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
@ -60,6 +69,7 @@ class UnitRgdExtractService @Autowired constructor(
squadData: List<RgdData>, squadData: List<RgdData>,
unitData: List<RgdData>, unitData: List<RgdData>,
weapons: Set<Weapon>, weapons: Set<Weapon>,
abilities: Set<Ability>,
race: String, race: String,
modFolderData: String, modFolderData: String,
mod: Mod, mod: Mod,
@ -84,6 +94,7 @@ class UnitRgdExtractService @Autowired constructor(
unit.filenameSquad = fileNameSquad unit.filenameSquad = fileNameSquad
unit.filenameUnit = fileNameUnit unit.filenameUnit = fileNameUnit
unit.uiIndexHint = unitData.getRgdTableByName("ui_ext")?.getIntByName("ui_index_hint") ?: 0 unit.uiIndexHint = unitData.getRgdTableByName("ui_ext")?.getIntByName("ui_index_hint") ?: 0
unit.uiHotkeyName = unitData.getRgdTableByName("ui_ext")?.getStringByName("ui_hotkey_name")
unit.haveReinforceMenu = squadData.getRgdTableByName("squad_reinforce_ext") != null unit.haveReinforceMenu = squadData.getRgdTableByName("squad_reinforce_ext") != null
val buildCost = getBuildCost(unitData, squadData) val buildCost = getBuildCost(unitData, squadData)
@ -141,7 +152,9 @@ class UnitRgdExtractService @Autowired constructor(
unit.reinforceCostSouls = reinforceCostData.souls unit.reinforceCostSouls = reinforceCostData.souls
unit.reinforceTime = reinforceCostData.time unit.reinforceTime = reinforceCostData.time
unit.unitModifiers = geUnitModifiers(unit, unitData, squadData).toMutableSet()
unit.unitRequirements = getUnitRequirements(unit, squadData).toMutableSet() unit.unitRequirements = getUnitRequirements(unit, squadData).toMutableSet()
unit.abilities = commonParseRgdService.getAbilities(unitData, abilities).toMutableSet()
val sergeantsData = getSergeantsData(squadData) val sergeantsData = getSergeantsData(squadData)
@ -156,6 +169,7 @@ class UnitRgdExtractService @Autowired constructor(
mod, mod,
sergeantRgdData, sergeantRgdData,
weapons, weapons,
abilities,
modFolderData, modFolderData,
sergeantData.cost, sergeantData.cost,
armorTypes armorTypes
@ -304,7 +318,7 @@ class UnitRgdExtractService @Autowired constructor(
.getRgdTableByName("squad_reinforce_ext") .getRgdTableByName("squad_reinforce_ext")
?.getRgdTableByName("cost") ?.getRgdTableByName("cost")
private fun getUnitWeapons(reinforceData: List<RgdData>?, weapons: Set<Weapon>): List<WeaponsData>? = reinforceData private fun getUnitWeapons(unitData: List<RgdData>?, weapons: Set<Weapon>): List<WeaponsData>? = unitData
?.getRgdTableByName("combat_ext") ?.getRgdTableByName("combat_ext")
?.getRgdTableByName("hardpoints") ?.getRgdTableByName("hardpoints")
?.mapNotNull { hardpoint -> ?.mapNotNull { hardpoint ->
@ -318,7 +332,7 @@ class UnitRgdExtractService @Autowired constructor(
it.mapNotNull { weapon -> it.mapNotNull { weapon ->
(weapon.value as? List<RgdData>)?.getStringByName("weapon")?.let { (weapon.value as? List<RgdData>)?.getStringByName("weapon")?.let {
if (it != "") { if (it != "") {
val weaponFileName = it.replace("weapon\\", "").replace(".lua", "") val weaponFileName = it.replace("weapon\\", "").replace(".rgd", "").replace(".lua", "")
val weaponEntity = weapons.find { val weaponEntity = weapons.find {
it.filename?.replace(".rgd", "") == weaponFileName it.filename?.replace(".rgd", "") == weaponFileName
} }
@ -339,6 +353,8 @@ class UnitRgdExtractService @Autowired constructor(
} else null } else null
}?.flatten() }?.flatten()
private fun getSergeantsData(squadData: List<RgdData>?): Pair<List<SergeantData>?, Int?> { private fun getSergeantsData(squadData: List<RgdData>?): Pair<List<SergeantData>?, Int?> {
val squadTable = squadData val squadTable = squadData
@ -365,6 +381,40 @@ class UnitRgdExtractService @Autowired constructor(
return Pair(sergeantsData, maxSergeants) return Pair(sergeantsData, maxSergeants)
} }
private fun geUnitModifiers(unit: DowUnit, unitData: List<RgdData>, squadData: List<RgdData>): List<UnitModifiers> {
fun getUnitModifiersFromTable(table: List<RgdData>?) : List<UnitModifiers> = table?.mapNotNull { m ->
if (m.name.contains("modifier_")) {
val mTable = m.value as List<RgdData>
if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua") null else {
UnitModifiers().also {
it.unit = unit
}.fillDataFromRgdTable(mTable)
}
} else null
}?.filterUseless() ?: emptyList()
fun getSquadModifiersFromTable(table: List<RgdData>?) : List<UnitModifiers> = table?.mapNotNull { m ->
if (m.name.contains("modifier_")) {
val mTable = m.value as List<RgdData>
val modifier = mTable.getRgdTableByName("modifier")
val maxLifetime = mTable.getDoubleByName("max_lifetime")
if (modifier?.getStringByName("\$REF") == "modifiers\\no_modifier.lua" || modifier == null) null else {
UnitModifiers().also {
it.unit = unit
it.maxLifeTime = maxLifetime
}.fillDataFromRgdTable(modifier)
}
} else null
}?.filterUseless() ?: emptyList()
val unitModifiersTable = unitData.getRgdTableByName("modifier_apply_ext")?.getRgdTableByName("modifiers")
val squadModifiersTable = squadData.getRgdTableByName("squad_modifier_apply_ext")?.getRgdTableByName("modifiers")
return getUnitModifiersFromTable(unitModifiersTable) + getSquadModifiersFromTable(squadModifiersTable)
}
private fun getUnitRequirements(unit: DowUnit, squadData: List<RgdData>): List<UnitRequirements> { private fun getUnitRequirements(unit: DowUnit, squadData: List<RgdData>): List<UnitRequirements> {
val requirements = squadData.getRgdTableByName("squad_requirement_ext")?.getRgdTableByName("requirements") val requirements = squadData.getRgdTableByName("squad_requirement_ext")?.getRgdTableByName("requirements")
return requirements?.mapNotNull { r -> return requirements?.mapNotNull { r ->

View File

@ -1,7 +1,14 @@
package com.dowstats.service.w40k package com.dowstats.service.w40k
import com.dowstats.Metadata import com.dowstats.Metadata
import com.dowstats.data.entities.* import com.dowstats.data.entities.ArmorType
import com.dowstats.data.entities.Mod
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.fillDataFromRgdTable
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.weapon.Weapon
import com.dowstats.data.entities.weapon.WeaponArmorPiercing
import com.dowstats.data.entities.weapon.WeaponModifiers
import com.dowstats.data.entities.weapon.WeaponRequirements
import com.dowstats.data.rgd.RgdData import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
@ -32,6 +39,7 @@ class WeaponRgdExtractService @Autowired constructor(
weapon.icon = weaponUiData?.iconPath weapon.icon = weaponUiData?.iconPath
weapon.description = weaponUiData?.description weapon.description = weaponUiData?.description
weapon.showInReinforce = weaponUiInfo?.getBooleanByName("show_in_reinforce") ?: false weapon.showInReinforce = weaponUiInfo?.getBooleanByName("show_in_reinforce") ?: false
weapon.uiHotkeyName = weaponData.getStringByName("ui_hotkey_name")
val cost = commonParseRgdService.getBuildCost(weaponData.getRgdTableByName("cost")) val cost = commonParseRgdService.getBuildCost(weaponData.getRgdTableByName("cost"))
weapon.costRequisition = cost.requisition ?: 0.0 weapon.costRequisition = cost.requisition ?: 0.0
@ -49,26 +57,34 @@ class WeaponRgdExtractService @Autowired constructor(
weapon.canAttackGround = weaponData.getBooleanByName("can_attack_ground_units") ?: true weapon.canAttackGround = weaponData.getBooleanByName("can_attack_ground_units") ?: true
val areaEffectData = commonParseRgdService.getAreaEffectData(weaponData) val areaEffectTable = weaponData.getRgdTableByName("area_effect")
val armoursPiercing = armorTypes.map { if (areaEffectTable != null) {
val weaponArmourPiercing = WeaponArmorPiercing() val areaEffectData = commonParseRgdService.getAreaEffectData(areaEffectTable)
weaponArmourPiercing.weapon = weapon
weaponArmourPiercing.armorType = it val armoursPiercing = armorTypes.map {
val piercingValue = (areaEffectData.weaponDmgMap[it.id] ?: areaEffectData.defaultArmorPiercing).toBigDecimal() val weaponArmourPiercing = WeaponArmorPiercing()
weaponArmourPiercing.piercingValue = piercingValue.let {pv -> if(pv <= BigDecimal(100)) pv else BigDecimal(100) } weaponArmourPiercing.weapon = weapon
weaponArmourPiercing weaponArmourPiercing.armorType = it
val piercingValue =
(areaEffectData.weaponDmgMap[it.id] ?: areaEffectData.defaultArmorPiercing).toBigDecimal()
weaponArmourPiercing.piercingValue =
piercingValue.let { pv -> if (pv <= BigDecimal(100)) pv else BigDecimal(100) }
weaponArmourPiercing
}
weapon.minDamageValue = areaEffectData.minDamageValue
weapon.minDamage = areaEffectData.minDamage
weapon.maxDamage = areaEffectData.maxDamage
weapon.throwForceMin = areaEffectData.throwForceMin
weapon.throwForceMax = areaEffectData.throwForceMax
weapon.moraleDamage = areaEffectData.moraleDamage
weapon.weaponPiercings = armoursPiercing
weapon.damageRadius = areaEffectData.damageRadius
} }
weapon.minDamageValue = areaEffectData.minDamageValue
weapon.minDamage = areaEffectData.minDamage
weapon.maxDamage = areaEffectData.maxDamage
weapon.throwForceMin = areaEffectData.throwForceMin
weapon.throwForceMax = areaEffectData.throwForceMax
weapon.moraleDamage = areaEffectData.moraleDamage
weapon.weaponPiercings = armoursPiercing
weapon.damageRadius = areaEffectData.damageRadius
weapon.modId = mod.id weapon.modId = mod.id
weapon.weaponModifiers = getWeaponModifiers(weapon, weaponData).toMutableSet()
weapon.weaponRequirements = getWeaponRequirements(weapon, weaponData).toMutableSet() weapon.weaponRequirements = getWeaponRequirements(weapon, weaponData).toMutableSet()
return if(weapon.minDamage == 0.0 && weapon.maxDamage == 0.0 && weapon.moraleDamage == 0.0){ return if(weapon.minDamage == 0.0 && weapon.maxDamage == 0.0 && weapon.moraleDamage == 0.0){
@ -76,6 +92,24 @@ class WeaponRgdExtractService @Autowired constructor(
} else weapon } else weapon
} }
private fun getWeaponModifiers(weapon: Weapon, weaponData: List<RgdData>?): List<WeaponModifiers> =
weaponData?.getRgdTableByName("area_effect")
?.getRgdTableByName("weapon_damage")
?.getRgdTableByName("modifiers")
?.mapNotNull { m ->
if (m.name.contains("modifier_")) {
val mTable = m.value as List<RgdData>
val modifier = mTable.getRgdTableByName("modifier")
val maxLifetime = mTable.getDoubleByName("max_lifetime")
if (modifier?.getStringByName("\$REF") == "modifiers\\no_modifier.lua" || modifier == null) null else {
WeaponModifiers().also {
it.weapon = weapon
it.maxLifeTime = maxLifetime
}.fillDataFromRgdTable(modifier)
}
} else null
}?.filterUseless() ?: emptyList()
private fun getWeaponRequirements(weapon: Weapon, weaponData: List<RgdData>): List<WeaponRequirements> { private fun getWeaponRequirements(weapon: Weapon, weaponData: List<RgdData>): List<WeaponRequirements> {
return try{ return try{
val requirements = weaponData.getRgdTableByName("requirements") val requirements = weaponData.getRgdTableByName("requirements")

View File

@ -44,7 +44,7 @@
"baseTableName": "building_affected_weapons", "baseTableName": "building_affected_weapons",
"constraintName": "fk_buildings_buildings_affected_weapons", "constraintName": "fk_buildings_buildings_affected_weapons",
"referencedColumnNames": "id", "referencedColumnNames": "id",
"referencedTableName": "researches", "referencedTableName": "buildings",
"onDelete": "CASCADE" "onDelete": "CASCADE"
} }
}, },

View File

@ -0,0 +1,98 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Fill activation table",
"author": "anibus",
"changes": [
{
"insert": {
"tableName": "activation",
"columns": [
{
"column": {
"name": "id",
"value": "ability_activation_always_on"
}
},{
"column": {
"name": "name",
"value": "Passive ability"
}
}
]
}
},{
"insert": {
"tableName": "activation",
"columns": [
{
"column": {
"name": "id",
"value": "ability_activation_meleehit"
}
},{
"column": {
"name": "name",
"value": "Active when receiving melee hit"
}
}
]
}
},{
"insert": {
"tableName": "activation",
"columns": [
{
"column": {
"name": "id",
"value": "ability_activation_targeted"
}
},{
"column": {
"name": "name",
"value": "Target ability"
}
}
]
}
},{
"insert": {
"tableName": "activation",
"columns": [
{
"column": {
"name": "id",
"value": "ability_activation_timed"
}
},{
"column": {
"name": "name",
"value": "Timed ability"
}
}
]
}
},{
"insert": {
"tableName": "activation",
"columns": [
{
"column": {
"name": "id",
"value": "ability_activation_toggled"
}
},{
"column": {
"name": "name",
"value": "On/off ability"
}
}
]
}
}
]
}
}
]
}

View File

@ -0,0 +1,81 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Fill area_effect table",
"author": "anibus",
"changes": [
{
"insert": {
"tableName": "area_effect",
"columns": [
{
"column": {
"name": "id",
"value": "area_effect_circle"
}
},{
"column": {
"name": "name",
"value": "Circle"
}
}
]
}
},{
"insert": {
"tableName": "activation",
"columns": [
{
"column": {
"name": "id",
"value": "area_effect_pie"
}
},{
"column": {
"name": "name",
"value": "Pie"
}
}
]
}
},{
"insert": {
"tableName": "activation",
"columns": [
{
"column": {
"name": "id",
"value": "area_effect_point"
}
},{
"column": {
"name": "name",
"value": "Point"
}
}
]
}
},{
"insert": {
"tableName": "activation",
"columns": [
{
"column": {
"name": "id",
"value": "area_effect_squad"
}
},{
"column": {
"name": "name",
"value": "Squad"
}
}
]
}
}
]
}
}
]
}

View File

@ -0,0 +1,81 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Fill area_filter table",
"author": "anibus",
"changes": [
{
"insert": {
"tableName": "area_filter",
"columns": [
{
"column": {
"name": "id",
"value": "area_filter_all"
}
},{
"column": {
"name": "name",
"value": "All"
}
}
]
}
},{
"insert": {
"tableName": "area_filter",
"columns": [
{
"column": {
"name": "id",
"value": "area_filter_allied"
}
},{
"column": {
"name": "name",
"value": "Allied"
}
}
]
}
},{
"insert": {
"tableName": "area_filter",
"columns": [
{
"column": {
"name": "id",
"value": "area_filter_enemy"
}
},{
"column": {
"name": "name",
"value": "Enemy"
}
}
]
}
},{
"insert": {
"tableName": "area_filter",
"columns": [
{
"column": {
"name": "id",
"value": "area_filter_own"
}
},{
"column": {
"name": "name",
"value": "Own"
}
}
]
}
}
]
}
}
]
}

View File

@ -0,0 +1,215 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Start new year 2026 work with abilities",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "ui_hotkey_name",
"type": "varchar(255)"
}
},
{
"column": {
"name": "child_ability_name",
"type": "varchar(255)"
}
},
{
"column": {
"name": "initial_delay_time",
"type": "varchar(255)"
}
},{
"column": {
"name": "radius",
"type": "number"
}
},{
"column": {
"name": "min_damage",
"type": "number"
}
},{
"column": {
"name": "min_damage_value",
"type": "number"
}
},{
"column": {
"name": "max_damage",
"type": "number"
}
},{
"column": {
"name": "morale_damage",
"type": "number"
}
},{
"column": {
"name": "throw_force_min",
"type": "number"
}
},{
"column": {
"name": "throw_force_max",
"type": "number"
}
},{
"column": {
"name": "activation_id",
"type": "varchar(255)"
}
},{
"column": {
"name": "area_effect_id",
"type": "varchar(255)"
}
},{
"addForeignKeyConstraint":
{
"constraintName": "fk_ability_activation",
"baseColumnNames": "activation_id",
"baseTableName": "abilities",
"referencedColumnNames": "id",
"referencedTableName": "activation"
}
},{
"addForeignKeyConstraint":
{
"constraintName": "fk_ability_area_effect",
"baseColumnNames": "area_effect_id",
"baseTableName": "abilities",
"referencedColumnNames": "id",
"referencedTableName": "area_effect"
}
}
],
"tableName": "abilities"
}
}
]
}
},
{
"changeSet": {
"id": "Add area_filter column",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "area_filter_id",
"type": "varchar(255)"
}
},{
"addForeignKeyConstraint":
{
"constraintName": "fk_ability_area_filter",
"baseColumnNames": "area_filter_id",
"baseTableName": "abilities",
"referencedColumnNames": "id",
"referencedTableName": "area_filter"
}
}
],
"tableName": "abilities"
}
}
]
}
},
{
"changeSet": {
"id": "Add ui_index_hint column",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "ui_index_hint",
"type": "int",
"value": 0,
"constraints": {
"nullable": false
}
}
}
],
"tableName": "abilities"
}
}
]
}
},
{
"changeSet": {
"id": "Add range, recharge_time, recharge_timer_global, refresh_time, duration_time, spawned_entity_name columns",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "range",
"type": "number"
}
},{
"column": {
"name": "recharge_time",
"type": "number"
}
},{
"column": {
"name": "recharge_timer_global",
"type": "boolean"
}
},{
"column": {
"name": "refresh_time",
"type": "number"
}
},{
"column": {
"name": "duration_time",
"type": "number"
}
},{
"column": {
"name": "spawned_entity_name",
"type": "varchar(1024)"
}
}
],
"tableName": "abilities"
}
}
]
}
},{
"changeSet": {
"id": "Change abilities name data type to Text column",
"author": "anibus",
"changes": [
{
"modifyDataType": {
"columnName": "name",
"newDataType": "text",
"tableName": "abilities"
}
}
]
}
}
]
}

View File

@ -0,0 +1,60 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ability_affected_buildings table",
"author": "ai_assistant",
"changes": [
{
"createTable": {
"tableName": "ability_affected_buildings",
"columns": [
{
"column": {
"name": "ability_id",
"type": "int",
"constraints": { "nullable": false }
}
},
{
"column": {
"name": "building_id",
"type": "int",
"constraints": { "nullable": false }
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "ability_id, building_id",
"constraintName": "uc_ability_affected_buildings",
"tableName": "ability_affected_buildings"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "ability_id",
"baseTableName": "ability_affected_buildings",
"constraintName": "fk_ability_aff_build_ability",
"referencedColumnNames": "id",
"referencedTableName": "abilities",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "building_id",
"baseTableName": "ability_affected_buildings",
"constraintName": "fk_ability_aff_build_building",
"referencedColumnNames": "id",
"referencedTableName": "buildings",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,60 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ability_affected_sergeants table",
"author": "ai_assistant",
"changes": [
{
"createTable": {
"tableName": "ability_affected_sergeants",
"columns": [
{
"column": {
"name": "ability_id",
"type": "int",
"constraints": { "nullable": false }
}
},
{
"column": {
"name": "sergeant_id",
"type": "int",
"constraints": { "nullable": false }
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "ability_id, sergeant_id",
"constraintName": "uc_ability_affected_sergeants",
"tableName": "ability_affected_sergeants"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "ability_id",
"baseTableName": "ability_affected_sergeants",
"constraintName": "fk_ability_aff_serg_ability",
"referencedColumnNames": "id",
"referencedTableName": "abilities",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "sergeant_id",
"baseTableName": "ability_affected_sergeants",
"constraintName": "fk_ability_aff_serg_sergeant",
"referencedColumnNames": "id",
"referencedTableName": "sergeants",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,60 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ability_affected_units table",
"author": "ai_assistant",
"changes": [
{
"createTable": {
"tableName": "ability_affected_units",
"columns": [
{
"column": {
"name": "ability_id",
"type": "int",
"constraints": { "nullable": false }
}
},
{
"column": {
"name": "unit_id",
"type": "int",
"constraints": { "nullable": false }
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "ability_id, unit_id",
"constraintName": "uc_ability_affected_units",
"tableName": "ability_affected_units"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "ability_id",
"baseTableName": "ability_affected_units",
"constraintName": "fk_ability_aff_units_ability",
"referencedColumnNames": "id",
"referencedTableName": "abilities",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "unit_id",
"baseTableName": "ability_affected_units",
"constraintName": "fk_ability_aff_units_unit",
"referencedColumnNames": "id",
"referencedTableName": "units",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,60 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ability_affected_weapons table",
"author": "ai_assistant",
"changes": [
{
"createTable": {
"tableName": "ability_affected_weapons",
"columns": [
{
"column": {
"name": "ability_id",
"type": "int",
"constraints": { "nullable": false }
}
},
{
"column": {
"name": "weapon_id",
"type": "int",
"constraints": { "nullable": false }
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "ability_id, weapon_id",
"constraintName": "uc_ability_affected_weapons",
"tableName": "ability_affected_weapons"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "ability_id",
"baseTableName": "ability_affected_weapons",
"constraintName": "fk_ability_aff_weap_ability",
"referencedColumnNames": "id",
"referencedTableName": "abilities",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "weapon_id",
"baseTableName": "ability_affected_weapons",
"constraintName": "fk_ability_aff_weap_weapon",
"referencedColumnNames": "id",
"referencedTableName": "weapons",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,76 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ability_armors_piercing table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "ability_armors_piercing",
"columns": [{
"column": {
"name": "id",
"type": "int",
"autoIncrement": true,
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},
{
"column": {
"name": "ability_id",
"type": "int",
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},
{
"column": {
"name": "armor_type_id",
"type": "varchar(50)",
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},{
"column": {
"name": "piercing_value",
"type": "number",
"constraints": {
"nullable": false
}
}
},{
"addForeignKeyConstraint":
{
"constraintName": "fk_ability_ability_armors_piercing",
"baseColumnNames": "ability_id",
"baseTableName": "ability_armors_piercing",
"referencedColumnNames": "id",
"referencedTableName": "abilities",
"onDelete": "CASCADE"
}
},{
"addForeignKeyConstraint":
{
"constraintName": "fk_armor_types_armors_damage_weapons",
"baseColumnNames": "armor_type_id",
"baseTableName": "ability_armors_piercing",
"referencedColumnNames": "id",
"referencedTableName": "armor_types"
}
}
]
}
}
]
}
}
]
}

View File

@ -0,0 +1,105 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ability_modifiers table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "ability_modifiers",
"columns": [
{
"column": {
"name": "id",
"type": "int",
"autoIncrement": true,
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},{
"column": {
"name": "reference",
"type": "varchar(255)"
}
},{
"column": {
"name": "usage_type",
"type": "varchar(255)"
}
},{
"column": {
"name": "value",
"type": "number"
}
},{
"column": {
"name": "target",
"type": "varchar(255)"
}
},{
"column": {
"name": "probability_of_applying",
"type": "number"
}
},{
"column": {
"name": "exclusive",
"type": "boolean"
}
},{
"column": {
"name": "application_type",
"type": "varchar(255)"
}
},{
"column": {
"name": "ability_id",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "ability_id",
"baseTableName": "ability_modifiers",
"constraintName": "fk_ability_ability_modifiers",
"referencedColumnNames": "id",
"referencedTableName": "abilities",
"onDelete": "CASCADE"
}
}
]
}
},
{
"changeSet": {
"id": "Add max_life_time to ability_modifiers",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "max_life_time",
"type": "number"
}
}
],
"tableName": "ability_modifiers"
}
}
]
}
}
]
}

View File

@ -0,0 +1,59 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ability_requirements table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "ability_requirements",
"columns": [
{
"column": {
"name": "id",
"type": "int",
"autoIncrement": true,
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},{
"column": {
"name": "reference",
"type": "varchar(255)"
}
},{
"column": {
"name": "value",
"type": "varchar(255)"
}
},{
"column": {
"name": "ability_id",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "ability_id",
"baseTableName": "ability_requirements",
"constraintName": "fk_ability_ability_requirements",
"referencedColumnNames": "id",
"referencedTableName": "abilities",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,58 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ability_target_filter table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "ability_target_filter",
"columns": [
{
"column": {
"name": "ability_id",
"type": "int",
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},
{
"column": {
"name": "armor_type_id",
"type": "varchar(50)",
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},{
"addForeignKeyConstraint":
{
"constraintName": "fk_ability_ability_target_filter",
"baseColumnNames": "ability_id",
"baseTableName": "ability_target_filter",
"referencedColumnNames": "id",
"referencedTableName": "abilities",
"onDelete": "CASCADE"
}
},{
"addForeignKeyConstraint":
{
"constraintName": "fk_armor_type_ability_target_filter",
"baseColumnNames": "armor_type_id",
"baseTableName": "ability_target_filter",
"referencedColumnNames": "id",
"referencedTableName": "armor_types"
}
}
]
}
}
]
}
}
]
}

View File

@ -0,0 +1,34 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add activation table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "activation",
"columns": [
{
"column": {
"name": "id",
"type": "varchar(255)",
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},{
"column": {
"name": "name",
"type": "varchar(255)"
}
}
]
}
}
]
}
}
]
}

View File

@ -0,0 +1,35 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add probability_of_applying, exclusive and application_type to addon modifiers",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "probability_of_applying",
"type": "number"
}
},{
"column": {
"name": "exclusive",
"type": "boolean"
}
},{
"column": {
"name": "application_type",
"type": "varchar(255)"
}
}
],
"tableName": "addon_modifiers"
}
}
]
}
}
]
}

View File

@ -0,0 +1,34 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add area_effect table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "area_effect",
"columns": [
{
"column": {
"name": "id",
"type": "varchar(255)",
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},{
"column": {
"name": "name",
"type": "varchar(255)"
}
}
]
}
}
]
}
}
]
}

View File

@ -0,0 +1,34 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add area_filter table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "area_filter",
"columns": [
{
"column": {
"name": "id",
"type": "varchar(255)",
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},{
"column": {
"name": "name",
"type": "varchar(255)"
}
}
]
}
}
]
}
}
]
}

View File

@ -0,0 +1,66 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add building_abilities table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "building_abilities",
"columns": [
{
"column": {
"name": "building_id",
"type": "int",
"constraints": {
"nullable": false
}
}
},
{
"column": {
"name": "ability_id",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "building_id, ability_id",
"constraintName": "uc_building_ability",
"tableName": "building_abilities"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "building_id",
"baseTableName": "building_abilities",
"constraintName": "fk_buildings_building_abilities",
"referencedColumnNames": "id",
"referencedTableName": "buildings",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "ability_id",
"baseTableName": "building_abilities",
"constraintName": "fk_abilities_building_abilities",
"referencedColumnNames": "id",
"referencedTableName": "abilities",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,25 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ui_hotkey_name column to building_addons",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "ui_hotkey_name",
"type": "varchar(255)"
}
}
],
"tableName": "building_addons"
}
}
]
}
}
]
}

View File

@ -0,0 +1,35 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add probability_of_applying, exclusive and application_type to building_modifiers",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "probability_of_applying",
"type": "number"
}
},{
"column": {
"name": "exclusive",
"type": "boolean"
}
},{
"column": {
"name": "application_type",
"type": "varchar(255)"
}
}
],
"tableName": "building_modifiers"
}
}
]
}
}
]
}

View File

@ -0,0 +1,25 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ui_hotkey_name column to buildings",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "ui_hotkey_name",
"type": "varchar(255)"
}
}
],
"tableName": "buildings"
}
}
]
}
}
]
}

View File

@ -0,0 +1,35 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add probability_of_applying and exclusive to research_modifiers",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "probability_of_applying",
"type": "number"
}
},{
"column": {
"name": "exclusive",
"type": "boolean"
}
},{
"column": {
"name": "application_type",
"type": "varchar(255)"
}
}
],
"tableName": "research_modifiers"
}
}
]
}
}
]
}

View File

@ -0,0 +1,25 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ui_hotkey_name column to researches",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "ui_hotkey_name",
"type": "varchar(255)"
}
}
],
"tableName": "researches"
}
}
]
}
}
]
}

View File

@ -0,0 +1,66 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add sergeant_abilities table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "sergeant_abilities",
"columns": [
{
"column": {
"name": "sergeant_id",
"type": "int",
"constraints": {
"nullable": false
}
}
},
{
"column": {
"name": "ability_id",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "sergeant_id, ability_id",
"constraintName": "uc_sergeant_ability",
"tableName": "sergeant_abilities"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "sergeant_id",
"baseTableName": "sergeant_abilities",
"constraintName": "fk_sergeants_sergeant_abilities",
"referencedColumnNames": "id",
"referencedTableName": "sergeants",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "ability_id",
"baseTableName": "sergeant_abilities",
"constraintName": "fk_abilities_sergeant_abilities",
"referencedColumnNames": "id",
"referencedTableName": "abilities",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,60 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add sergeant_affected_buildings table",
"author": "ai_assistant",
"changes": [
{
"createTable": {
"tableName": "sergeant_affected_buildings",
"columns": [
{
"column": {
"name": "sergeant_id",
"type": "int",
"constraints": { "nullable": false }
}
},
{
"column": {
"name": "building_id",
"type": "int",
"constraints": { "nullable": false }
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "sergeant_id, building_id",
"constraintName": "uc_sergeant_affected_buildings",
"tableName": "sergeant_affected_buildings"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "sergeant_id",
"baseTableName": "sergeant_affected_buildings",
"constraintName": "fk_sergeant_aff_build_sergeant",
"referencedColumnNames": "id",
"referencedTableName": "sergeants",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "building_id",
"baseTableName": "sergeant_affected_buildings",
"constraintName": "fk_sergeant_aff_build_building",
"referencedColumnNames": "id",
"referencedTableName": "buildings",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,60 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add sergeant_affected_sergeants table",
"author": "ai_assistant",
"changes": [
{
"createTable": {
"tableName": "sergeant_affected_sergeants",
"columns": [
{
"column": {
"name": "sergeant_id",
"type": "int",
"constraints": { "nullable": false }
}
},
{
"column": {
"name": "sergeant_id_affected",
"type": "int",
"constraints": { "nullable": false }
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "sergeant_id, sergeant_id_affected",
"constraintName": "uc_sergeant_affected_sergeants",
"tableName": "sergeant_affected_sergeants"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "sergeant_id",
"baseTableName": "sergeant_affected_sergeants",
"constraintName": "fk_sergeant_aff_serg_main",
"referencedColumnNames": "id",
"referencedTableName": "sergeants",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "sergeant_id_affected",
"baseTableName": "sergeant_affected_sergeants",
"constraintName": "fk_sergeant_aff_serg_target",
"referencedColumnNames": "id",
"referencedTableName": "sergeants",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,60 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add sergeant_affected_units table",
"author": "ai_assistant",
"changes": [
{
"createTable": {
"tableName": "sergeant_affected_units",
"columns": [
{
"column": {
"name": "sergeant_id",
"type": "int",
"constraints": { "nullable": false }
}
},
{
"column": {
"name": "unit_id",
"type": "int",
"constraints": { "nullable": false }
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "sergeant_id, unit_id",
"constraintName": "uc_sergeant_affected_units",
"tableName": "sergeant_affected_units"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "sergeant_id",
"baseTableName": "sergeant_affected_units",
"constraintName": "fk_sergeant_aff_units_sergeant",
"referencedColumnNames": "id",
"referencedTableName": "sergeants",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "unit_id",
"baseTableName": "sergeant_affected_units",
"constraintName": "fk_sergeant_aff_units_unit",
"referencedColumnNames": "id",
"referencedTableName": "units",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,60 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add sergeant_affected_weapons table",
"author": "ai_assistant",
"changes": [
{
"createTable": {
"tableName": "sergeant_affected_weapons",
"columns": [
{
"column": {
"name": "sergeant_id",
"type": "int",
"constraints": { "nullable": false }
}
},
{
"column": {
"name": "weapon_id",
"type": "int",
"constraints": { "nullable": false }
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "sergeant_id, weapon_id",
"constraintName": "uc_sergeant_affected_weapons",
"tableName": "sergeant_affected_weapons"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "sergeant_id",
"baseTableName": "sergeant_affected_weapons",
"constraintName": "fk_sergeant_aff_weap_sergeant",
"referencedColumnNames": "id",
"referencedTableName": "sergeants",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint": {
"baseColumnNames": "weapon_id",
"baseTableName": "sergeant_affected_weapons",
"constraintName": "fk_sergeant_aff_weap_weapon",
"referencedColumnNames": "id",
"referencedTableName": "weapons",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,84 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add sergeant_modifiers table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "sergeant_modifiers",
"columns": [
{
"column": {
"name": "id",
"type": "int",
"autoIncrement": true,
"constraints": {
"primaryKey": true,
"nullable": false
}
}
},{
"column": {
"name": "reference",
"type": "varchar(255)"
}
},{
"column": {
"name": "usage_type",
"type": "varchar(255)"
}
},{
"column": {
"name": "value",
"type": "number"
}
},{
"column": {
"name": "target",
"type": "varchar(255)"
}
},{
"column": {
"name": "probability_of_applying",
"type": "number"
}
},{
"column": {
"name": "exclusive",
"type": "boolean"
}
},{
"column": {
"name": "application_type",
"type": "varchar(255)"
}
},{
"column": {
"name": "sergeant_id",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "sergeant_id",
"baseTableName": "sergeant_modifiers",
"constraintName": "fk_sergeant_sergeant_modifiers",
"referencedColumnNames": "id",
"referencedTableName": "sergeants",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,52 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add ui_hotkey_name column to sergeants",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "ui_hotkey_name",
"type": "varchar(255)"
}
}
],
"tableName": "sergeants"
}
}
]
}
},
{
"changeSet": {
"id": "Add morale data to sergeants",
"author": "anibus",
"changes": [
{
"addColumn": {
"columns": [
{
"column": {
"name": "morale_income_max",
"type": "number"
}
},
{
"column": {
"name": "morale_income_rate",
"type": "number"
}
}
],
"tableName": "sergeants"
}
}
]
}
}
]
}

View File

@ -0,0 +1,66 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add unit_abilities table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "unit_abilities",
"columns": [
{
"column": {
"name": "unit_id",
"type": "int",
"constraints": {
"nullable": false
}
}
},
{
"column": {
"name": "ability_id",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "unit_id, ability_id",
"constraintName": "uc_unit_ability",
"tableName": "unit_abilities"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "unit_id",
"baseTableName": "unit_abilities",
"constraintName": "fk_units_unit_abilities",
"referencedColumnNames": "id",
"referencedTableName": "units",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "ability_id",
"baseTableName": "unit_abilities",
"constraintName": "fk_abilities_unit_abilities",
"referencedColumnNames": "id",
"referencedTableName": "abilities",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

View File

@ -0,0 +1,66 @@
{
"databaseChangeLog": [
{
"changeSet": {
"id": "Add unit_affected_buildings table",
"author": "anibus",
"changes": [
{
"createTable": {
"tableName": "unit_affected_buildings",
"columns": [
{
"column": {
"name": "unit_id",
"type": "int",
"constraints": {
"nullable": false
}
}
},
{
"column": {
"name": "building_id",
"type": "int",
"constraints": {
"nullable": false
}
}
}
]
}
},
{
"addUniqueConstraint": {
"columnNames": "unit_id, building_id",
"constraintName": "uc_unit_affected_buildings_unit_id_building_id",
"tableName": "unit_affected_buildings"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "unit_id",
"baseTableName": "unit_affected_buildings",
"constraintName": "fk_researches_researches_affected_buildings",
"referencedColumnNames": "id",
"referencedTableName": "units",
"onDelete": "CASCADE"
}
},
{
"addForeignKeyConstraint":
{
"baseColumnNames": "building_id",
"baseTableName": "unit_affected_buildings",
"constraintName": "fk_buildings_researches_affected_buildings",
"referencedColumnNames": "id",
"referencedTableName": "buildings",
"onDelete": "CASCADE"
}
}
]
}
}
]
}

Some files were not shown because too many files have changed in this diff Show More