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.UnitFullDto
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.repositories.UnitRepository
import com.dowstats.service.datamaps.DowUnitMappingService
import org.springframework.beans.factory.annotation.Autowired

View File

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

View File

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

View File

@ -1,8 +1,8 @@
package com.dowstats.data.dto
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Sergeant
import com.dowstats.data.entities.Weapon
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.weapon.Weapon
data class WeaponsData(
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
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Sergeant
import com.dowstats.data.entities.Weapon
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.weapon.Weapon
data class EntityCompressDto(

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
package com.dowstats.data.dto.controllers
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
import com.dowstats.data.entities.Weapon
import com.dowstats.data.entities.weapon.Weapon
data class WeaponUnitShortDto(
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 addonRequirement: RequirementDto?,
val icon: String?,
val hotkey: String?,
)
data class BuildingAddonShortDto(

View File

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

View File

@ -19,4 +19,5 @@ data class ResearchDto(
val icon: String?,
val uiIndexHint : Int,
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
import com.dowstats.data.dto.controllers.EntityCompressDtoObject.compressDto
import com.dowstats.data.dto.controllers.SergeantUnitShortDto
import com.dowstats.data.dto.controllers.ModifierDto
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.GenerationType
import jakarta.persistence.Id
@ -17,6 +21,22 @@ open class ModifiersBase {
var target: String? = null
var usageType: String? = 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 {
@ -26,6 +46,17 @@ open class ModifiersBase {
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)
@JsonIgnore
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.BuildingAddonShortDto
import com.dowstats.data.entities.building.Building
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Sergeant
import com.dowstats.data.entities.Weapon
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.sergant.Sergeant
import com.dowstats.data.entities.weapon.Weapon
import com.fasterxml.jackson.annotation.JsonIgnore
import jakarta.persistence.*
@ -69,6 +69,7 @@ class BuildingAddon {
var affectedWeapons: MutableSet<Weapon> = mutableSetOf()
var uiIndexHint: Int = 0
var uiHotkeyName: String? = null
var icon: String? = null
var modId: Long? = null
@ -91,7 +92,9 @@ class BuildingAddon {
affectedWeapons.toShortDtoSet(),
),
addonRequirement = addonRequirementDto,
icon = icon
icon = icon,
hotkey = uiHotkeyName
)
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.research.ResearchShortDto
import com.dowstats.data.entities.ArmorType
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.DowUnitObject.toUnitDto
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.unit.DowUnitObject.toUnitDto
import com.dowstats.data.entities.Race
import com.dowstats.data.entities.Sergeant
import com.dowstats.data.entities.Weapon
import com.dowstats.data.entities.Weapon.HardpointPosition
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.sergant.Sergeant
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.research.Research
import jakarta.persistence.*
@ -59,6 +60,7 @@ class Building {
var detectRadius: Int? = null
var repairMax: Int? = null
var uiIndexHint: Int = 0
var uiHotkeyName: String? = null
var advancedBuildOption: Boolean = false
var icon: String? = null
var modId: Long? = null
@ -130,6 +132,30 @@ class Building {
inverseJoinColumns = [JoinColumn(name = "building_id")])
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])
var buildingRequirements: MutableSet<BuildingRequirements> = mutableSetOf()
@ -163,6 +189,7 @@ class Building {
icon,
modId!!,
buildingAddons,
abilities.map { it.toShortDto() }.toSet(),
researches,
modifiers.map { it.toDto() },
AffectedDataDto(
@ -175,6 +202,7 @@ class Building {
weapons,
requirement,
affectedResearches.map { it.toResearchShortDto() }.toSet(),
uiHotkeyName,
)

View File

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

View File

@ -15,13 +15,4 @@ class ResearchModifiers : ModifiersBase() {
@JsonIgnore
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.SergeantDto
import com.dowstats.data.dto.controllers.SergeantUnitShortDtoObject.toShortDtoSet
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.building.Building
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 jakarta.persistence.*
@ -44,25 +52,33 @@ class Sergeant {
var health: Int? = null
var armour: Double? = null
var healthRegeneration: Double? = null
var moraleIncomeMax: Double? = null
var moraleIncomeRate: Double? = null
var moraleDeathPenalty: Int? = null
var mass: Int? = null
var upTime: Double? = null
var sightRadius: Int? = null
var detectRadius: Int? = null
var icon: String? = null
var uiHotkeyName: String? = null
var faithIncome: Double? = null
var powerIncome: Double? = null
var requisitionIncome: Double? = null
var modId: Long? = null
@Transient
var weaponHardpoints: MutableSet<HardpointPosition> = mutableSetOf()
@OneToMany(mappedBy = "sergeant", cascade = [CascadeType.ALL])
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
@JoinTable(name = "researches_affected_sergeants",
joinColumns = [JoinColumn(name = "sergeant_id")],
@ -81,6 +97,52 @@ class Sergeant {
inverseJoinColumns = [JoinColumn(name = "building_id")])
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])
var sergeantRequirements: MutableSet<SergeantRequirements> = mutableSetOf()
@ -105,13 +167,24 @@ class Sergeant {
armour,
healthRegeneration,
moraleDeathPenalty,
moraleIncomeMax,
moraleIncomeRate,
mass,
upTime,
sightRadius,
detectRadius,
icon,
weapons.toList(),
abilities.sortedWith ( compareBy<Ability> { it.activation?.id }.thenBy{ it.uiIndexHint.let { 0 - it } }).map { it.toShortDto() }.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.entities.weapon.Weapon
import com.fasterxml.jackson.annotation.JsonIgnore
import java.io.Serializable
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 jakarta.persistence.Entity
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.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.building.Building
import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.research.ResearchModifiers
import com.dowstats.data.entities.weapon.Weapon
import jakarta.persistence.*
@ -72,6 +81,7 @@ class DowUnit {
var requisitionIncome: Double? = null
var haveReinforceMenu: Boolean = false
var uiIndexHint: Int = 0
var uiHotkeyName: String? = null
var icon: String? = null
var modId: Long? = null
@ -81,6 +91,12 @@ class DowUnit {
@OneToMany(mappedBy = "unit", cascade = [CascadeType.ALL])
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
@JoinTable(name = "researches_affected_units",
joinColumns = [JoinColumn(name = "unit_id")],
@ -99,6 +115,52 @@ class DowUnit {
inverseJoinColumns = [JoinColumn(name = "building_id")])
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])
var unitRequirements: MutableSet<UnitRequirements> = mutableSetOf()
@ -151,10 +213,19 @@ class DowUnit {
modId!!,
sergeantsDtos,
weapons,
abilities.sortedWith ( compareBy<Ability> { it.activation?.id }.thenBy{ it.uiIndexHint.let { 0 - it } }).map { it.toShortDto() }.toSet(),
haveReinforceMenu,
affectedResearches.map { it.toResearchShortDto() }.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,
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 jakarta.persistence.Entity
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne
import jakarta.persistence.Table
@Entity
@Table(name = "unit_requirements")
class UnitRequirements: RequirementBase() {
@ -15,4 +15,4 @@ class UnitRequirements: RequirementBase() {
@JoinColumn(name = "unit_id", nullable = false)
@JsonIgnore
var unit: DowUnit? = null
}
}

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.entities.weapon.Weapon
import com.fasterxml.jackson.annotation.JsonIgnore
import java.io.Serializable
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.WeaponDto
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.building.Building
import com.dowstats.data.entities.building.BuildingWeapon
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.*
@ -39,6 +44,7 @@ class Weapon {
var isMeleeWeapon: Boolean = true
var canAttackAir: Boolean = true
var canAttackGround: Boolean = true
var uiHotkeyName: String? = null
var icon: String? = null
var showInReinforce: Boolean = true
var modId: Long? = null
@ -61,6 +67,24 @@ class Weapon {
inverseJoinColumns = [JoinColumn(name = "building_id")])
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])
var unitsUse: MutableSet<UnitWeapon>? = null
@ -73,6 +97,9 @@ class Weapon {
// for many-to-many persistance
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])
var weaponRequirements: MutableSet<WeaponRequirements> = mutableSetOf()
@ -110,7 +137,9 @@ class Weapon {
weaponPiercings.map { it.toDto() },
affectedResearches.map { it.toResearchShortDto() }.toSet(),
affectedAddons.map { it.toShortDto() }.toSet(),
weaponModifiers.map { mod -> mod.toDto().copy(maxLifeTime = mod.maxLifeTime) },
requirementDto,
uiHotkeyName,
)
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.entities.ArmorType
import com.fasterxml.jackson.annotation.JsonIgnore
import java.math.BigDecimal
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 jakarta.persistence.Entity
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
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 org.springframework.data.repository.*

View File

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

View File

@ -1,6 +1,6 @@
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 org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.*

View File

@ -1,8 +1,6 @@
package com.dowstats.data.repositories
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.Weapon
import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.weapon.Weapon
import org.springframework.data.repository.*
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.entities.building.Building
import com.dowstats.data.entities.DowUnitObject.toUnitDto
import com.dowstats.data.entities.unit.DowUnitObject.toUnitDto
object CommonMapping {
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.SergeantDto
import com.dowstats.data.dto.controllers.UnitFullDto
import com.dowstats.data.entities.DowUnit
import com.dowstats.data.entities.DowUnitObject.toUnitDto
import com.dowstats.data.entities.unit.DowUnit
import com.dowstats.data.entities.unit.DowUnitObject.toUnitDto
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.UnitRepository
import org.springframework.beans.factory.annotation.Autowired

View File

@ -1,15 +1,6 @@
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.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 org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service

View File

@ -1,9 +1,13 @@
package com.dowstats.service.postparsing
import com.dowstats.data.entities.*
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.entities.addon.BuildingAddon
import com.dowstats.data.entities.building.Building
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 org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
@ -15,6 +19,7 @@ class PostParsingService @Autowired constructor(
val researchRepository: ResearchRepository,
val addonRepository: AddonRepository,
val unitRepository: UnitRepository,
val abilityRepository: AbilityRepository,
val sergeantRepository: SergeantRepository,
val buildingRepository: BuildingRepository,
val weaponRepository: WeaponRepository,
@ -27,6 +32,7 @@ class PostParsingService @Autowired constructor(
val modId = mod.id!!
val researches = researchRepository.findAllByModId(modId)
val addons = addonRepository.findAllByModId(modId)
val abilities = abilityRepository.findAllByModId(modId)
val units = unitRepository.findByModIdAndRace(modId, null)
val sergeants = sergeantRepository.findAllByModId(modId)
val buildings = buildingRepository.findByModIdAndRace(modId, null)
@ -47,6 +53,21 @@ class PostParsingService @Autowired constructor(
bindBuildingToAffectedBuildings(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) {
log.warn("Error occurred during bind researches", e)
}
@ -232,4 +253,181 @@ class PostParsingService @Autowired constructor(
weaponRepository.saveAll(weaponsWithBindings)
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.data.entities.*
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.fillDataFromRgdTable
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.addon.AddonModifiers
import com.dowstats.data.entities.addon.AddonRequirements
@ -40,6 +41,7 @@ class BuildingAddonRgdExtractService @Autowired constructor(
addon.name = uiInfo.name
addon.description = uiInfo.description
addon.uiIndexHint = addonRgdData.getIntByName("ui_index_hint") ?: 0
addon.uiHotkeyName = addonRgdData.getStringByName("ui_hotkey_name")
addon.icon = uiInfo.iconPath
addon.filename = fileName
@ -66,11 +68,7 @@ class BuildingAddonRgdExtractService @Autowired constructor(
if (mTable.getStringByName("\$REF") == "modifiers\\no_modifier.lua") null else {
AddonModifiers().also {
it.addon = addon
it.reference = mTable.getStringByName("\$REF")
it.target = mTable.getStringByName("target_type_name")
it.usageType = mTable.getRgdTableByName("usage_type")?.getStringByName("\$REF")
it.value = mTable.getDoubleByName("value")
}
}.fillDataFromRgdTable(mTable)
}
} else null
}?.filterUseless() ?: emptyList()

View File

@ -3,11 +3,15 @@ package com.dowstats.service.w40k
import com.dowstats.Metadata
import com.dowstats.data.dto.BuildingDataToSave
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.building.Building
import com.dowstats.data.entities.building.BuildingModifiers
import com.dowstats.data.entities.building.BuildingRequirements
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.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
@ -44,6 +48,7 @@ class BuildingRgdExtractService @Autowired constructor(
modDictionary: Map<Int, String>,
buildingData: List<RgdData>,
weapons: Set<Weapon>,
abilities: Set<Ability>,
researches: Set<Research>,
units: List<DowUnit>,
race: Race,
@ -61,13 +66,14 @@ class BuildingRgdExtractService @Autowired constructor(
building.armorType2 = getBuildingArmourType(buildingData, armorTypes, "type_armour_2")
building.filename = fileName
val buildingUiInfo = buildingData.getRgdTableByName("ui_ext")
?.getRgdTableByName("ui_info") ?: throw Exception("Could not find ui_info at $fileName")
val uiExt = buildingData.getRgdTableByName("ui_ext") ?: throw Exception("Could not find ui_ext 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)
building.name = buildingUiData.name
building.description = buildingUiData.description
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
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.abilities = commonParseRgdService.getAbilities(buildingData, abilities).toMutableSet()
val addons = getAddons(buildingData)
building.addons = addons?.mapNotNull {addonFileName ->
val addonRgdData = addonsRgdData[addonFileName]
@ -172,7 +180,7 @@ class BuildingRgdExtractService @Autowired constructor(
if (it != "") {
WeaponsData(hardpointValue,
weapon.name.replace("weapon_", "").toInt(),
it.replace("weapon\\", "").replace(".lua", ""))
it.replace("weapon\\", "").replace(".lua", "").replace(".rgd", ""))
} 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 {
BuildingModifiers().also {
it.building = building
it.reference = mTable.getStringByName("\$REF")
it.target = mTable.getStringByName("target_type_name")
it.usageType = mTable.getRgdTableByName("usage_type")?.getStringByName("\$REF")
it.value = mTable.getDoubleByName("value")
}
}.fillDataFromRgdTable(mTable)
}
} else null
}.filterUseless()

View File

@ -6,6 +6,7 @@ import com.dowstats.data.dto.BuildCost
import com.dowstats.data.dto.ResourceIncome
import com.dowstats.data.dto.UiInfo
import com.dowstats.data.entities.Mod
import com.dowstats.data.entities.ability.Ability
import com.dowstats.data.rgd.RgdData
import com.dowstats.data.rgd.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
@ -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 name = nameRef?.let { try { modDictionary[it.toInt()] } catch (e: Exception) { it } }
@ -89,7 +90,9 @@ class CommonParseRgdService @Autowired constructor(
}
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) }
?.let { iconsService.convertTgaToJpegImage(iconPath, it, mod.name) }
@ -101,19 +104,29 @@ class CommonParseRgdService @Autowired constructor(
return UiInfo(name, description, icon)
}
fun getAreaEffectData(weaponData: List<RgdData>): AreaEffect {
val areaEffect = weaponData.getRgdTableByName("area_effect")
fun getAreaEffectData(areaEffectData: List<RgdData>): AreaEffect {
val areaEffectInformation = areaEffect?.getRgdTableByName("area_effect_information")
val cantHaveRadius = areaEffectInformation?.getRgdTableByName("area_type")?.getStringByName("\$REF")?.contains("tp_area_effect_point") == true
val areaEffectInformation = areaEffectData.getRgdTableByName("area_effect_information")
val areaType = areaEffectInformation?.getRgdTableByName("area_type")
?.getStringByName("\$REF")
?.replace("type_areaeffect\\tp_","")
?.replace(".lua","")
val filterType = areaEffectInformation?.getRgdTableByName("filter_type")
?.getStringByName("\$REF")
?.replace("type_areafilter\\tp_","")
?.replace(".lua","")
val cantHaveRadius = areaEffectInformation?.equals("area_effect_point") == true
val damageRadius = if(cantHaveRadius) 0.0 else areaEffectInformation?.getDoubleByName("radius") ?: 0.0
val throwData = areaEffect?.getRgdTableByName("throw_data")
val throwData = areaEffectData.getRgdTableByName("throw_data")
val forceMin = throwData?.getDoubleByName("force_min") ?: 0.0
val forceMax = throwData?.getDoubleByName("force_max") ?: 0.0
val armourDamage = areaEffect
?.getRgdTableByName("weapon_damage")
val armourDamage = areaEffectData
.getRgdTableByName("weapon_damage")
?.getRgdTableByName("armour_damage")
val minDamage = armourDamage?.getDoubleByName("min_damage") ?: 0.0
val maxDamage = armourDamage?.getDoubleByName("max_damage") ?: 0.0
@ -121,6 +134,7 @@ class CommonParseRgdService @Autowired constructor(
val moraleDamage = armourDamage?.getDoubleByName("morale_damage") ?: 0.0
val defaultArmourPiercing = armourDamage?.getDoubleByName("armour_piercing") ?: 0.0
val weaponDmgMap: Map<String, Double> =
armourDamage?.getRgdTableByName("armour_piercing_types")?.mapNotNull { armour_piercing ->
@ -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 =
"$modFolderData${File.separator}attrib${File.separator}weapon"
fun getAbilitiesAttribsPath(modFolderData: String): String =
"$modFolderData${File.separator}attrib${File.separator}abilities"
fun getResearchAttribsPath(modFolderData: String): String =
"$modFolderData${File.separator}attrib${File.separator}research"

View File

@ -1,9 +1,15 @@
package com.dowstats.service.w40k
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.BuildingWeaponKey
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.rgd.RgdData
import com.dowstats.service.postparsing.PostParsingService
@ -24,8 +30,13 @@ class ModParserService @Autowired constructor(
val researchRgdExtractService: ResearchRgdExtractService,
val raceRepository: RaceRepository,
val armorTypeRepository: ArmorTypeRepository,
val areaEffectRepository: AreaEffectRepository,
val areaFilterRepository: AreaFilterRepository,
val activationRepository: ActivationRepository,
val unitRepository: UnitRepository,
val sergeantRepository: SergeantRepository,
val abilityRgdExtractService: AbilityRgdExtractService,
val abilityRepository: AbilityRepository,
val weaponRgdExtractService: WeaponRgdExtractService,
val weaponRepository: WeaponRepository,
val modAttribPathService: ModAttribPathService,
@ -76,6 +87,10 @@ class ModParserService @Autowired constructor(
armorTypeRepository.findByIsUa(true).toSet()
else armorTypeRepository.findByIsClassic(true).toSet()
val areaEffects = areaEffectRepository.findAll().toSet()
val areaFilters = areaFilterRepository.findAll().toSet()
val activations = activationRepository.findAll().toSet()
racesList.forEach {
unitRepository.deleteAllByModIdAndRaceId(mod.id!!, it)
}
@ -87,9 +102,10 @@ class ModParserService @Autowired constructor(
val enrichedModDictionary = defaultDictionary + modDictionary
val weapons = saveWeapons(modFolderData, mod, armorTypes, enrichedModDictionary)
val abilities = saveAbilities(modFolderData, mod, activations, areaEffects, areaFilters, armorTypes, enrichedModDictionary)
val researches = saveResearches(modFolderData, mod, enrichedModDictionary)
saveUnits(modFolderData, weapons, racesList, armorTypes, mod, enrichedModDictionary)
saveBuildings(modFolderData, weapons, researches, racesList, armorTypes, mod, enrichedModDictionary)
saveUnits(modFolderData, weapons, abilities, racesList, armorTypes, mod, enrichedModDictionary)
saveBuildings(modFolderData, weapons, abilities, researches, racesList, armorTypes, mod, enrichedModDictionary)
modRepository.removeCampaignEntities(mod.id!!)
postParsingService.bindResearch(mod)
@ -170,6 +186,7 @@ class ModParserService @Autowired constructor(
private fun saveUnits(
modFolderData: String,
weapons: Set<Weapon>,
abilities: Set<Ability>,
racesList: List<String>,
armorTypes: Set<ArmorType>,
mod: Mod,
@ -235,6 +252,7 @@ class ModParserService @Autowired constructor(
squadRgdData.value,
unitRgdData,
weapons,
abilities,
raceFolder,
modFolderData,
mod,
@ -298,6 +316,7 @@ class ModParserService @Autowired constructor(
private fun saveBuildings(
modFolderData: String,
weapons: Set<Weapon>,
abilities: Set<Ability>,
researches: Set<Research>,
racesList: List<String>,
armorTypes: Set<ArmorType>,
@ -342,6 +361,7 @@ class ModParserService @Autowired constructor(
modDictionary,
structure.value,
weapons,
abilities,
researches,
raceUnits,
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.data.entities.*
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.fillDataFromRgdTable
import com.dowstats.data.entities.ModifiersBase.ModifiersBaseCompanion.filterUseless
import com.dowstats.data.entities.research.Research
import com.dowstats.data.entities.research.ResearchModifiers
import com.dowstats.data.entities.research.ResearchRequirements
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
@ -38,6 +40,7 @@ class ResearchRgdExtractService @Autowired constructor(
research.name = researchUiInfo.name
research.description = researchUiInfo.description
research.uiIndexHint = researchData.getIntByName("ui_index_hint") ?: 0
research.uiHotkeyName = researchData.getStringByName("ui_hotkey_name")
research.icon = researchUiInfo.iconPath
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 {
ResearchModifiers().also {
it.research = research
it.reference = mTable.getStringByName("\$REF")
it.usageType = mTable.getRgdTableByName("usage_type")?.getStringByName("\$REF")
it.target = mTable.getStringByName("target_type_name")
it.value = mTable.getDoubleByName("value")
}
}.fillDataFromRgdTable(mTable)
}
} else null
}?.filterUseless() ?: emptyList()

View File

@ -3,6 +3,13 @@ package com.dowstats.service.w40k
import com.dowstats.Metadata
import com.dowstats.data.dto.BuildCost
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.RgdDataUtil.getDoubleByName
import com.dowstats.data.rgd.RgdDataUtil.getIntByName
@ -44,6 +51,7 @@ class SergeantRgdExtractService @Autowired constructor(
mod: Mod,
sergeantData: List<RgdData>,
weapons: Set<Weapon>,
abilities: Set<Ability>,
modFolderData: String,
buildCost: BuildCost,
armorTypes: Set<ArmorType>,
@ -62,13 +70,14 @@ class SergeantRgdExtractService @Autowired constructor(
sergeant.armorType2 = getUnitArmorType(sergeantData, armorTypes, "type_armour_2")
sergeant.filename = fileName
val sergeantUiRgd = sergeantData.getRgdTableByName("ui_ext")
?.getRgdTableByName("ui_info") ?: throw Exception("$fileName")
val uiExt = sergeantData.getRgdTableByName("ui_ext") ?: throw Exception("Could not find ui_ext at $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)
sergeant.name = sergeantUiInfo.name
sergeant.description = sergeantUiInfo.description
sergeant.icon = sergeantUiInfo.iconPath
sergeant.uiHotkeyName = uiExt.getStringByName("ui_hotkey_name")
val healthData = getHealthAndMoraleDeathPenaltyData(sergeantData)
sergeant.health = healthData.hitpoints?.toInt()
@ -76,6 +85,10 @@ class SergeantRgdExtractService @Autowired constructor(
sergeant.healthRegeneration = healthData.regeneration
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"))
sergeant.faithIncome = incomeData.faith
sergeant.powerIncome = incomeData.power
@ -90,8 +103,11 @@ class SergeantRgdExtractService @Autowired constructor(
sergeant.modId = mod.id!!
sergeant.sergeantModifiers = getSergeantModifiers(sergeant, sergeantData).toMutableSet()
sergeant.sergeantRequirements = getSergeantRequirements(sergeant, sergeantData).toMutableSet()
sergeant.abilities = commonParseRgdService.getAbilities(sergeantData, abilities).toMutableSet()
val sergeantWeapons = getSergeantWeapons(sergeantData)?.mapNotNull { weaponData ->
weapons.find {
it.filename == weaponData.weaponFilename + ".rgd"
@ -166,6 +182,18 @@ class SergeantRgdExtractService @Autowired constructor(
} else null
}?.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> {
val requirements = sergeantData.getRgdTableByName("requirement_ext")?.getRgdTableByName("requirements")
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.WeaponsData
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.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
@ -60,6 +69,7 @@ class UnitRgdExtractService @Autowired constructor(
squadData: List<RgdData>,
unitData: List<RgdData>,
weapons: Set<Weapon>,
abilities: Set<Ability>,
race: String,
modFolderData: String,
mod: Mod,
@ -84,6 +94,7 @@ class UnitRgdExtractService @Autowired constructor(
unit.filenameSquad = fileNameSquad
unit.filenameUnit = fileNameUnit
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
val buildCost = getBuildCost(unitData, squadData)
@ -141,7 +152,9 @@ class UnitRgdExtractService @Autowired constructor(
unit.reinforceCostSouls = reinforceCostData.souls
unit.reinforceTime = reinforceCostData.time
unit.unitModifiers = geUnitModifiers(unit, unitData, squadData).toMutableSet()
unit.unitRequirements = getUnitRequirements(unit, squadData).toMutableSet()
unit.abilities = commonParseRgdService.getAbilities(unitData, abilities).toMutableSet()
val sergeantsData = getSergeantsData(squadData)
@ -156,6 +169,7 @@ class UnitRgdExtractService @Autowired constructor(
mod,
sergeantRgdData,
weapons,
abilities,
modFolderData,
sergeantData.cost,
armorTypes
@ -304,7 +318,7 @@ class UnitRgdExtractService @Autowired constructor(
.getRgdTableByName("squad_reinforce_ext")
?.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("hardpoints")
?.mapNotNull { hardpoint ->
@ -318,7 +332,7 @@ class UnitRgdExtractService @Autowired constructor(
it.mapNotNull { weapon ->
(weapon.value as? List<RgdData>)?.getStringByName("weapon")?.let {
if (it != "") {
val weaponFileName = it.replace("weapon\\", "").replace(".lua", "")
val weaponFileName = it.replace("weapon\\", "").replace(".rgd", "").replace(".lua", "")
val weaponEntity = weapons.find {
it.filename?.replace(".rgd", "") == weaponFileName
}
@ -339,6 +353,8 @@ class UnitRgdExtractService @Autowired constructor(
} else null
}?.flatten()
private fun getSergeantsData(squadData: List<RgdData>?): Pair<List<SergeantData>?, Int?> {
val squadTable = squadData
@ -365,6 +381,40 @@ class UnitRgdExtractService @Autowired constructor(
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> {
val requirements = squadData.getRgdTableByName("squad_requirement_ext")?.getRgdTableByName("requirements")
return requirements?.mapNotNull { r ->

View File

@ -1,7 +1,14 @@
package com.dowstats.service.w40k
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.RgdDataUtil.getBooleanByName
import com.dowstats.data.rgd.RgdDataUtil.getDoubleByName
@ -32,6 +39,7 @@ class WeaponRgdExtractService @Autowired constructor(
weapon.icon = weaponUiData?.iconPath
weapon.description = weaponUiData?.description
weapon.showInReinforce = weaponUiInfo?.getBooleanByName("show_in_reinforce") ?: false
weapon.uiHotkeyName = weaponData.getStringByName("ui_hotkey_name")
val cost = commonParseRgdService.getBuildCost(weaponData.getRgdTableByName("cost"))
weapon.costRequisition = cost.requisition ?: 0.0
@ -49,26 +57,34 @@ class WeaponRgdExtractService @Autowired constructor(
weapon.canAttackGround = weaponData.getBooleanByName("can_attack_ground_units") ?: true
val areaEffectData = commonParseRgdService.getAreaEffectData(weaponData)
val areaEffectTable = weaponData.getRgdTableByName("area_effect")
val armoursPiercing = armorTypes.map {
val weaponArmourPiercing = WeaponArmorPiercing()
weaponArmourPiercing.weapon = weapon
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
if (areaEffectTable != null) {
val areaEffectData = commonParseRgdService.getAreaEffectData(areaEffectTable)
val armoursPiercing = armorTypes.map {
val weaponArmourPiercing = WeaponArmorPiercing()
weaponArmourPiercing.weapon = weapon
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.weaponModifiers = getWeaponModifiers(weapon, weaponData).toMutableSet()
weapon.weaponRequirements = getWeaponRequirements(weapon, weaponData).toMutableSet()
return if(weapon.minDamage == 0.0 && weapon.maxDamage == 0.0 && weapon.moraleDamage == 0.0){
@ -76,6 +92,24 @@ class WeaponRgdExtractService @Autowired constructor(
} 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> {
return try{
val requirements = weaponData.getRgdTableByName("requirements")

View File

@ -44,7 +44,7 @@
"baseTableName": "building_affected_weapons",
"constraintName": "fk_buildings_buildings_affected_weapons",
"referencedColumnNames": "id",
"referencedTableName": "researches",
"referencedTableName": "buildings",
"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