mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-15 04:54:05 +09:00
item throwing sounds and better linter
This commit is contained in:
BIN
assets/mods/basegame/audio/effects/throwing/throw_low_short.wav
Normal file
BIN
assets/mods/basegame/audio/effects/throwing/throw_low_short.wav
Normal file
Binary file not shown.
@@ -8,16 +8,11 @@ import kotlin.system.exitProcess
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-05-22.
|
* Created by minjaesong on 2023-05-22.
|
||||||
*/
|
*/
|
||||||
fun main() {
|
class QuickDirtyLint {
|
||||||
|
private val csiBold = "\u001B[1m"
|
||||||
val csiR = "\u001B[31m"
|
private val csiR = "\u001B[31m"
|
||||||
val csiG = "\u001B[32m"
|
private val csiG = "\u001B[32m"
|
||||||
val csi0 = "\u001B[m"
|
private val csi0 = "\u001B[m"
|
||||||
|
|
||||||
val superClasses = listOf(
|
|
||||||
Actor::class.java,
|
|
||||||
GameItem::class.java
|
|
||||||
)
|
|
||||||
|
|
||||||
val serialisablePrimitives = listOf(
|
val serialisablePrimitives = listOf(
|
||||||
// comparison: exact match
|
// comparison: exact match
|
||||||
@@ -101,37 +96,102 @@ fun main() {
|
|||||||
"Ljava/util/List" to "java.util.List has no zero-arg constructor."
|
"Ljava/util/List" to "java.util.List has no zero-arg constructor."
|
||||||
)
|
)
|
||||||
|
|
||||||
var retcode = 0
|
val classGraph = ClassGraph().acceptPackages("net.torvald.terrarum")/*.verbose()*/.enableAllInfo().scan()
|
||||||
|
|
||||||
ClassGraph().acceptPackages("net.torvald.terrarum")/*.verbose()*/.enableAllInfo().scan().let { scan ->
|
fun checkForNonSerialisableFields(): Int {
|
||||||
val offendingFields = scan.allClasses.filter { classinfo ->
|
val superClasses = listOf(
|
||||||
superClasses.any { classinfo.extendsSuperclass(it) || classinfo.name == it.canonicalName } &&
|
Actor::class.java,
|
||||||
!classaNonGrata.contains(classinfo.name)
|
GameItem::class.java
|
||||||
}.flatMap { clazz ->
|
)
|
||||||
clazz.declaredFieldInfo.filter { field ->
|
|
||||||
!field.isTransient &&
|
var retcode = 0
|
||||||
!field.isEnum &&
|
|
||||||
!serialisablePrimitives.contains(field.typeSignatureOrTypeDescriptorStr) &&
|
classGraph.let { scan ->
|
||||||
serialisableTypes.none { field.typeSignatureOrTypeDescriptorStr.startsWith(it) }
|
val offendingFields = scan.allClasses.filter { classinfo ->
|
||||||
|
superClasses.any { classinfo.extendsSuperclass(it) || classinfo.name == it.canonicalName } &&
|
||||||
|
!classaNonGrata.contains(classinfo.name)
|
||||||
|
}.flatMap { clazz ->
|
||||||
|
clazz.declaredFieldInfo.filter { field ->
|
||||||
|
!field.isTransient &&
|
||||||
|
!field.isEnum &&
|
||||||
|
!serialisablePrimitives.contains(field.typeSignatureOrTypeDescriptorStr) &&
|
||||||
|
serialisableTypes.none { field.typeSignatureOrTypeDescriptorStr.startsWith(it) }
|
||||||
|
}
|
||||||
|
}.filter {
|
||||||
|
!classaNomenNonGrata.contains(it.name) && !it.name.startsWith("this") && !it.name.contains("\$delegate")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offendingFields.isNotEmpty()) {
|
||||||
|
println("$csiBold$csiR= Classes with non-@Transient fields =$csi0\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
offendingFields.forEach {
|
||||||
|
println("$csiBold${it.name}$csi0\n" +
|
||||||
|
"\t${csiG}from: ${csi0}${it.className}\n" +
|
||||||
|
"\t${csiG}type: ${csi0}${it.typeSignatureOrTypeDescriptorStr}\n" +
|
||||||
|
"\t${csiG}remarks: ${csi0}${
|
||||||
|
remarks.keys.filter { key ->
|
||||||
|
it.typeSignatureOrTypeDescriptorStr.startsWith(
|
||||||
|
key
|
||||||
|
)
|
||||||
|
}.map { remarks[it] }.joinToString(" ")
|
||||||
|
}"
|
||||||
|
)
|
||||||
|
retcode = 1
|
||||||
}
|
}
|
||||||
}.filter {
|
|
||||||
!classaNomenNonGrata.contains(it.name) && !it.name.startsWith("this") && !it.name.contains("\$delegate")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// println(offendingFields)
|
if (retcode != 0) {
|
||||||
|
println("\n${csiR}Having above classes as non-@Transient may cause savegame to not load!$csi0")
|
||||||
offendingFields.forEach {
|
|
||||||
println("\u001B[1m${it.name}\u001B[m\n" +
|
|
||||||
"\t${csiG}from: ${csi0}${it.className}\n" +
|
|
||||||
"\t${csiG}type: ${csi0}${it.typeSignatureOrTypeDescriptorStr}\n" +
|
|
||||||
"\t${csiG}remarks: ${csi0}${remarks.keys.filter { key -> it.typeSignatureOrTypeDescriptorStr.startsWith(key) }.map { remarks[it] }.joinToString(" ")}")
|
|
||||||
retcode = 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return retcode
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retcode != 0) {
|
fun checkForNoZeroArgConstructor(): Int {
|
||||||
println("\n${csiR}Having above classes as non-@Transient may cause savegame to not load!$csi0")
|
val superClasses = listOf(
|
||||||
|
Actor::class.java
|
||||||
|
)
|
||||||
|
|
||||||
|
var retcode = 0
|
||||||
|
|
||||||
|
classGraph.let { scan ->
|
||||||
|
val offendingClasses = scan.allClasses.filter { classinfo ->
|
||||||
|
superClasses.any { classinfo.extendsSuperclass(it) || classinfo.name == it.canonicalName } &&
|
||||||
|
!classaNonGrata.contains(classinfo.name)
|
||||||
|
}.filter {
|
||||||
|
!classaNomenNonGrata.contains(it.name) && !it.name.startsWith("this") && !it.name.contains("\$delegate") &&
|
||||||
|
!it.name.endsWith("$1") && !it.name.endsWith("$2") && !it.name.endsWith("$3") &&
|
||||||
|
!it.name.endsWith("$4") && !it.name.endsWith("$5") && !it.name.endsWith("$6")
|
||||||
|
}.filter {
|
||||||
|
it.declaredConstructorInfo.none { it.parameterInfo.isEmpty() }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offendingClasses.isNotEmpty()) {
|
||||||
|
println("$csiBold$csiR= Classes with no-zero-arg constructors =$csi0\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
offendingClasses.forEach {
|
||||||
|
println("$csiBold${it.name}$csi0\n")
|
||||||
|
retcode = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retcode != 0) {
|
||||||
|
println("\n${csiR}Having no zero-arg constructors for above classes will cause savegame to not load!$csi0")
|
||||||
|
}
|
||||||
|
|
||||||
|
return retcode
|
||||||
}
|
}
|
||||||
|
|
||||||
exitProcess(retcode)
|
fun main() {
|
||||||
|
val nonSerialisable = checkForNonSerialisableFields()
|
||||||
|
val noZeroArgConstructor = checkForNoZeroArgConstructor()
|
||||||
|
|
||||||
|
exitProcess(nonSerialisable or noZeroArgConstructor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
QuickDirtyLint().main()
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ abstract class AudioBank : Disposable {
|
|||||||
|
|
||||||
abstract val name: String
|
abstract val name: String
|
||||||
|
|
||||||
abstract val samplingRate: Int
|
abstract val samplingRate: Float
|
||||||
abstract val channels: Int
|
abstract val channels: Int
|
||||||
abstract val totalSizeInSamples: Long
|
abstract val totalSizeInSamples: Long
|
||||||
abstract fun currentPositionInSamples(): Long
|
abstract fun currentPositionInSamples(): Long
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.jme3.math.FastMath
|
|||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE
|
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE
|
||||||
|
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATEF
|
||||||
import net.torvald.terrarum.ceilToInt
|
import net.torvald.terrarum.ceilToInt
|
||||||
import net.torvald.terrarum.floorToInt
|
import net.torvald.terrarum.floorToInt
|
||||||
import net.torvald.terrarum.serialise.toUint
|
import net.torvald.terrarum.serialise.toUint
|
||||||
@@ -25,7 +26,7 @@ private data class Frac(var nom: Int, val denom: Int) {
|
|||||||
*
|
*
|
||||||
* Created by minjaesong on 2023-11-17.
|
* Created by minjaesong on 2023-11-17.
|
||||||
*/
|
*/
|
||||||
class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (FloatArray, FloatArray) -> Int?, val onAudioFinished: () -> Unit) {
|
class AudioProcessBuf(val inputSamplingRate: Float, val audioReadFun: (FloatArray, FloatArray) -> Int?, val onAudioFinished: () -> Unit) {
|
||||||
|
|
||||||
var pitch: Float = 1f
|
var pitch: Float = 1f
|
||||||
var playbackSpeed = 1f
|
var playbackSpeed = 1f
|
||||||
@@ -48,6 +49,10 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (FloatArray,
|
|||||||
else 1f / (1f - this)
|
else 1f / (1f - this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PlayRate is varying value for simulation of Doppler Shift, etc., if all you want is to just change
|
||||||
|
* the pitch of the entire audio, override the sampling rate of the [MusicContainer].
|
||||||
|
*/
|
||||||
internal val playRate: Float
|
internal val playRate: Float
|
||||||
get() = (playbackSpeed * pitch).coerceIn(0.5f, 2f)/*(playbackSpeed * when (jitterMode) { // disabled until arraycopy negative length bug is resolved
|
get() = (playbackSpeed * pitch).coerceIn(0.5f, 2f)/*(playbackSpeed * when (jitterMode) { // disabled until arraycopy negative length bug is resolved
|
||||||
1 -> jitterMode1(totalSamplesPlayed.toFloat())
|
1 -> jitterMode1(totalSamplesPlayed.toFloat())
|
||||||
@@ -58,7 +63,7 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (FloatArray,
|
|||||||
get() = inputSamplingRate * playRate
|
get() = inputSamplingRate * playRate
|
||||||
|
|
||||||
private val doResample
|
private val doResample
|
||||||
get() = !(inputSamplingRate == SAMPLING_RATE && (playRate - 1f).absoluteValue < (1f / 1024f))
|
get() = !(inputSamplingRate == SAMPLING_RATEF && (playRate - 1f).absoluteValue < (1f / 1024f))
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val RPM = 45f
|
private val RPM = 45f
|
||||||
@@ -90,6 +95,8 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (FloatArray,
|
|||||||
|
|
||||||
private val bufLut = HashMap<Pair<Int, Int>, Int>()
|
private val bufLut = HashMap<Pair<Int, Int>, Int>()
|
||||||
|
|
||||||
|
private val bufferRates = arrayOf(48000,44100,32768,32000,24000,22050,16384,16000,12000,11025,8192,8000)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val bl = arrayOf(
|
val bl = arrayOf(
|
||||||
1152,1380,1814,1792,2304,2634,3502,3456,4608,5141,6874,6912,
|
1152,1380,1814,1792,2304,2634,3502,3456,4608,5141,6874,6912,
|
||||||
@@ -99,14 +106,17 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (FloatArray,
|
|||||||
4096,4554,5421,5376,6144,7056,8796,8704,10240,12078,15544,15360
|
4096,4554,5421,5376,6144,7056,8796,8704,10240,12078,15544,15360
|
||||||
)
|
)
|
||||||
|
|
||||||
arrayOf(48000,44100,32768,32000,24000,22050,16384,16000,12000,11025,8192,8000).forEachIndexed { ri, r ->
|
bufferRates.forEachIndexed { ri, r ->
|
||||||
arrayOf(128,256,512,1024,2048).forEachIndexed { bi, b ->
|
arrayOf(128,256,512,1024,2048).forEachIndexed { bi, b ->
|
||||||
bufLut[b to r] = bl[bi * 12 + ri] * 2
|
bufLut[b to r] = (bl[bi * 12 + ri] * 1.05).ceilToInt() * 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOptimalBufferSize(rate: Int) = bufLut[App.audioBufferSize to rate]!!
|
private fun getOptimalBufferSize(rate: Float): Int {
|
||||||
|
val validRate = bufferRates.map { (rate - it) to it }.first { it.first >= 0 }.second
|
||||||
|
return bufLut[App.audioBufferSize to validRate]!!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val q
|
private val q
|
||||||
@@ -146,8 +156,8 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (FloatArray,
|
|||||||
|
|
||||||
private val finL = FloatArray(fetchSize + 2 * PADSIZE)
|
private val finL = FloatArray(fetchSize + 2 * PADSIZE)
|
||||||
private val finR = FloatArray(fetchSize + 2 * PADSIZE)
|
private val finR = FloatArray(fetchSize + 2 * PADSIZE)
|
||||||
private val fmidL = FloatArray((fetchSize * 2 + 1.0).toInt())
|
private val fmidL = FloatArray(fetchSize * 4)
|
||||||
private val fmidR = FloatArray((fetchSize * 2 + 1.0).toInt())
|
private val fmidR = FloatArray(fetchSize * 4)
|
||||||
private val foutL = FloatArray(internalBufferSize) // 640 for (44100, 48000), 512 for (48000, 48000) with BUFFER_SIZE = 512 * 4
|
private val foutL = FloatArray(internalBufferSize) // 640 for (44100, 48000), 512 for (48000, 48000) with BUFFER_SIZE = 512 * 4
|
||||||
private val foutR = FloatArray(internalBufferSize) // 640 for (44100, 48000), 512 for (48000, 48000) with BUFFER_SIZE = 512 * 4
|
private val foutR = FloatArray(internalBufferSize) // 640 for (44100, 48000), 512 for (48000, 48000) with BUFFER_SIZE = 512 * 4
|
||||||
private val readBufL = FloatArray(fetchSize)
|
private val readBufL = FloatArray(fetchSize)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import net.torvald.reflection.forceInvoke
|
|||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.audio.AudioBank
|
import net.torvald.terrarum.audio.AudioBank
|
||||||
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack
|
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack
|
||||||
|
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATEF
|
||||||
import net.torvald.terrarum.serialise.toUint
|
import net.torvald.terrarum.serialise.toUint
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
import net.torvald.unsafe.UnsafeHelper
|
||||||
import net.torvald.unsafe.UnsafePtr
|
import net.torvald.unsafe.UnsafePtr
|
||||||
@@ -26,12 +27,36 @@ class MusicContainer(
|
|||||||
val file: File,
|
val file: File,
|
||||||
val looping: Boolean = false,
|
val looping: Boolean = false,
|
||||||
val toRAM: Boolean = false,
|
val toRAM: Boolean = false,
|
||||||
|
val samplingRateOverride: Float?, // this is FIXED sampling rate
|
||||||
override var songFinishedHook: (AudioBank) -> Unit = {}
|
override var songFinishedHook: (AudioBank) -> Unit = {}
|
||||||
): AudioBank() {
|
): AudioBank() {
|
||||||
override val samplingRate: Int
|
override val samplingRate: Float
|
||||||
override val channels: Int
|
override val channels: Int
|
||||||
val codec: String
|
val codec: String
|
||||||
|
|
||||||
|
// make Java code shorter
|
||||||
|
constructor(
|
||||||
|
name: String,
|
||||||
|
file: File,
|
||||||
|
looping: Boolean = false,
|
||||||
|
toRAM: Boolean = false,
|
||||||
|
songFinishedHook: (AudioBank) -> Unit = {}
|
||||||
|
) : this(name, file, looping, toRAM, null, songFinishedHook)
|
||||||
|
// make Java code shorter
|
||||||
|
constructor(
|
||||||
|
name: String,
|
||||||
|
file: File,
|
||||||
|
looping: Boolean = false,
|
||||||
|
songFinishedHook: (AudioBank) -> Unit = {}
|
||||||
|
) : this(name, file, looping, false, null, songFinishedHook)
|
||||||
|
// make Java code shorter
|
||||||
|
constructor(
|
||||||
|
name: String,
|
||||||
|
file: File,
|
||||||
|
songFinishedHook: (AudioBank) -> Unit = {}
|
||||||
|
) : this(name, file, false, false, null, songFinishedHook)
|
||||||
|
|
||||||
|
|
||||||
var samplesReadCount = 0L; internal set
|
var samplesReadCount = 0L; internal set
|
||||||
override val totalSizeInSamples: Long
|
override val totalSizeInSamples: Long
|
||||||
private val totalSizeInBytes: Long
|
private val totalSizeInBytes: Long
|
||||||
@@ -55,18 +80,18 @@ class MusicContainer(
|
|||||||
|
|
||||||
bytesPerSample = 2 * channels
|
bytesPerSample = 2 * channels
|
||||||
|
|
||||||
samplingRate = when (gdxMusic) {
|
samplingRate = samplingRateOverride ?: when (gdxMusic) {
|
||||||
is Wav.Music -> {
|
is Wav.Music -> {
|
||||||
val rate = gdxMusic.extortField<Wav.WavInputStream>("input")!!.sampleRate
|
val rate = gdxMusic.extortField<Wav.WavInputStream>("input")!!.sampleRate
|
||||||
|
|
||||||
// App.printdbg(this, "music $name is WAV; rate = $rate")
|
// App.printdbg(this, "music $name is WAV; rate = $rate")
|
||||||
rate
|
rate.toFloat()
|
||||||
}
|
}
|
||||||
is Ogg.Music -> {
|
is Ogg.Music -> {
|
||||||
val rate = gdxMusic.extortField<OggInputStream>("input")!!.sampleRate
|
val rate = gdxMusic.extortField<OggInputStream>("input")!!.sampleRate
|
||||||
|
|
||||||
// App.printdbg(this, "music $name is OGG; rate = $rate")
|
// App.printdbg(this, "music $name is OGG; rate = $rate")
|
||||||
rate
|
rate.toFloat()
|
||||||
}
|
}
|
||||||
is Mp3.Music -> {
|
is Mp3.Music -> {
|
||||||
val tempMusic = Gdx.audio.newMusic(Gdx.files.absolute(file.absolutePath))
|
val tempMusic = Gdx.audio.newMusic(Gdx.files.absolute(file.absolutePath))
|
||||||
@@ -81,11 +106,11 @@ class MusicContainer(
|
|||||||
// gdxMusic.reset()
|
// gdxMusic.reset()
|
||||||
|
|
||||||
// App.printdbg(this, "music $name is MP3; rate = $rate")
|
// App.printdbg(this, "music $name is MP3; rate = $rate")
|
||||||
rate
|
rate.toFloat()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
// App.printdbg(this, "music $name is ${gdxMusic::class.qualifiedName}; rate = default")
|
// App.printdbg(this, "music $name is ${gdxMusic::class.qualifiedName}; rate = default")
|
||||||
TerrarumAudioMixerTrack.SAMPLING_RATE
|
TerrarumAudioMixerTrack.SAMPLING_RATEF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +340,7 @@ class MusicContainer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun makeCopy(): AudioBank {
|
override fun makeCopy(): AudioBank {
|
||||||
val new = MusicContainer(name, file, looping, false, songFinishedHook)
|
val new = MusicContainer(name, file, looping, false, samplingRateOverride, songFinishedHook)
|
||||||
|
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if (this.toRAM) {
|
if (this.toRAM) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {})
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val name = "spieluhr"
|
override val name = "spieluhr"
|
||||||
override val samplingRate = 48000 // 122880 // use 122880 to make each tick is 2048 samples
|
override val samplingRate = 48000f // 122880 // use 122880 to make each tick is 2048 samples
|
||||||
override val channels = 1
|
override val channels = 1
|
||||||
|
|
||||||
private val getSample = // usage: getSample(noteNum 0..60)
|
private val getSample = // usage: getSample(noteNum 0..60)
|
||||||
|
|||||||
@@ -16,29 +16,46 @@ import kotlin.math.log10
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2024-07-12.
|
* Created by minjaesong on 2024-07-12.
|
||||||
*/
|
*/
|
||||||
open class ActorLobbed : ActorWithBody()
|
open class ActorLobbed(throwPitch: Float) : ActorWithBody() {
|
||||||
|
|
||||||
|
protected constructor() : this(1f)
|
||||||
|
|
||||||
|
@Transient private val whooshSound = MusicContainer(
|
||||||
|
"throw_low_short", ModMgr.getFile("basegame", "audio/effects/throwing/throw_low_short.wav"),
|
||||||
|
toRAM = true,
|
||||||
|
samplingRateOverride = 48000f * throwPitch.coerceIn(0.5f, 2f)
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
renderOrder = RenderOrder.FRONT
|
||||||
|
physProp = PhysProperties.PHYSICS_OBJECT()
|
||||||
|
elasticity = 0.34
|
||||||
|
}
|
||||||
|
|
||||||
|
private var soundFired = false
|
||||||
|
|
||||||
|
override fun updateImpl(delta: Float) {
|
||||||
|
super.updateImpl(delta)
|
||||||
|
if (!soundFired) {
|
||||||
|
soundFired = true
|
||||||
|
startAudio(whooshSound, 1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2024-02-13.
|
* Created by minjaesong on 2024-02-13.
|
||||||
*/
|
*/
|
||||||
open class ActorPrimedBomb(
|
open class ActorPrimedBomb(
|
||||||
|
throwPitch: Float,
|
||||||
@Transient private var explosionPower: Float = 1f,
|
@Transient private var explosionPower: Float = 1f,
|
||||||
private var fuse: Second = 1f,
|
private var fuse: Second = 1f,
|
||||||
@Transient private var dropProbNonOre: Float = 0.25f,
|
@Transient private var dropProbNonOre: Float = 0.25f,
|
||||||
@Transient private var dropProbOre: Float = 0.75f
|
@Transient private var dropProbOre: Float = 0.75f
|
||||||
) : ActorLobbed() {
|
) : ActorLobbed(throwPitch) {
|
||||||
|
|
||||||
init {
|
protected constructor() : this(1f, 1f, 1f)
|
||||||
renderOrder = RenderOrder.MIDTOP
|
|
||||||
physProp = PhysProperties.PHYSICS_OBJECT()
|
|
||||||
elasticity = 0.34
|
|
||||||
}
|
|
||||||
|
|
||||||
protected constructor() : this(1f, 1f) {
|
|
||||||
renderOrder = RenderOrder.MIDTOP
|
|
||||||
physProp = PhysProperties.PHYSICS_OBJECT()
|
|
||||||
}
|
|
||||||
|
|
||||||
private var explosionCalled = false
|
private var explosionCalled = false
|
||||||
|
|
||||||
@@ -110,7 +127,10 @@ open class ActorPrimedBomb(
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2024-02-14.
|
* Created by minjaesong on 2024-02-14.
|
||||||
*/
|
*/
|
||||||
class ActorCherryBomb : ActorPrimedBomb(14f, 4.5f) { // 14 is the intended value; 32 is for testing
|
class ActorCherryBomb(throwPitch: Float) : ActorPrimedBomb(throwPitch, 14f, 4.5f) { // 14 is the intended value; 32 is for testing
|
||||||
|
|
||||||
|
private constructor() : this(1f)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val itemImage = CommonResourcePool.getAsItemSheet("basegame.items").get(0,13)
|
val itemImage = CommonResourcePool.getAsItemSheet("basegame.items").get(0,13)
|
||||||
|
|
||||||
@@ -126,7 +146,10 @@ class ActorCherryBomb : ActorPrimedBomb(14f, 4.5f) { // 14 is the intended value
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2024-07-12.
|
* Created by minjaesong on 2024-07-12.
|
||||||
*/
|
*/
|
||||||
class ActorGlowOrb : ActorLobbed() {
|
class ActorGlowOrb(throwPitch: Float) : ActorLobbed(throwPitch) {
|
||||||
|
|
||||||
|
private constructor() : this(1f)
|
||||||
|
|
||||||
val spawnTime = INGAME.world.worldTime.TIME_T
|
val spawnTime = INGAME.world.worldTime.TIME_T
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ open class Cultivable: FixtureBase {
|
|||||||
* Created by minjaesong on 2024-02-03.
|
* Created by minjaesong on 2024-02-03.
|
||||||
*/
|
*/
|
||||||
open class SaplingBase(val species: Int) : Cultivable(72000) {
|
open class SaplingBase(val species: Int) : Cultivable(72000) {
|
||||||
|
private constructor() : this(0)
|
||||||
|
|
||||||
private val variant = (0..3).random()
|
private val variant = (0..3).random()
|
||||||
init {
|
init {
|
||||||
CommonResourcePool.addToLoadingList("basegame/sprites/saplings.tga") {
|
CommonResourcePool.addToLoadingList("basegame/sprites/saplings.tga") {
|
||||||
|
|||||||
@@ -16,13 +16,17 @@ import org.dyn4j.geometry.Vector2
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2016-03-15.
|
* Created by minjaesong on 2016-03-15.
|
||||||
*/
|
*/
|
||||||
open class DroppedItem : ActorWithBody {
|
class DroppedItem : ActorWithBody {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val NO_PICKUP_TIME = 1f
|
const val NO_PICKUP_TIME = 1f
|
||||||
const val MERGER_RANGE = 8.0 * TILE_SIZED // the wanted distance, squared
|
const val MERGER_RANGE = 8.0 * TILE_SIZED // the wanted distance, squared
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
renderOrder = RenderOrder.FRONT
|
||||||
|
}
|
||||||
|
|
||||||
var itemID: ItemID = ""; private set
|
var itemID: ItemID = ""; private set
|
||||||
|
|
||||||
@Transient private var visualItemID = ""
|
@Transient private var visualItemID = ""
|
||||||
|
|||||||
@@ -33,7 +33,10 @@ open class ItemThrowable(originalID: ItemID, private val throwableActorClassName
|
|||||||
override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long = mouseInInteractableRange(actor) { mx, my, mtx, mty ->
|
override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long = mouseInInteractableRange(actor) { mx, my, mtx, mty ->
|
||||||
val (throwPos, throwForce) = getThrowPosAndVector(actor)
|
val (throwPos, throwForce) = getThrowPosAndVector(actor)
|
||||||
|
|
||||||
val lobbed = Class.forName(throwableActorClassName).getDeclaredConstructor().newInstance() as ActorWithBody
|
val magnRel = throwForce.magnitude / actor.avStrength * 1000.0
|
||||||
|
val pitch = (magnRel * 0.2).sqrt().toFloat()
|
||||||
|
|
||||||
|
val lobbed = Class.forName(throwableActorClassName).getDeclaredConstructor(pitch.javaClass).newInstance(pitch) as ActorWithBody
|
||||||
lobbed.setPositionFromCentrePoint(throwPos)
|
lobbed.setPositionFromCentrePoint(throwPos)
|
||||||
lobbed.externalV.set(throwForce)
|
lobbed.externalV.set(throwForce)
|
||||||
setupLobbedActor(lobbed)
|
setupLobbedActor(lobbed)
|
||||||
|
|||||||
Reference in New Issue
Block a user