mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-02 13:18:26 +08:00
Upgraded Kotlin to 1.4.30 and Gradle to 6.8.2. Set the Kotlin JVM version to 11. Added a subproject for offline asset generation which, at the moment, can generate the list of item types. Ported unitxt and ItemPMT parsing.
This commit is contained in:
parent
93e57012e7
commit
321fb3a475
@ -1,16 +1,18 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
|
||||
|
||||
plugins {
|
||||
kotlin("js") version "1.4.20" apply false
|
||||
kotlin("multiplatform") version "1.4.20" apply false
|
||||
kotlin("plugin.serialization") version "1.4.20" apply false
|
||||
kotlin("js") version "1.4.30" apply false
|
||||
kotlin("multiplatform") version "1.4.30" apply false
|
||||
kotlin("plugin.serialization") version "1.4.30" apply false
|
||||
}
|
||||
|
||||
tasks.wrapper {
|
||||
gradleVersion = "6.6.1"
|
||||
gradleVersion = "6.8.2"
|
||||
}
|
||||
|
||||
subprojects {
|
||||
project.extra["jvmVersion"] = "11"
|
||||
|
||||
project.extra["coroutinesVersion"] = "1.4.2"
|
||||
project.extra["kotlinLoggingVersion"] = "2.0.2"
|
||||
project.extra["ktorVersion"] = "1.4.3"
|
||||
|
@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "1.4.20"
|
||||
kotlin("jvm") version "1.4.30"
|
||||
`java-gradle-plugin`
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,14 @@ plugins {
|
||||
val coroutinesVersion: String by project.ext
|
||||
val kotlinLoggingVersion: String by project.extra
|
||||
|
||||
val jvmVersion: String by project.extra
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
kotlinOptions {
|
||||
jvmTarget = jvmVersion
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
js {
|
||||
browser {}
|
||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
2
gradlew
vendored
2
gradlew
vendored
@ -130,7 +130,7 @@ fi
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
|
21
gradlew.bat
vendored
21
gradlew.bat
vendored
@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@ -54,7 +54,7 @@ goto fail
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
@ -64,21 +64,6 @@ echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
@ -20,6 +20,14 @@ val kotlinLoggingVersion: String by project.extra
|
||||
val serializationVersion: String by project.extra
|
||||
val slf4jVersion: String by project.extra
|
||||
|
||||
val jvmVersion: String by project.extra
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
kotlinOptions {
|
||||
jvmTarget = jvmVersion
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
js {
|
||||
browser {
|
||||
|
@ -0,0 +1,257 @@
|
||||
package world.phantasmal.lib.fileFormats
|
||||
|
||||
import world.phantasmal.lib.cursor.Cursor
|
||||
|
||||
class ItemPmt(
|
||||
val statBoosts: List<PmtStatBoost>,
|
||||
val frames: List<PmtFrame>,
|
||||
val barriers: List<PmtFrame>,
|
||||
val units: List<PmtUnit>,
|
||||
val tools: List<List<PmtTool>>,
|
||||
val weapons: List<List<PmtWeapon>>,
|
||||
)
|
||||
|
||||
class PmtStatBoost(
|
||||
val stat1: Int,
|
||||
val stat2: Int,
|
||||
val amount1: Int,
|
||||
val amount2: Int,
|
||||
)
|
||||
|
||||
class PmtFrame(
|
||||
val id: Int,
|
||||
val type: Int,
|
||||
val skin: Int,
|
||||
val teamPoints: Int,
|
||||
val dfp: Int,
|
||||
val evp: Int,
|
||||
val blockParticle: Int,
|
||||
val blockEffect: Int,
|
||||
val frameClass: Int,
|
||||
val reserved1: Int,
|
||||
val requiredLevel: Int,
|
||||
val efr: Int,
|
||||
val eth: Int,
|
||||
val eic: Int,
|
||||
val edk: Int,
|
||||
val elt: Int,
|
||||
val dfpRange: Int,
|
||||
val evpRange: Int,
|
||||
val statBoost: Int,
|
||||
val techBoost: Int,
|
||||
val unknown1: Int,
|
||||
)
|
||||
|
||||
class PmtUnit(
|
||||
val id: Int,
|
||||
val type: Int,
|
||||
val skin: Int,
|
||||
val teamPoints: Int,
|
||||
val stat: Int,
|
||||
val statAmount: Int,
|
||||
val plusMinus: Int,
|
||||
val reserved: ByteArray,
|
||||
)
|
||||
|
||||
class PmtTool(
|
||||
val id: Int,
|
||||
val type: Int,
|
||||
val skin: Int,
|
||||
val teamPoints: Int,
|
||||
val amount: Int,
|
||||
val tech: Int,
|
||||
val cost: Int,
|
||||
val itemFlag: Int,
|
||||
val reserved: ByteArray,
|
||||
)
|
||||
|
||||
class PmtWeapon(
|
||||
val id: Int,
|
||||
val type: Int,
|
||||
val skin: Int,
|
||||
val teamPoints: Int,
|
||||
val weaponClass: Int,
|
||||
val reserved1: Int,
|
||||
val minAtp: Int,
|
||||
val maxAtp: Int,
|
||||
val reqAtp: Int,
|
||||
val reqMst: Int,
|
||||
val reqAta: Int,
|
||||
val mst: Int,
|
||||
val maxGrind: Int,
|
||||
val photon: Int,
|
||||
val special: Int,
|
||||
val ata: Int,
|
||||
val statBoost: Int,
|
||||
val projectile: Int,
|
||||
val photonTrail1x: Int,
|
||||
val photonTrail1y: Int,
|
||||
val photonTrail2x: Int,
|
||||
val photonTrail2y: Int,
|
||||
val photonType: Int,
|
||||
val unknown1: ByteArray,
|
||||
val techBoost: Int,
|
||||
val comboType: Int,
|
||||
)
|
||||
|
||||
fun parseItemPmt(cursor: Cursor): ItemPmt {
|
||||
val index = parseRel(cursor, parseIndex = true).index
|
||||
|
||||
// This size (65268) of this table seems wrong, so we pass in a hard-coded value.
|
||||
val statBoosts = parseStatBoosts(cursor, index[305].offset, 52)
|
||||
val frames = parseFrames(cursor, index[7].offset, index[7].size)
|
||||
val barriers = parseFrames(cursor, index[8].offset, index[8].size)
|
||||
val units = parseUnits(cursor, index[9].offset, index[9].size)
|
||||
val tools = mutableListOf<List<PmtTool>>()
|
||||
val weapons = mutableListOf<List<PmtWeapon>>()
|
||||
|
||||
for (i in 11..37) {
|
||||
tools.add(parseTools(cursor, index[i].offset, index[i].size))
|
||||
}
|
||||
|
||||
for (i in 38..275) {
|
||||
weapons.add(parseWeapons(cursor, index[i].offset, index[i].size))
|
||||
}
|
||||
|
||||
return ItemPmt(
|
||||
statBoosts,
|
||||
frames,
|
||||
barriers,
|
||||
units,
|
||||
tools,
|
||||
weapons,
|
||||
)
|
||||
}
|
||||
|
||||
private fun parseStatBoosts(cursor: Cursor, offset: Int, size: Int): List<PmtStatBoost> {
|
||||
cursor.seekStart(offset)
|
||||
|
||||
val statBoosts = mutableListOf<PmtStatBoost>()
|
||||
|
||||
repeat(size) {
|
||||
statBoosts.add(PmtStatBoost(
|
||||
stat1 = cursor.uByte().toInt(),
|
||||
stat2 = cursor.uByte().toInt(),
|
||||
amount1 = cursor.short().toInt(),
|
||||
amount2 = cursor.short().toInt(),
|
||||
))
|
||||
}
|
||||
|
||||
return statBoosts
|
||||
}
|
||||
|
||||
private fun parseFrames(cursor: Cursor, offset: Int, size: Int): List<PmtFrame> {
|
||||
cursor.seekStart(offset)
|
||||
|
||||
val frames = mutableListOf<PmtFrame>()
|
||||
|
||||
repeat(size) {
|
||||
frames.add(PmtFrame(
|
||||
id = cursor.int(),
|
||||
type = cursor.short().toInt(),
|
||||
skin = cursor.short().toInt(),
|
||||
teamPoints = cursor.int(),
|
||||
dfp = cursor.short().toInt(),
|
||||
evp = cursor.short().toInt(),
|
||||
blockParticle = cursor.uByte().toInt(),
|
||||
blockEffect = cursor.uByte().toInt(),
|
||||
frameClass = cursor.uByte().toInt(),
|
||||
reserved1 = cursor.uByte().toInt(),
|
||||
requiredLevel = cursor.uByte().toInt(),
|
||||
efr = cursor.uByte().toInt(),
|
||||
eth = cursor.uByte().toInt(),
|
||||
eic = cursor.uByte().toInt(),
|
||||
edk = cursor.uByte().toInt(),
|
||||
elt = cursor.uByte().toInt(),
|
||||
dfpRange = cursor.uByte().toInt(),
|
||||
evpRange = cursor.uByte().toInt(),
|
||||
statBoost = cursor.uByte().toInt(),
|
||||
techBoost = cursor.uByte().toInt(),
|
||||
unknown1 = cursor.short().toInt(),
|
||||
))
|
||||
}
|
||||
|
||||
return frames
|
||||
}
|
||||
|
||||
private fun parseUnits(cursor: Cursor, offset: Int, size: Int): List<PmtUnit> {
|
||||
cursor.seekStart(offset)
|
||||
|
||||
val units = mutableListOf<PmtUnit>()
|
||||
|
||||
repeat(size) {
|
||||
units.add(PmtUnit(
|
||||
id = cursor.int(),
|
||||
type = cursor.short().toInt(),
|
||||
skin = cursor.short().toInt(),
|
||||
teamPoints = cursor.int(),
|
||||
stat = cursor.short().toInt(),
|
||||
statAmount = cursor.short().toInt(),
|
||||
plusMinus = cursor.uByte().toInt(),
|
||||
reserved = cursor.byteArray(3),
|
||||
))
|
||||
}
|
||||
|
||||
return units
|
||||
}
|
||||
|
||||
private fun parseTools(cursor: Cursor, offset: Int, size: Int): List<PmtTool> {
|
||||
cursor.seekStart(offset)
|
||||
|
||||
val tools = mutableListOf<PmtTool>()
|
||||
|
||||
repeat(size) {
|
||||
tools.add(PmtTool(
|
||||
id = cursor.int(),
|
||||
type = cursor.short().toInt(),
|
||||
skin = cursor.short().toInt(),
|
||||
teamPoints = cursor.int(),
|
||||
amount = cursor.short().toInt(),
|
||||
tech = cursor.short().toInt(),
|
||||
cost = cursor.int(),
|
||||
itemFlag = cursor.uByte().toInt(),
|
||||
reserved = cursor.byteArray(3),
|
||||
))
|
||||
}
|
||||
|
||||
return tools
|
||||
}
|
||||
|
||||
private fun parseWeapons(cursor: Cursor, offset: Int, size: Int): List<PmtWeapon> {
|
||||
cursor.seekStart(offset)
|
||||
|
||||
val weapons = mutableListOf<PmtWeapon>()
|
||||
|
||||
repeat(size) {
|
||||
weapons.add(PmtWeapon(
|
||||
id = cursor.int(),
|
||||
type = cursor.short().toInt(),
|
||||
skin = cursor.short().toInt(),
|
||||
teamPoints = cursor.int(),
|
||||
weaponClass = cursor.uByte().toInt(),
|
||||
reserved1 = cursor.uByte().toInt(),
|
||||
minAtp = cursor.short().toInt(),
|
||||
maxAtp = cursor.short().toInt(),
|
||||
reqAtp = cursor.short().toInt(),
|
||||
reqMst = cursor.short().toInt(),
|
||||
reqAta = cursor.short().toInt(),
|
||||
mst = cursor.short().toInt(),
|
||||
maxGrind = cursor.uByte().toInt(),
|
||||
photon = cursor.byte().toInt(),
|
||||
special = cursor.uByte().toInt(),
|
||||
ata = cursor.uByte().toInt(),
|
||||
statBoost = cursor.uByte().toInt(),
|
||||
projectile = cursor.uByte().toInt(),
|
||||
photonTrail1x = cursor.byte().toInt(),
|
||||
photonTrail1y = cursor.byte().toInt(),
|
||||
photonTrail2x = cursor.byte().toInt(),
|
||||
photonTrail2y = cursor.byte().toInt(),
|
||||
photonType = cursor.byte().toInt(),
|
||||
unknown1 = cursor.byteArray(5),
|
||||
techBoost = cursor.uByte().toInt(),
|
||||
comboType = cursor.uByte().toInt(),
|
||||
))
|
||||
}
|
||||
|
||||
return weapons
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package world.phantasmal.lib.fileFormats
|
||||
|
||||
import world.phantasmal.lib.cursor.Cursor
|
||||
import kotlin.math.min
|
||||
|
||||
class Unitxt(val categories: List<List<String>>)
|
||||
|
||||
fun parseUnitxt(cursor: Cursor): Unitxt {
|
||||
val categoryCount = cursor.int()
|
||||
val entryCounts = cursor.intArray(categoryCount)
|
||||
|
||||
val categoryEntryOffsets: List<IntArray> = entryCounts.map { entryCount ->
|
||||
cursor.intArray(entryCount)
|
||||
}
|
||||
|
||||
val categories = categoryEntryOffsets.map { entryOffsets ->
|
||||
entryOffsets.map { entryOffset ->
|
||||
cursor.seekStart(entryOffset)
|
||||
cursor.stringUtf16(
|
||||
min(1024, cursor.bytesLeft),
|
||||
nullTerminated = true,
|
||||
dropRemaining = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return Unitxt(categories)
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package world.phantasmal.lib.fileFormats
|
||||
|
||||
import world.phantasmal.lib.test.LibTestSuite
|
||||
import world.phantasmal.lib.test.readFile
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class ItemPmtTests : LibTestSuite() {
|
||||
@Test
|
||||
fun parseBasicItemPmt() = testAsync {
|
||||
val itemPmt = parseItemPmt(readFile("/ItemPMT.bin"))
|
||||
|
||||
val saber = itemPmt.weapons[1][0]
|
||||
|
||||
assertEquals(177, saber.id)
|
||||
assertEquals(40, saber.minAtp)
|
||||
assertEquals(55, saber.maxAtp)
|
||||
assertEquals(30, saber.ata)
|
||||
assertEquals(35, saber.maxGrind)
|
||||
assertEquals(30, saber.reqAtp)
|
||||
}
|
||||
}
|
@ -2,6 +2,14 @@ plugins {
|
||||
kotlin("multiplatform")
|
||||
}
|
||||
|
||||
val jvmVersion: String by project.extra
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
kotlinOptions {
|
||||
jvmTarget = jvmVersion
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
js {
|
||||
browser {}
|
||||
|
@ -7,6 +7,7 @@ include(
|
||||
":test-utils",
|
||||
":web",
|
||||
":web:assembly-worker",
|
||||
":web:assets-generation",
|
||||
":web:shared",
|
||||
":webui"
|
||||
)
|
||||
|
@ -4,6 +4,14 @@ plugins {
|
||||
|
||||
val coroutinesVersion: String by project.ext
|
||||
|
||||
val jvmVersion: String by project.extra
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
kotlinOptions {
|
||||
jvmTarget = jvmVersion
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
js {
|
||||
browser {}
|
||||
|
@ -6,7 +6,7 @@ import world.phantasmal.lib.asm.dataFlowAnalysis.ControlFlowGraph
|
||||
import world.phantasmal.lib.asm.dataFlowAnalysis.getMapDesignations
|
||||
import world.phantasmal.lib.asm.dataFlowAnalysis.getStackValue
|
||||
import world.phantasmal.web.shared.*
|
||||
import world.phantasmal.web.shared.AssemblyProblem
|
||||
import world.phantasmal.web.shared.messages.*
|
||||
import kotlin.math.min
|
||||
import world.phantasmal.lib.asm.AssemblyProblem as AssemblerAssemblyProblem
|
||||
|
||||
|
27
web/assets-generation/build.gradle.kts
Normal file
27
web/assets-generation/build.gradle.kts
Normal file
@ -0,0 +1,27 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
|
||||
val jvmVersion: String by project.extra
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions {
|
||||
jvmTarget = jvmVersion
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":lib"))
|
||||
implementation(project(":web:shared"))
|
||||
}
|
||||
|
||||
tasks.register<JavaExec>("generateAssets") {
|
||||
val outputFile = File(buildDir, "generatedAssets")
|
||||
outputs.dir(outputFile)
|
||||
|
||||
classpath = sourceSets.main.get().runtimeClasspath
|
||||
main = "world.phantasmal.web.assetsGeneration.Main"
|
||||
args = listOf(outputFile.absolutePath)
|
||||
}
|
@ -0,0 +1,219 @@
|
||||
package world.phantasmal.web.assetsGeneration
|
||||
|
||||
import kotlinx.serialization.encodeToString
|
||||
import world.phantasmal.core.splice
|
||||
import world.phantasmal.lib.buffer.Buffer
|
||||
import world.phantasmal.lib.compression.prs.prsDecompress
|
||||
import world.phantasmal.lib.cursor.cursor
|
||||
import world.phantasmal.lib.fileFormats.ItemPmt
|
||||
import world.phantasmal.lib.fileFormats.parseItemPmt
|
||||
import world.phantasmal.lib.fileFormats.parseUnitxt
|
||||
import world.phantasmal.web.shared.JSON_FORMAT_PRETTY
|
||||
import world.phantasmal.web.shared.dto.*
|
||||
import java.io.File
|
||||
import java.util.Comparator.comparing
|
||||
|
||||
object Ephinea {
|
||||
/**
|
||||
* ItemPMT.bin and ItemPT.gsl comes from stock Tethealla. ItemPT.gsl is not used at the moment.
|
||||
* unitxt_j.prs comes from the Ephinea client.
|
||||
* TODO: manual fixes:
|
||||
* - Clio is equipable by HUnewearls
|
||||
* - Red Ring has a requirement of 180, not 108
|
||||
*/
|
||||
fun generateAssets(outputDir: File) {
|
||||
val items = loadItems(loadItemNames())
|
||||
|
||||
File(outputDir, "item_types.ephinea.json")
|
||||
.writeText(JSON_FORMAT_PRETTY.encodeToString(items))
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts item names from unitxt file.
|
||||
*/
|
||||
private fun loadItemNames(): List<String> {
|
||||
val unitxtBuffer =
|
||||
object {}::class.java.getResourceAsStream(
|
||||
"/ephinea/client/data/unitxt_j.prs"
|
||||
).use { Buffer.fromByteArray(it.readBytes()) }
|
||||
|
||||
val unitxt = parseUnitxt(prsDecompress(unitxtBuffer.cursor()).unwrap())
|
||||
|
||||
val itemNames = unitxt.categories[1].toMutableList()
|
||||
// Strip custom Ephinea items until we have the Ephinea ItemPMT.bin.
|
||||
itemNames.splice(177, 50, emptyList())
|
||||
itemNames.splice(639, 59, emptyList())
|
||||
|
||||
return itemNames
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads items from ItemPMT.
|
||||
*/
|
||||
private fun loadItems(itemNames: List<String>): List<ItemType> {
|
||||
val itemPmtBuffer =
|
||||
object {}::class.java.getResourceAsStream(
|
||||
"/ephinea/ship-config/param/ItemPMT.bin"
|
||||
).use { Buffer.fromByteArray(it.readBytes()) }
|
||||
|
||||
val itemPmt = parseItemPmt(itemPmtBuffer.cursor())
|
||||
val itemTypes = mutableListOf<ItemType>()
|
||||
val ids = mutableSetOf<Int>()
|
||||
|
||||
fun checkId(id: Int, type: String, name: String) {
|
||||
check(ids.add(id)) {
|
||||
"""Trying to add $type with ID $id ($name) but ID already exists."""
|
||||
}
|
||||
}
|
||||
|
||||
for ((categoryI, category) in itemPmt.weapons.withIndex()) {
|
||||
for ((i, weapon) in category.withIndex()) {
|
||||
val id = (categoryI shl 8) + i
|
||||
val name = itemNames[weapon.id]
|
||||
checkId(id, "weapon", name)
|
||||
|
||||
itemTypes.add(WeaponItemType(
|
||||
id,
|
||||
name,
|
||||
weapon.minAtp,
|
||||
weapon.maxAtp,
|
||||
weapon.ata,
|
||||
weapon.maxGrind,
|
||||
weapon.reqAtp,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
for ((i, frame) in itemPmt.frames.withIndex()) {
|
||||
val id = 0x10100 + i
|
||||
val name = itemNames[frame.id]
|
||||
checkId(id, "frame", name)
|
||||
|
||||
val stats = getStatBoosts(itemPmt, frame.statBoost)
|
||||
|
||||
itemTypes.add(FrameItemType(
|
||||
id,
|
||||
name,
|
||||
stats.atp,
|
||||
stats.ata,
|
||||
minEvp = frame.evp + stats.minEvp,
|
||||
maxEvp = frame.evp + stats.minEvp + frame.evpRange,
|
||||
minDfp = frame.dfp + stats.minDfp,
|
||||
maxDfp = frame.dfp + stats.minDfp + frame.dfpRange,
|
||||
stats.mst,
|
||||
stats.hp,
|
||||
stats.lck,
|
||||
))
|
||||
}
|
||||
|
||||
for ((i, barrier) in itemPmt.barriers.withIndex()) {
|
||||
val id = 0x10200 + i
|
||||
val name = itemNames[barrier.id]
|
||||
checkId(id, "barrier", name)
|
||||
|
||||
val stats = getStatBoosts(itemPmt, barrier.statBoost)
|
||||
|
||||
itemTypes.add(BarrierItemType(
|
||||
id,
|
||||
name,
|
||||
stats.atp,
|
||||
stats.ata,
|
||||
minEvp = barrier.evp + stats.minEvp,
|
||||
maxEvp = barrier.evp + stats.minEvp + barrier.evpRange,
|
||||
minDfp = barrier.dfp + stats.minDfp,
|
||||
maxDfp = barrier.dfp + stats.minDfp + barrier.dfpRange,
|
||||
stats.mst,
|
||||
stats.hp,
|
||||
stats.lck,
|
||||
))
|
||||
}
|
||||
|
||||
for ((i, unit) in itemPmt.units.withIndex()) {
|
||||
val id = 0x10300 + i
|
||||
val name = itemNames[unit.id]
|
||||
checkId(id, "unit", name)
|
||||
|
||||
itemTypes.add(UnitItemType(
|
||||
id,
|
||||
name,
|
||||
))
|
||||
}
|
||||
|
||||
for ((categoryI, category) in itemPmt.tools.withIndex()) {
|
||||
for ((i, tool) in category.withIndex()) {
|
||||
val id = (0x30000 or (categoryI shl 8)) + i
|
||||
val name = itemNames[tool.id]
|
||||
checkId(id, "tool", name)
|
||||
|
||||
itemTypes.add(ToolItemType(
|
||||
id,
|
||||
name,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
itemTypes.sortWith(comparing({ it.name }, String.CASE_INSENSITIVE_ORDER))
|
||||
|
||||
return itemTypes
|
||||
}
|
||||
}
|
||||
|
||||
private class Boosts(
|
||||
val atp: Int,
|
||||
val ata: Int,
|
||||
val minEvp: Int,
|
||||
val minDfp: Int,
|
||||
val mst: Int,
|
||||
val hp: Int,
|
||||
val lck: Int,
|
||||
)
|
||||
|
||||
private fun getStatBoosts(itemPmt: ItemPmt, index: Int): Boosts {
|
||||
val statBoosts = itemPmt.statBoosts[index]
|
||||
val amount = statBoosts.amount1
|
||||
|
||||
var atp = 0
|
||||
var ata = 0
|
||||
var minEvp = 0
|
||||
var minDfp = 0
|
||||
var mst = 0
|
||||
var hp = 0
|
||||
var lck = 0
|
||||
|
||||
when (statBoosts.stat1) {
|
||||
1 -> atp += amount
|
||||
2 -> ata += amount
|
||||
3 -> minEvp += amount
|
||||
4 -> minDfp += amount
|
||||
5 -> mst += amount
|
||||
6 -> hp += amount
|
||||
7 -> lck += amount
|
||||
8 -> {
|
||||
atp += amount
|
||||
ata += amount
|
||||
minEvp += amount
|
||||
minDfp += amount
|
||||
mst += amount
|
||||
hp += amount
|
||||
lck += amount
|
||||
}
|
||||
9 -> atp -= amount
|
||||
10 -> ata -= amount
|
||||
11 -> minEvp -= amount
|
||||
12 -> minDfp -= amount
|
||||
13 -> mst -= amount
|
||||
14 -> hp -= amount
|
||||
15 -> lck -= amount
|
||||
16 -> {
|
||||
atp -= amount
|
||||
ata -= amount
|
||||
minEvp -= amount
|
||||
minDfp -= amount
|
||||
mst -= amount
|
||||
hp -= amount
|
||||
lck -= amount
|
||||
}
|
||||
}
|
||||
|
||||
return Boosts(atp, ata, minEvp, minDfp, mst, hp, lck)
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package world.phantasmal.web.assetsGeneration
|
||||
|
||||
import java.io.File
|
||||
|
||||
object Main {
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
require(args.isNotEmpty()) {
|
||||
"Expected at least one argument denoting the directory where assets should be generated."
|
||||
}
|
||||
|
||||
val outputDir = File(args.first())
|
||||
outputDir.mkdirs()
|
||||
|
||||
Ephinea.generateAssets(outputDir)
|
||||
}
|
||||
}
|
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user