From 8006f2ac096ab8cd6ecef80359c8858fe9c36c07 Mon Sep 17 00:00:00 2001 From: TheSaminator Date: Wed, 15 Jun 2022 12:52:24 -0400 Subject: [PATCH] Add ship faction flavors (these will be useful for the campaign) --- .../starshipfights/game/ai/ai_optimization.kt | 2 + .../kotlin/net/starshipfights/game/ship.kt | 3 +- .../game/ship_faction_flavors.kt | 89 +++++++++ .../threejs/UniformsUtils.module_three.kt | 7 +- .../net/starshipfights/game/game_render.kt | 10 +- .../net/starshipfights/game/game_resources.kt | 3 + .../game/ship_faction_flavors_js.kt | 169 ++++++++++++++++++ .../meshes/fulkreykk-1-gannan-class.diff.png | Bin 79 -> 79 bytes .../meshes/fulkreykk-1-gannan-class.spec.png | Bin 78 -> 78 bytes .../meshes/fulkreykk-1-lodovik-class.diff.png | Bin 83 -> 83 bytes .../meshes/fulkreykk-1-lodovik-class.spec.png | Bin 82 -> 82 bytes .../meshes/fulkreykk-2-karnas-class.diff.png | Bin 83 -> 83 bytes .../meshes/fulkreykk-2-karnas-class.spec.png | Bin 82 -> 82 bytes .../meshes/fulkreykk-2-pertona-class.diff.png | Bin 83 -> 83 bytes .../meshes/fulkreykk-2-pertona-class.spec.png | Bin 82 -> 82 bytes .../meshes/fulkreykk-2-voss-class.diff.png | Bin 83 -> 83 bytes .../meshes/fulkreykk-2-voss-class.spec.png | Bin 82 -> 82 bytes .../fulkreykk-3-brekoryn-class.diff.png | Bin 83 -> 83 bytes .../fulkreykk-3-brekoryn-class.spec.png | Bin 82 -> 82 bytes .../meshes/fulkreykk-3-falk-class.diff.png | Bin 83 -> 83 bytes .../meshes/fulkreykk-3-falk-class.spec.png | Bin 82 -> 82 bytes .../meshes/fulkreykk-3-lorus-class.diff.png | Bin 83 -> 83 bytes .../meshes/fulkreykk-3-lorus-class.spec.png | Bin 82 -> 82 bytes .../meshes/fulkreykk-3-orsh-class.diff.png | Bin 83 -> 83 bytes .../meshes/fulkreykk-3-orsh-class.spec.png | Bin 82 -> 82 bytes .../meshes/fulkreykk-3-tefran-class.diff.png | Bin 83 -> 83 bytes .../meshes/fulkreykk-3-tefran-class.spec.png | Bin 82 -> 82 bytes .../meshes/fulkreykk-4-kassck-class.diff.png | Bin 83 -> 83 bytes .../meshes/fulkreykk-4-kassck-class.spec.png | Bin 82 -> 82 bytes .../meshes/fulkreykk-4-khorr-class.diff.png | Bin 83 -> 83 bytes .../meshes/fulkreykk-4-khorr-class.spec.png | Bin 82 -> 82 bytes .../meshes/usa-1-coleman-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-1-coleman-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-1-jefferson-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-1-jefferson-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-1-quenney-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-1-quenney-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-1-roosevelt-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-1-roosevelt-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-1-washington-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-1-washington-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-3-arlington-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-3-arlington-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-3-concord-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-3-concord-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-3-lexington-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-3-lexington-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-3-raven-rock-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-3-raven-rock-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-5-iowa-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-5-iowa-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-5-maryland-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-5-maryland-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-5-new-york-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-5-new-york-class.spec.png | Bin 87 -> 87 bytes .../meshes/usa-5-ohio-class.diff.png | Bin 87 -> 87 bytes .../meshes/usa-5-ohio-class.spec.png | Bin 87 -> 87 bytes .../starshipfights/data/admiralty/admirals.kt | 6 +- .../net/starshipfights/game/game_start_jvm.kt | 3 +- 59 files changed, 283 insertions(+), 9 deletions(-) create mode 100644 src/commonMain/kotlin/net/starshipfights/game/ship_faction_flavors.kt create mode 100644 src/jsMain/kotlin/net/starshipfights/game/ship_faction_flavors_js.kt diff --git a/src/commonMain/kotlin/net/starshipfights/game/ai/ai_optimization.kt b/src/commonMain/kotlin/net/starshipfights/game/ai/ai_optimization.kt index 37b0717..60aea4e 100644 --- a/src/commonMain/kotlin/net/starshipfights/game/ai/ai_optimization.kt +++ b/src/commonMain/kotlin/net/starshipfights/game/ai/ai_optimization.kt @@ -174,10 +174,12 @@ fun generateFleet(faction: Faction, rank: AdmiralRank, side: GlobalSide): Map val name = "${side}_${++shipCount}" + val flavor = FactionFlavor.defaultForFaction(faction) Ship( id = Id(name), name = name, shipType = st, + shipFlavor = flavor ) }.associateBy { it.id } } diff --git a/src/commonMain/kotlin/net/starshipfights/game/ship.kt b/src/commonMain/kotlin/net/starshipfights/game/ship.kt index a1eaf9b..85ef04f 100644 --- a/src/commonMain/kotlin/net/starshipfights/game/ship.kt +++ b/src/commonMain/kotlin/net/starshipfights/game/ship.kt @@ -9,7 +9,8 @@ data class Ship( val id: Id, val name: String, - val shipType: ShipType + val shipType: ShipType, + val shipFlavor: FactionFlavor ) { val fullName: String get() = "${shipType.faction.shipPrefix}$name" diff --git a/src/commonMain/kotlin/net/starshipfights/game/ship_faction_flavors.kt b/src/commonMain/kotlin/net/starshipfights/game/ship_faction_flavors.kt new file mode 100644 index 0000000..7daeee6 --- /dev/null +++ b/src/commonMain/kotlin/net/starshipfights/game/ship_faction_flavors.kt @@ -0,0 +1,89 @@ +package net.starshipfights.game + +import kotlinx.serialization.Serializable + +@Serializable +data class IntColor(val red: Int, val green: Int, val blue: Int) { + init { + require(red in 0..255) { "Invalid RGB value: red = $red" } + require(green in 0..255) { "Invalid RGB value: green = $green" } + require(blue in 0..255) { "Invalid RGB value: blue = $blue" } + } + + override fun toString(): String { + val redHex = red.toString(16).padStart(2, '0') + val greenHex = green.toString(16).padStart(2, '0') + val blueHex = blue.toString(16).padStart(2, '0') + + return "#$redHex$greenHex$blueHex" + } +} + +val IntColor.highlight: IntColor + get() = let { (r, g, b) -> + IntColor( + 255 - (255 - r) * 2 / 3, + 255 - (255 - g) * 2 / 3, + 255 - (255 - b) * 2 / 3, + ) + } + +val Faction.trimColor: IntColor? + get() = when (this) { + Faction.MECHYRDIA -> IntColor(255, 204, 51) + Faction.NDRC -> IntColor(255, 153, 51) + Faction.MASRA_DRAETSEN -> IntColor(34, 85, 170) + Faction.FELINAE_FELICES -> IntColor(255, 119, 187) + Faction.ISARNAREYKK -> null + Faction.VESTIGIUM -> IntColor(108, 96, 153) + } + +enum class FactionFlavor(val nativeName: String?, val translatedName: String, val colorReplacement: IntColor) { + MECHYRDIA("Štelflót Ciarstuos Mehurdiasi", "Imperial Star Fleet of Mechyrdia", IntColor(255, 204, 51)), + TYLA("Helasram Laevashtam Moashtas Tulasras", "Stellar Navy of the Tylan Republic", IntColor(51, 102, 204)), + OLYMPIA("Classis Nautica Rei Publicae Olympicae", "Naval Fleet of the Olympia Commonwealth", IntColor(204, 51, 51)), + TEXANDRIA("Texandrische Sternenmarine der Volkswehr", "Texandrian Star Navy of the Public Defense", IntColor(255, 221, 119)), + + NDRC("Sterrenvloot der NdRC", "NdRC Stellar Fleet", IntColor(255, 153, 51)), + CCC("Collegium Comitatum Caeleste", "Celestial Caravan Company", IntColor(255, 204, 51)), + MJOLNIR_ENERGY("Mjolniri Energia", "Mjölnir Energy", IntColor(34, 68, 136)), + + MASRA_DRAETSEN(null, "Diadochus Masra Draetsen", IntColor(34, 85, 170)), + AEDON_CULTISTS(null, "Aedon Cultists", IntColor(136, 68, 204)), + FERTHLON_EXILES(null, "Ferthlon Exiles", IntColor(51, 204, 68)), + + RES_NOSTRA(null, "Res Nostra", IntColor(153, 17, 85)), + CORSAIRS(null, "Corsairs' Commune", IntColor(34, 34, 34)), + FELINAE_FELICES(null, "Felinae Felices", IntColor(255, 119, 187)), + + ISARNAREYKK(null, "Isarnareyksk Federation", IntColor(255, 255, 255)), + SWARTAREYKK(null, "Swartareyksk Totalitariat", IntColor(255, 170, 170)), + THEUDAREYKK(null, "Theudareyksk Kingdom", IntColor(153, 204, 255)), + STAHLAREYKK(null, "Stahlareyksk Binding", IntColor(204, 153, 102)), + LYUDAREYKK(null, "Lyudareyksk Baurginassus", IntColor(153, 204, 153)), + NEUIA_FULKREYKK(null, "Neuia Fulkreykk Rebellion", IntColor(153, 153, 153)), + + CORVUS_CLUSTER_VESTIGIUM(null, "Vestigium Sect in the Corvus Cluster", IntColor(108, 96, 153)), + COLEMAN_SF_BASE_VESTIGIUM(null, "Vestigium Sect at Coleman Space Force Base", IntColor(153, 102, 102)), + ; + + companion object { + fun defaultForFaction(playerFaction: Faction): FactionFlavor = when (playerFaction) { + Faction.MECHYRDIA -> MECHYRDIA + Faction.NDRC -> NDRC + Faction.MASRA_DRAETSEN -> MASRA_DRAETSEN + Faction.FELINAE_FELICES -> FELINAE_FELICES + Faction.ISARNAREYKK -> ISARNAREYKK + Faction.VESTIGIUM -> CORVUS_CLUSTER_VESTIGIUM + } + + fun optionsForAiEnemy(computerFaction: Faction): Set = when (computerFaction) { + Faction.MECHYRDIA -> setOf(MECHYRDIA, TYLA, OLYMPIA, TEXANDRIA, NDRC, CORSAIRS, RES_NOSTRA) + Faction.NDRC -> setOf(NDRC, CCC, MJOLNIR_ENERGY, RES_NOSTRA, CORSAIRS) + Faction.MASRA_DRAETSEN -> setOf(MASRA_DRAETSEN, AEDON_CULTISTS, FERTHLON_EXILES) + Faction.FELINAE_FELICES -> setOf(FELINAE_FELICES, RES_NOSTRA, CORSAIRS) + Faction.ISARNAREYKK -> setOf(ISARNAREYKK, SWARTAREYKK, THEUDAREYKK, STAHLAREYKK, LYUDAREYKK, NEUIA_FULKREYKK) + Faction.VESTIGIUM -> setOf(CORVUS_CLUSTER_VESTIGIUM, COLEMAN_SF_BASE_VESTIGIUM) + } + } +} diff --git a/src/jsMain/kotlin/externals/threejs/UniformsUtils.module_three.kt b/src/jsMain/kotlin/externals/threejs/UniformsUtils.module_three.kt index d845a29..62aa3bd 100644 --- a/src/jsMain/kotlin/externals/threejs/UniformsUtils.module_three.kt +++ b/src/jsMain/kotlin/externals/threejs/UniformsUtils.module_three.kt @@ -3,6 +3,7 @@ package externals.threejs -external fun cloneUniforms(uniforms_src: Any): Any - -external fun mergeUniforms(uniforms: Array): Any +external object UniformsUtils { + fun clone(uniforms_src: Any): Any + fun merge(uniforms: Array): Any +} diff --git a/src/jsMain/kotlin/net/starshipfights/game/game_render.kt b/src/jsMain/kotlin/net/starshipfights/game/game_render.kt index d0ff67f..306ebab 100644 --- a/src/jsMain/kotlin/net/starshipfights/game/game_render.kt +++ b/src/jsMain/kotlin/net/starshipfights/game/game_render.kt @@ -1,8 +1,11 @@ package net.starshipfights.game import externals.threejs.* +import net.starshipfights.data.Id object GameRender { + private val shipMeshCache = mutableMapOf, Mesh>() + fun renderGameState(scene: Scene, state: GameState) { scene.background = RenderResources.spaceboxes.getValue(state.battleInfo.bg) scene.getObjectByName("light")?.removeFromParent() @@ -16,7 +19,10 @@ object GameRender { when (state.renderShipAs(ship, mySide)) { ShipRenderMode.NONE -> {} ShipRenderMode.SIGNAL -> shipGroup.add(RenderResources.enemySignal.generate(ship.position.location)) - ShipRenderMode.FULL -> shipGroup.add(RenderResources.shipMesh.generate(ship)) + ShipRenderMode.FULL -> shipGroup.add(shipMeshCache[ship.id]?.also { render -> + RenderScaling.toWorldRotation(ship.position.facing, render) + render.position.copy(RenderScaling.toWorldPosition(ship.position.location)) + } ?: RenderResources.shipMesh.generate(ship)) } } } @@ -27,7 +33,7 @@ object RenderScaling { const val METERS_PER_3D_MESH_UNIT = 6.9 fun toWorldRotation(facing: Double, obj: Object3D) { - obj.rotateY(-facing) + obj.rotation.y = -facing } fun toBattleLength(length3js: Double) = length3js * METERS_PER_THREEJS_UNIT diff --git a/src/jsMain/kotlin/net/starshipfights/game/game_resources.kt b/src/jsMain/kotlin/net/starshipfights/game/game_resources.kt index 0d73b67..908df1c 100644 --- a/src/jsMain/kotlin/net/starshipfights/game/game_resources.kt +++ b/src/jsMain/kotlin/net/starshipfights/game/game_resources.kt @@ -249,6 +249,8 @@ object RenderResources { outlineRed.material = redOutlineMaterial CustomRenderFactory { ship -> + val faction = ship.ship.shipType.faction + val flavor = ship.ship.shipFlavor val side = ship.owner.relativeTo(mySide) ShipRender( @@ -257,6 +259,7 @@ object RenderResources { mesh.clone(true).unsafeCast().apply { receiveShadow = true castShadow = true + material = material.unsafeCast().forShip(faction, flavor) }, when (side) { LocalSide.GREEN -> outlineGreen diff --git a/src/jsMain/kotlin/net/starshipfights/game/ship_faction_flavors_js.kt b/src/jsMain/kotlin/net/starshipfights/game/ship_faction_flavors_js.kt new file mode 100644 index 0000000..0c4bbc7 --- /dev/null +++ b/src/jsMain/kotlin/net/starshipfights/game/ship_faction_flavors_js.kt @@ -0,0 +1,169 @@ +package net.starshipfights.game + +import externals.threejs.* + +fun IntColor.to3JS() = Color(this.toString()) + +private val black = Color("#000000") +private val white = Color("#FFFFFF") + +private val shipShaderMaterial: ShaderMaterial by lazy { + val customFragmentShader = """ + |#define PHONG + | + |uniform vec3 diffuse; + |uniform vec3 emissive; + |uniform vec3 specular; + |uniform float shininess; + |uniform float opacity; + | + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + |#include + | + |uniform vec3 oldColorDiff; + |uniform vec3 oldColorSpec; + |uniform vec3 newColorDiff; + |uniform vec3 newColorSpec; + |uniform vec3 tintColor; + | + |// Add the mapTexelToLinear function manually + |vec4 mapTexelToLinear( vec4 value ) { + | return LinearToLinear( value ); + |} + | + |void main() { + | #include + | + | vec4 diffuseColor = vec4( diffuse, opacity ); + | ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + | vec3 totalEmissiveRadiance = emissive; + | + | #include + | + | // Replaces the include of map_fragment + |#ifdef USE_MAP + | vec4 texelColor = texture2D( map, vUv ); + | if (texelColor.rgb == oldColorDiff) { + | texelColor = vec4(newColorDiff, texelColor.a); + | } + | texelColor = mapTexelToLinear( texelColor ); + | diffuseColor *= texelColor; + |#endif + | + | #include + | #include + | #include + | + | // Replaces the include of specularmap_fragment + | vec3 specularStrength; + |#ifdef USE_SPECULARMAP + | vec4 texelSpecular = texture2D( specularMap, vUv ); + | if (texelSpecular.rgb == oldColorSpec) { + | texelSpecular = vec4(oldColorSpec, texelSpecular.a); + | } + | specularStrength = texelSpecular.rgb; + |#else + | specularStrength = vec3( 1.0, 1.0, 1.0 ); + |#endif + | + | #include + | #include + | #include + | + | // accumulation + | #include + | #include + | #include + | #include + | + | // modulation + | #include + | vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance; + | + | #include + | #include + | + | // Inserted custom code + | gl_FragColor = vec4(gl_FragColor.rgb * tintColor, gl_FragColor.a); + | // End of custom code + | + | #include + | #include + | #include + | #include + | #include + |} + """.trimMargin() + + ShaderMaterial( + configure { + uniforms = UniformsUtils.merge( + arrayOf( + ShaderLib.phong.uniforms, + configure { + this["oldColorDiff"] = configure { value = black } + this["oldColorSpec"] = configure { value = black } + this["newColorDiff"] = configure { value = black } + this["newColorSpec"] = configure { value = black } + this["tintColor"] = configure { value = white } + } + ) + ).unsafeCast() + defines = configure> { + this["USE_UV"] = "" + this["USE_MAP"] = "" + this["USE_SPECULARMAP"] = "" + } + vertexShader = ShaderLib.phong.vertexShader + fragmentShader = customFragmentShader + lights = true + } + ) +} + +fun MeshPhongMaterial.forShip(faction: Faction, flavor: FactionFlavor): ShaderMaterial { + return shipShaderMaterial.clone().unsafeCast().also { material -> + material.uniforms["diffuse"]?.value?.unsafeCast()?.copy(color) + material.uniforms["specular"]?.value?.unsafeCast()?.copy(specular) + material.uniforms["shininess"]?.value = shininess.toDouble().coerceAtLeast(EPSILON) + + map?.let { material.uniforms["map"]?.value = it } + specularMap?.let { material.uniforms["specularMap"]?.value = it } + + faction.trimColor?.let { oldColorDiff -> + val newColorDiff = flavor.colorReplacement + + val oldColorSpec = oldColorDiff.highlight + val newColorSpec = newColorDiff.highlight + + material.uniforms["oldColorDiff"]?.value?.unsafeCast()?.copy(oldColorDiff.to3JS()) + material.uniforms["oldColorSpec"]?.value?.unsafeCast()?.copy(oldColorSpec.to3JS()) + material.uniforms["newColorDiff"]?.value?.unsafeCast()?.copy(newColorDiff.to3JS()) + material.uniforms["newColorSpec"]?.value?.unsafeCast()?.copy(newColorSpec.to3JS()) + } ?: material.uniforms["tintColor"]?.value?.unsafeCast()?.copy(flavor.colorReplacement.to3JS()) + } +} diff --git a/src/jsMain/resources/meshes/fulkreykk-1-gannan-class.diff.png b/src/jsMain/resources/meshes/fulkreykk-1-gannan-class.diff.png index 89a96a9290ad56b0a5cd26772d888460751363c3..7122902848b80a2324eab97b27955f3516c01255 100644 GIT binary patch delta 42 xcmebGpP;20muyk|?9BfyTekc+PCxgDpTV4yBmTlnttJX`KF#ox#YF{aDluYb6FC@O1TaS?83{1OS}_5fA_X diff --git a/src/jsMain/resources/meshes/fulkreykk-1-gannan-class.spec.png b/src/jsMain/resources/meshes/fulkreykk-1-gannan-class.spec.png index ba419154dd8d8dfb10a833a26e78b9b2bf7f78fa..02d329763c082e2beac144abbdab7c8ab3714b8c 100644 GIT binary patch delta 41 wcmebCo1moy^mB85$}@zubADf5d%BPT2s~Z=T-G@yGywoM CoE9qp delta 46 zcmWFzo}i_9D|trcvorONw`}>(bL`mv%W3ES@H6=Jb81T&+cz-)fv2mV%Q~loCIB1G B6b%3X diff --git a/src/jsMain/resources/meshes/fulkreykk-1-lodovik-class.spec.png b/src/jsMain/resources/meshes/fulkreykk-1-lodovik-class.spec.png index 621e4bd2318d20ca2ed279d1cf36d2f9bf10f9e4..a9a204177b071ecb8161b7d60d22ae2e18bf7fec 100644 GIT binary patch delta 45 zcmWFvnxLf-m;By>G`rgD(Y4}gEJ%h&ln+-8w^0;>FVdQ&MBb@00fy6 Avj6}9 delta 45 zcmWFvnxLg|E7{}qiy!NsJo+@>(eveg@2Fe#47MBD3-vQ9v>1TE)78&qol`;+00g%a Ao&W#< diff --git a/src/jsMain/resources/meshes/fulkreykk-2-karnas-class.diff.png b/src/jsMain/resources/meshes/fulkreykk-2-karnas-class.diff.png index 522b9ce6fc7735a45b399358c3bfbae14d3b7b8b..8c6cf1ee0fd57565cf332a93c87f497ac6b5924f 100644 GIT binary patch delta 46 zcmWFzo}i@}muyk|?9Bg}#_9k3y}f_u=j8m6XNcX*`F(Po&@Toc@O1TaS?83{1OVYr B6FC3? delta 46 zcmWFzo}i_9D|trcvors<%ryQly?p84bOW=0{0yPHIknaHy9Y4?2{ B7Ha?i delta 45 zcmWFvnxLg|E7{}qiy!YNP5Tyq^5|3h=1G_88JsHF3xjhiS{Z=A)78&qol`;+01pHd AJOBUy diff --git a/src/jsMain/resources/meshes/fulkreykk-2-pertona-class.diff.png b/src/jsMain/resources/meshes/fulkreykk-2-pertona-class.diff.png index 522b9ce6fc7735a45b399358c3bfbae14d3b7b8b..8c6cf1ee0fd57565cf332a93c87f497ac6b5924f 100644 GIT binary patch delta 46 zcmWFzo}i@}muyk|?9Bg}#_9k3y}f_u=j8m6XNcX*`F(Po&@Toc@O1TaS?83{1OVYr B6FC3? delta 46 zcmWFzo}i_9D|trcvors<%ryQly?p84bOW=0{0yPHIknaHy9Y4?2{ B7Ha?i delta 45 zcmWFvnxLg|E7{}qiy!YNP5Tyq^5|3h=1G_88JsHF3xjhiS{Z=A)78&qol`;+01pHd AJOBUy diff --git a/src/jsMain/resources/meshes/fulkreykk-2-voss-class.diff.png b/src/jsMain/resources/meshes/fulkreykk-2-voss-class.diff.png index e6865b38d6c734ee993c8e809606b65ff7217ee7..fc5c53eadaee31a2db9ae91bee99cd14f3c5bc72 100644 GIT binary patch delta 46 zcmWFzo}i@}muyk|?9BfyTekc+PCxf2KPTspJVUfU=Xa)c6G|C?z|+;wWt~$(69E6` B6WIU& delta 46 zcmWFzo}i_9D|trcvorONw`}>JX`KEq-N5W0KSOXhr?z&_*B}NU@O1TaS?83{1OWFo B68r!F diff --git a/src/jsMain/resources/meshes/fulkreykk-2-voss-class.spec.png b/src/jsMain/resources/meshes/fulkreykk-2-voss-class.spec.png index 31b52423802bbbd30ffe2d1a8f55b25941b14ff6..fb61f01309acfb1852068042aa11fe3f8f2ddc68 100644 GIT binary patch delta 45 zcmWFvnxLf-m;BPx# delta 45 zcmWFvnxLg|E7{}qiy!NsJozopr02-MU AAOHXW diff --git a/src/jsMain/resources/meshes/fulkreykk-3-brekoryn-class.diff.png b/src/jsMain/resources/meshes/fulkreykk-3-brekoryn-class.diff.png index 522b9ce6fc7735a45b399358c3bfbae14d3b7b8b..8c6cf1ee0fd57565cf332a93c87f497ac6b5924f 100644 GIT binary patch delta 46 zcmWFzo}i@}muyk|?9Bg}#_9k3y}f_u=j8m6XNcX*`F(Po&@Toc@O1TaS?83{1OVYr B6FC3? delta 46 zcmWFzo}i_9D|trcvors<%ryQly?p84bOW=0{0yPHIknaHy9Y4?2{ B7Ha?i delta 45 zcmWFvnxLg|E7{}qiy!YNP5Tyq^5|3h=1G_88JsHF3xjhiS{Z=A)78&qol`;+01pHd AJOBUy diff --git a/src/jsMain/resources/meshes/fulkreykk-3-falk-class.diff.png b/src/jsMain/resources/meshes/fulkreykk-3-falk-class.diff.png index 522b9ce6fc7735a45b399358c3bfbae14d3b7b8b..8c6cf1ee0fd57565cf332a93c87f497ac6b5924f 100644 GIT binary patch delta 46 zcmWFzo}i@}muyk|?9Bg}#_9k3y}f_u=j8m6XNcX*`F(Po&@Toc@O1TaS?83{1OVYr B6FC3? delta 46 zcmWFzo}i_9D|trcvors<%ryQly?p84bOW=0{0yPHIknaHy9Y4?2{ B7Ha?i delta 45 zcmWFvnxLg|E7{}qiy!YNP5Tyq^5|3h=1G_88JsHF3xjhiS{Z=A)78&qol`;+01pHd AJOBUy diff --git a/src/jsMain/resources/meshes/fulkreykk-3-lorus-class.diff.png b/src/jsMain/resources/meshes/fulkreykk-3-lorus-class.diff.png index 522b9ce6fc7735a45b399358c3bfbae14d3b7b8b..8c6cf1ee0fd57565cf332a93c87f497ac6b5924f 100644 GIT binary patch delta 46 zcmWFzo}i@}muyk|?9Bg}#_9k3y}f_u=j8m6XNcX*`F(Po&@Toc@O1TaS?83{1OVYr B6FC3? delta 46 zcmWFzo}i_9D|trcvors<%ryQly?p84bOW=0{0yPHIknaHy9Y4?2{ B7Ha?i delta 45 zcmWFvnxLg|E7{}qiy!YNP5Tyq^5|3h=1G_88JsHF3xjhiS{Z=A)78&qol`;+01pHd AJOBUy diff --git a/src/jsMain/resources/meshes/fulkreykk-3-orsh-class.diff.png b/src/jsMain/resources/meshes/fulkreykk-3-orsh-class.diff.png index e6865b38d6c734ee993c8e809606b65ff7217ee7..fc5c53eadaee31a2db9ae91bee99cd14f3c5bc72 100644 GIT binary patch delta 46 zcmWFzo}i@}muyk|?9BfyTekc+PCxf2KPTspJVUfU=Xa)c6G|C?z|+;wWt~$(69E6` B6WIU& delta 46 zcmWFzo}i_9D|trcvorONw`}>JX`KEq-N5W0KSOXhr?z&_*B}NU@O1TaS?83{1OWFo B68r!F diff --git a/src/jsMain/resources/meshes/fulkreykk-3-orsh-class.spec.png b/src/jsMain/resources/meshes/fulkreykk-3-orsh-class.spec.png index 31b52423802bbbd30ffe2d1a8f55b25941b14ff6..fb61f01309acfb1852068042aa11fe3f8f2ddc68 100644 GIT binary patch delta 45 zcmWFvnxLf-m;BPx# delta 45 zcmWFvnxLg|E7{}qiy!NsJozopr02-MU AAOHXW diff --git a/src/jsMain/resources/meshes/fulkreykk-3-tefran-class.diff.png b/src/jsMain/resources/meshes/fulkreykk-3-tefran-class.diff.png index 522b9ce6fc7735a45b399358c3bfbae14d3b7b8b..8c6cf1ee0fd57565cf332a93c87f497ac6b5924f 100644 GIT binary patch delta 46 zcmWFzo}i@}muyk|?9Bg}#_9k3y}f_u=j8m6XNcX*`F(Po&@Toc@O1TaS?83{1OVYr B6FC3? delta 46 zcmWFzo}i_9D|trcvors<%ryQly?p84bOW=0{0yPHIknaHy9Y4?2{ B7Ha?i delta 45 zcmWFvnxLg|E7{}qiy!YNP5Tyq^5|3h=1G_88JsHF3xjhiS{Z=A)78&qol`;+01pHd AJOBUy diff --git a/src/jsMain/resources/meshes/fulkreykk-4-kassck-class.diff.png b/src/jsMain/resources/meshes/fulkreykk-4-kassck-class.diff.png index 522b9ce6fc7735a45b399358c3bfbae14d3b7b8b..8c6cf1ee0fd57565cf332a93c87f497ac6b5924f 100644 GIT binary patch delta 46 zcmWFzo}i@}muyk|?9Bg}#_9k3y}f_u=j8m6XNcX*`F(Po&@Toc@O1TaS?83{1OVYr B6FC3? delta 46 zcmWFzo}i_9D|trcvors<%ryQly?p84bOW=0{0yPHIknaHy9Y4?2{ B7Ha?i delta 45 zcmWFvnxLg|E7{}qiy!YNP5Tyq^5|3h=1G_88JsHF3xjhiS{Z=A)78&qol`;+01pHd AJOBUy diff --git a/src/jsMain/resources/meshes/fulkreykk-4-khorr-class.diff.png b/src/jsMain/resources/meshes/fulkreykk-4-khorr-class.diff.png index 522b9ce6fc7735a45b399358c3bfbae14d3b7b8b..8c6cf1ee0fd57565cf332a93c87f497ac6b5924f 100644 GIT binary patch delta 46 zcmWFzo}i@}muyk|?9Bg}#_9k3y}f_u=j8m6XNcX*`F(Po&@Toc@O1TaS?83{1OVYr B6FC3? delta 46 zcmWFzo}i_9D|trcvors<%ryQly?p84bOW=0{0yPHIknaHy9Y4?2{ B7Ha?i delta 45 zcmWFvnxLg|E7{}qiy!YNP5Tyq^5|3h=1G_88JsHF3xjhiS{Z=A)78&qol`;+01pHd AJOBUy diff --git a/src/jsMain/resources/meshes/usa-1-coleman-class.diff.png b/src/jsMain/resources/meshes/usa-1-coleman-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-1-jefferson-class.diff.png b/src/jsMain/resources/meshes/usa-1-jefferson-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-1-quenney-class.diff.png b/src/jsMain/resources/meshes/usa-1-quenney-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-1-roosevelt-class.diff.png b/src/jsMain/resources/meshes/usa-1-roosevelt-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-1-washington-class.diff.png b/src/jsMain/resources/meshes/usa-1-washington-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-3-arlington-class.diff.png b/src/jsMain/resources/meshes/usa-3-arlington-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-3-concord-class.diff.png b/src/jsMain/resources/meshes/usa-3-concord-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-3-lexington-class.diff.png b/src/jsMain/resources/meshes/usa-3-lexington-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-3-raven-rock-class.diff.png b/src/jsMain/resources/meshes/usa-3-raven-rock-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-5-iowa-class.diff.png b/src/jsMain/resources/meshes/usa-5-iowa-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-5-maryland-class.diff.png b/src/jsMain/resources/meshes/usa-5-maryland-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-5-new-york-class.diff.png b/src/jsMain/resources/meshes/usa-5-new-york-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jsMain/resources/meshes/usa-5-ohio-class.diff.png b/src/jsMain/resources/meshes/usa-5-ohio-class.diff.png index f6e42f10c4e01a54e7b9d0ade8cc38d6626d2d89..4fce63f01007f780a32f596853188648b8a7a485 100644 GIT binary patch delta 50 zcmWF!pP;21mwdu=#?ShblT`nopJ)4f|E^uX_AguZte&BZnP)+;F8?Y9An?u!6r2D6 delta 50 zcmWF!pP;3CD|v@?@w5L6?)3eCDZBdLZPulK#V3aS;%8`J<~DMj7P+1Q2s~Z=T-G@y GGywp6mlgB? diff --git a/src/jvmMain/kotlin/net/starshipfights/data/admiralty/admirals.kt b/src/jvmMain/kotlin/net/starshipfights/data/admiralty/admirals.kt index ae3a248..01f3be2 100644 --- a/src/jvmMain/kotlin/net/starshipfights/data/admiralty/admirals.kt +++ b/src/jvmMain/kotlin/net/starshipfights/data/admiralty/admirals.kt @@ -67,11 +67,12 @@ data class ShipInDrydock( override val id: Id = Id(), val name: String, val shipType: ShipType, + val shipFlavor: FactionFlavor = FactionFlavor.defaultForFaction(shipType.faction), val readyAt: @Contextual Instant, val owningAdmiral: Id ) : DataDocument { val shipData: Ship - get() = Ship(id.reinterpret(), name, shipType) + get() = Ship(id.reinterpret(), name, shipType, shipFlavor) val fullName: String get() = shipData.fullName @@ -132,7 +133,7 @@ suspend fun getAdmiralsShips(admiralId: Id): Map, Ship> { .associate { it.shipData.id to it.shipData } } -fun generateFleet(admiral: Admiral): List = ShipWeightClass.values() +fun generateFleet(admiral: Admiral, flavor: FactionFlavor = FactionFlavor.defaultForFaction(admiral.faction)): List = ShipWeightClass.values() .flatMap { swc -> val shipTypes = ShipType.values().filter { st -> st.weightClass == swc && st.faction == admiral.faction @@ -155,6 +156,7 @@ fun generateFleet(admiral: Admiral): List = ShipWeightClass.value id = Id(), name = name, shipType = st, + shipFlavor = flavor, readyAt = now, owningAdmiral = admiral.id ) diff --git a/src/jvmMain/kotlin/net/starshipfights/game/game_start_jvm.kt b/src/jvmMain/kotlin/net/starshipfights/game/game_start_jvm.kt index a6d5733..89c84b4 100644 --- a/src/jvmMain/kotlin/net/starshipfights/game/game_start_jvm.kt +++ b/src/jvmMain/kotlin/net/starshipfights/game/game_start_jvm.kt @@ -47,6 +47,7 @@ suspend fun generateTrainingInitialState(playerInfo: InGameAdmiral, enemyFaction val guestDeployCenter = Position(Vec2(0.0, (battleLength / 2) - deployLength2)) val aiAdmiral = genAI(enemyFaction, battleInfo.size) + val aiFlavor = FactionFlavor.optionsForAiEnemy(enemyFaction).random() return GameState( start = GameStart( @@ -66,7 +67,7 @@ suspend fun generateTrainingInitialState(playerInfo: InGameAdmiral, enemyFaction -PI / 2, PickBoundary.Rectangle(guestDeployCenter, deployWidth2, deployLength2), -PI / 2, - generateFleet(aiAdmiral) + generateFleet(aiAdmiral, aiFlavor) .associate { it.shipData.id to it.shipData } .filterValues { it.shipType.weightClass.tier <= battleInfo.size.maxTier } ) -- 2.25.1