actorwithbody splitted in favour of new particle type

Former-commit-id: 121bd069d0a9eeef60f5ecb085a11a93c4b4a84d
Former-commit-id: 539b4b6916e808c01298190cf347e928f61fe62e
This commit is contained in:
Song Minjae
2017-01-21 16:52:16 +09:00
parent c9d83455a9
commit 56a012d843
49 changed files with 752 additions and 428 deletions

View File

@@ -19,4 +19,14 @@ Colour overlay is set to 6 500 K as untouched. The value must be
## Sunlight ##
Sunlight of the midday must have colour temperature of 5 700 K.
Sunlight of the midday must have colour temperature of 5 700 K.
## Weather effects ##
* Wind
- Blows away sands/snows
- Tilts raindrops/snowfall
* Precipitation
- Rain, snow

View File

@@ -2,7 +2,7 @@ package net.torvald.aa
import net.torvald.point.Point2d
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithSprite
import net.torvald.terrarum.gameactors.sqr
import java.util.*
@@ -23,7 +23,7 @@ class KDHeapifiedTree() {
private val dimension = 2
private val initialSize = 128
private val nodes = Array<ActorWithBody?>(initialSize, { null })
private val nodes = Array<ActorWithSprite?>(initialSize, { null })
private val root: Int = 0
@@ -34,13 +34,13 @@ class KDHeapifiedTree() {
private fun Int.getActor() = nodes[this]
private fun Int.getLeft() = this * 2 + 1
private fun Int.getRight() = this * 2 + 2
private fun Int.set(value: ActorWithBody?) { nodes[this] = value }
private fun Int.setLeftChild(value: ActorWithBody?) { nodes[this.getLeft()] = value }
private fun Int.setRightChild(value: ActorWithBody?) { nodes[this.getRight()] = value }
private fun Int.set(value: ActorWithSprite?) { nodes[this] = value }
private fun Int.setLeftChild(value: ActorWithSprite?) { nodes[this.getLeft()] = value }
private fun Int.setRightChild(value: ActorWithSprite?) { nodes[this.getRight()] = value }
private val zeroPoint = Point2d(0.0, 0.0)
private fun create(points: List<ActorWithBody?>, depth: Int, index: Int): ActorWithBody? {
private fun create(points: List<ActorWithSprite?>, depth: Int, index: Int): ActorWithSprite? {
if (points.isEmpty()) {
index.set(null)
@@ -91,7 +91,7 @@ class KDHeapifiedTree() {
private fun expandArray() {
val prevNodes = nodes.copyOf()
Array<ActorWithBody?>(prevNodes.size * 2, { null })
Array<ActorWithSprite?>(prevNodes.size * 2, { null })
create(prevNodes.toList(), 0, 0)
}

View File

@@ -7,19 +7,15 @@ package net.torvald.spriteanimation
import net.torvald.terrarum.StateInGame
import net.torvald.terrarum.Terrarum
import com.jme3.math.FastMath
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithSprite
import org.newdawn.slick.Graphics
import org.newdawn.slick.Image
import org.newdawn.slick.SlickException
import org.newdawn.slick.SpriteSheet
class SpriteAnimation(val parentActor: ActorWithBody) {
class SpriteAnimation(val parentActor: ActorWithSprite, val cellWidth: Int, val cellHeight: Int) {
private var spriteImage: SpriteSheet? = null
var height: Int = 0
private set
var width: Int = 0
private set
private var currentFrame = 1 // one-based!
private var currentRow = 1 // one-based!
private var nFrames: Int = 1
@@ -47,11 +43,11 @@ class SpriteAnimation(val parentActor: ActorWithBody) {
* @throws SlickException
*/
fun setSpriteImage(imagePath: String) {
spriteImage = SpriteSheet(imagePath, this.width, this.height)
spriteImage = SpriteSheet(imagePath, cellWidth, cellHeight)
}
fun setSpriteImage(image: Image) {
spriteImage = SpriteSheet(image, this.width, this.height)
spriteImage = SpriteSheet(image, cellWidth, cellHeight)
}
/**
@@ -62,16 +58,6 @@ class SpriteAnimation(val parentActor: ActorWithBody) {
this.delay = delay
}
/**
* Sets sprite dimension. This is necessary for this to work.
* @param w width of the animation frame
* @param h height of the animation frame
*/
fun setDimension(w: Int, h: Int) {
width = w
height = h
}
/**
* Sets sheet rows and animation frames. Will default to
* 1, 1 (still image of top left from the sheet) if not called.
@@ -115,6 +101,10 @@ class SpriteAnimation(val parentActor: ActorWithBody) {
* @param scale
*/
@JvmOverloads fun render(g: Graphics, posX: Float, posY: Float, scale: Float = 1f) {
if (cellWidth == 0 || cellHeight == 0) {
throw Error("Sprite width or height is set to zero! ($cellWidth, $cellHeight); master: $parentActor")
}
// Null checking
if (currentImage == null) {
currentImage = getScaledSprite(scale)
@@ -131,8 +121,8 @@ class SpriteAnimation(val parentActor: ActorWithBody) {
flippedImage.draw(
Math.round(posX).toFloat(),
FastMath.floor(posY).toFloat(),
FastMath.floor(width * scale).toFloat(),
FastMath.floor(height * scale).toFloat()
FastMath.floor(cellWidth * scale).toFloat(),
FastMath.floor(cellHeight * scale).toFloat()
)
}
}

View File

@@ -24,6 +24,7 @@ import net.torvald.terrarum.mapdrawer.MapCamera
import net.torvald.terrarum.mapgenerator.WorldGenerator
import net.torvald.terrarum.mapgenerator.RoguelikeRandomiser
import net.torvald.terrarum.tileproperties.TileCodex
import net.torvald.terrarum.tileproperties.TilePropUtil
import net.torvald.terrarum.tilestats.TileStats
import net.torvald.terrarum.ui.*
import net.torvald.terrarum.weather.WeatherMixer
@@ -36,6 +37,8 @@ import org.newdawn.slick.state.StateBasedGame
import shader.Shader
import java.lang.management.ManagementFactory
import java.util.*
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
/**
* Created by minjaesong on 15-12-30.
@@ -56,10 +59,10 @@ constructor() : BasicGameState() {
val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
val uiContainer = ArrayList<UIHandler>()
private val actorsRenderBehind = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderMiddle = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderMidTop = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderFront = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderBehind = ArrayList<ActorVisible>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderMiddle = ArrayList<ActorVisible>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderMidTop = ArrayList<ActorVisible>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderFront = ArrayList<ActorVisible>(ACTORCONTAINER_INITIAL_SIZE)
lateinit var consoleHandler: UIHandler
lateinit var debugWindow: UIHandler
@@ -127,8 +130,6 @@ constructor() : BasicGameState() {
// add new player and put it to actorContainer
playableActorDelegate = PlayableActorDelegate(PlayerBuilderSigrid())
//player = PBCynthia.create()
//player.setNoClip(true);
addActor(player)
@@ -185,8 +186,9 @@ constructor() : BasicGameState() {
///////////////////////////
// world-related updates //
///////////////////////////
TilePropUtil.dynamicLumFuncTickClock()
world.updateWorldTime(delta)
WorldSimulator(world, player, delta)
WorldSimulator(player, delta)
WeatherMixer.update(gc, delta)
TileStats.update()
if (!(CommandDict["setgl"] as SetGlobalLightOverride).lightOverride)
@@ -255,9 +257,13 @@ constructor() : BasicGameState() {
private fun repossessActor() {
// check if currently pocessed actor is removed from game
if (!hasActor(player))
// re-possess canonical player
changePossession(Player.PLAYER_REF_ID) // TODO completely other behaviour?
if (!hasActor(player)) {
// re-possess canonical player
if (hasActor(Player.PLAYER_REF_ID))
changePossession(Player.PLAYER_REF_ID)
else
changePossession(0x51621D) // FIXME fallback debug mode (FIXME is there for a reminder visible in ya IDE)
}
}
private fun changePossession(newActor: PlayableActorDelegate) {
@@ -266,7 +272,7 @@ constructor() : BasicGameState() {
}
playableActorDelegate = newActor
WorldSimulator(world, player, UPDATE_DELTA)
WorldSimulator(player, UPDATE_DELTA)
}
private fun changePossession(refid: Int) {
@@ -280,8 +286,8 @@ constructor() : BasicGameState() {
playableActorDelegate!!.actor.collisionType = HumanoidNPC.DEFAULT_COLLISION_TYPE
// accept new delegate
playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid)
playableActorDelegate!!.actor.collisionType = ActorWithBody.COLLISION_KINEMATIC
WorldSimulator(world, player, UPDATE_DELTA)
playableActorDelegate!!.actor.collisionType = ActorWithSprite.COLLISION_KINEMATIC
WorldSimulator(player, UPDATE_DELTA)
}
private fun setAppTitle() {
@@ -325,7 +331,7 @@ constructor() : BasicGameState() {
actorsRenderMidTop.forEach { actor -> actor.drawBody(worldG) }
player.drawBody(worldG)
actorsRenderFront.forEach { actor -> actor.drawBody(worldG) }
// --> Change of blend mode <-- introduced by ActorWithBody //
// --> Change of blend mode <-- introduced by ActorVisible //
/////////////////////////////
@@ -352,7 +358,7 @@ constructor() : BasicGameState() {
actorsRenderMidTop.forEach { actor -> actor.drawGlow(worldG) }
player.drawGlow(worldG)
actorsRenderFront.forEach { actor -> actor.drawGlow(worldG) }
// --> blendLightenOnly() <-- introduced by ActorWithBody //
// --> blendLightenOnly() <-- introduced by ActorVisible //
////////////////////////
@@ -362,7 +368,7 @@ constructor() : BasicGameState() {
// draw reference ID if debugWindow is open
if (debugWindow.isVisible) {
actorContainer.forEachIndexed { i, actor ->
if (actor is ActorWithBody) {
if (actor is ActorVisible) {
worldG.color = Color.white
worldG.font = Terrarum.fontSmallNumbers
worldG.drawString(
@@ -401,6 +407,13 @@ constructor() : BasicGameState() {
/////////////////
gwin.drawImage(worldDrawFrameBuffer.getScaledCopy(screenZoom), 0f, 0f)
gwin.drawImage(uisDrawFrameBuffer, 0f, 0f)
// centre marker
/*gwin.color = Color(0x00FFFF)
gwin.lineWidth = 1f
gwin.drawLine(Terrarum.WIDTH / 2f, 0f, Terrarum.WIDTH / 2f, Terrarum.HEIGHT.toFloat())
gwin.drawLine(0f, Terrarum.HEIGHT / 2f, Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT / 2f)*/
}
override fun keyPressed(key: Int, c: Char) {
@@ -484,7 +497,7 @@ constructor() : BasicGameState() {
while (i < actorContainerSize) { // loop through actorContainerInactive
val actor = actorContainerInactive[i]
val actorIndex = i
if (actor is ActorWithBody && actor.inUpdateRange()) {
if (actor is ActorVisible && actor.inUpdateRange()) {
addActor(actor) // duplicates are checked here
actorContainerInactive.removeAt(actorIndex)
actorContainerSize -= 1
@@ -507,12 +520,12 @@ constructor() : BasicGameState() {
val actorIndex = i
// kill actors flagged to despawn
if (actor.flagDespawn) {
actorContainer.removeAt(actorIndex)
removeActor(actor)
actorContainerSize -= 1
i-- // array removed 1 elem, so we also decrement counter by 1
}
// inactivate distant actors
else if (actor is ActorWithBody && !actor.inUpdateRange()) {
else if (actor is ActorVisible && !actor.inUpdateRange()) {
if (actor !is Projectile) { // if it's a projectile, don't inactivate it; just kill it.
actorContainerInactive.add(actor) // naïve add; duplicates are checked when the actor is re-activated
}
@@ -559,7 +572,7 @@ constructor() : BasicGameState() {
d.forEach { if (it < ret) ret = it }
return ret
}
private fun distToActorSqr(a: ActorWithBody, p: ActorWithBody) =
private fun distToActorSqr(a: ActorVisible, p: ActorVisible) =
min(// take min of normal position and wrapped (x < 0) position
(a.hitbox.centeredX - p.hitbox.centeredX).sqr() +
(a.hitbox.centeredY - p.hitbox.centeredY).sqr(),
@@ -568,7 +581,7 @@ constructor() : BasicGameState() {
(a.hitbox.centeredX - p.hitbox.centeredX - world.width * TILE_SIZE).sqr() +
(a.hitbox.centeredY - p.hitbox.centeredY).sqr()
)
private fun distToCameraSqr(a: ActorWithBody) =
private fun distToCameraSqr(a: ActorVisible) =
min(
(a.hitbox.posX - MapCamera.x).sqr() +
(a.hitbox.posY - MapCamera.y).sqr(),
@@ -579,14 +592,14 @@ constructor() : BasicGameState() {
)
/** whether the actor is within screen */
private fun ActorWithBody.inScreen() =
private fun ActorVisible.inScreen() =
distToCameraSqr(this) <=
(Terrarum.WIDTH.plus(this.hitbox.width.div(2)).times(1 / Terrarum.ingame.screenZoom).sqr() +
Terrarum.HEIGHT.plus(this.hitbox.height.div(2)).times(1 / Terrarum.ingame.screenZoom).sqr())
/** whether the actor is within update range */
private fun ActorWithBody.inUpdateRange() = distToCameraSqr(this) <= ACTOR_UPDATE_RANGE.sqr()
private fun ActorVisible.inUpdateRange() = distToCameraSqr(this) <= ACTOR_UPDATE_RANGE.sqr()
/**
* actorContainer extensions
@@ -596,8 +609,21 @@ constructor() : BasicGameState() {
fun hasActor(ID: Int): Boolean =
if (actorContainer.size == 0)
false
else
actorContainer.binarySearch(ID) >= 0
else {
// TODO cherche for inactive
val binsearch = actorContainer.binarySearch(ID)
if (binsearch < 0) {
if (actorContainerInactive.size == 0) false
else {
val binsearch2 = actorContainerInactive.binarySearch(ID)
binsearch2 >= 0
}
}
else {
true
}
}
fun removeActor(ID: Int) = removeActor(getActorByID(ID))
/**
@@ -616,7 +642,7 @@ constructor() : BasicGameState() {
// indexToDelete >= 0 means that the actor certainly exists in the game
// which means we don't need to check if i >= 0 again
if (actor is ActorWithBody) {
if (actor is ActorVisible) {
when (actor.renderOrder) {
ActorOrder.BEHIND -> {
val i = actorsRenderBehind.binarySearch(actor.referenceID)
@@ -648,12 +674,12 @@ constructor() : BasicGameState() {
actorContainer.add(actor)
insertionSortLastElem(actorContainer) // we can do this as we are only adding single actor
if (actor is ActorWithBody) {
if (actor is ActorVisible) {
when (actor.renderOrder) {
ActorOrder.BEHIND -> actorsRenderBehind.add(actor)
ActorOrder.MIDDLE -> actorsRenderMiddle.add(actor)
ActorOrder.MIDTOP -> actorsRenderMidTop.add(actor)
ActorOrder.FRONT -> actorsRenderFront.add(actor)
ActorOrder.BEHIND -> { actorsRenderBehind.add(actor); insertionSortLastElemAV(actorsRenderBehind) }
ActorOrder.MIDDLE -> { actorsRenderMiddle.add(actor); insertionSortLastElemAV(actorsRenderMiddle) }
ActorOrder.MIDTOP -> { actorsRenderMidTop.add(actor); insertionSortLastElemAV(actorsRenderMidTop) }
ActorOrder.FRONT -> { actorsRenderFront .add(actor); insertionSortLastElemAV(actorsRenderFront ) }
}
}
}
@@ -681,15 +707,26 @@ constructor() : BasicGameState() {
}
private fun insertionSortLastElem(arr: ArrayList<Actor>) {
var j: Int
val index: Int = arr.size - 1
val x = arr[index]
j = index - 1
while (j > 0 && arr[j] > x) {
arr[j + 1] = arr[j]
j -= 1
lock(ReentrantLock()) {
var j = arr.lastIndex - 1
val x = arr.last()
while (j >= 0 && arr[j] > x) {
arr[j + 1] = arr[j]
j -= 1
}
arr[j + 1] = x
}
}
private fun insertionSortLastElemAV(arr: ArrayList<ActorVisible>) { // out-projection doesn't work, duh
lock(ReentrantLock()) {
var j = arr.lastIndex - 1
val x = arr.last()
while (j >= 0 && arr[j] > x) {
arr[j + 1] = arr[j]
j -= 1
}
arr[j + 1] = x
}
arr[j + 1] = x
}
private fun ArrayList<out Actor>.binarySearch(actor: Actor) = this.binarySearch(actor.referenceID)
@@ -712,6 +749,16 @@ constructor() : BasicGameState() {
}
return -(low + 1) // key not found
}
inline fun lock(lock: Lock, body: () -> Unit) {
lock.lock()
try {
body()
}
finally {
lock.unlock()
}
}
}
fun Color.toInt() = redByte.shl(16) or greenByte.shl(8) or blueByte

View File

@@ -55,6 +55,23 @@ class StateNoiseTexGen : BasicGameState() {
return Joise(ridged_autocorrect)
}
private fun noiseBrownianGranite(): Joise {
val ridged = ModuleFractal()
ridged.setType(ModuleFractal.FractalType.FBM)
ridged.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
ridged.setNumOctaves(2)
ridged.setFrequency(16.0)
ridged.seed = Random().nextLong()
val brownian_select = ModuleSelect()
brownian_select.setControlSource(ridged)
brownian_select.setThreshold(0.8)
brownian_select.setLowSource(0.0)
brownian_select.setHighSource(1.0)
return Joise(brownian_select)
}
private fun noiseBillowFractal(): Joise {
val ridged = ModuleFractal()
ridged.setType(ModuleFractal.FractalType.BILLOW)
@@ -70,19 +87,6 @@ class StateNoiseTexGen : BasicGameState() {
return Joise(ridged_autocorrect)
}
private fun noiseBlobs(): Joise {
val gradval = ModuleBasisFunction()
gradval.seed = Random().nextLong()
gradval.setType(ModuleBasisFunction.BasisType.GRADVAL)
gradval.setInterpolation(ModuleBasisFunction.InterpolationType.QUINTIC)
val gradval_autocorrect = ModuleAutoCorrect()
gradval_autocorrect.setRange(0.0, 1.0)
gradval_autocorrect.setSource(gradval)
return Joise(gradval_autocorrect)
}
private fun noiseSimplex(): Joise {
val simplex = ModuleFractal()
simplex.seed = Random().nextLong()
@@ -114,7 +118,7 @@ class StateNoiseTexGen : BasicGameState() {
}
fun generateNoiseImage() {
val noiseModule = noiseBrownian() // change noise function here
val noiseModule = noiseBrownianGranite() // change noise function here
for (y in 0..imagesize - 1) {
for (x in 0..imagesize - 1) {

View File

@@ -33,8 +33,16 @@ constructor(gamename: String) : StateBasedGame(gamename) {
var previousState: Int? = null // to be used with temporary states like StateMonitorCheck
val systemArch = System.getProperty("os.arch")
private val thirtyTwoBitArchs = arrayOf("i386", "i686", "ppc", "x86", "x86_32") // I know I should Write Once, Run Everywhere; but just in case :)
val is32Bit = thirtyTwoBitArchs.contains(systemArch)
init {
// just in case
println("[Terrarum] os.arch = $systemArch")
gameConfig = GameConfig()
joypadLabelStart = when (getConfigString("joypadlabelstyle")) {
@@ -67,7 +75,7 @@ constructor(gamename: String) : StateBasedGame(gamename) {
else
gameLocale = gameLocaleFromConfig
println("[terrarum] Locale: " + gameLocale)
println("[Terrarum] Locale: " + gameLocale)
try {
Controllers.getController(0)
@@ -127,6 +135,12 @@ constructor(gamename: String) : StateBasedGame(gamename) {
ingame = StateInGame()
addState(ingame)
// foolproof
if (stateCount < 1) {
throw Error("Please add or un-comment addState statements")
}
}
companion object {
@@ -158,16 +172,18 @@ constructor(gamename: String) : StateBasedGame(gamename) {
var HEIGHT = 742 // IMAX ratio
var VSYNC = true
val VSYNC_TRIGGER_THRESHOLD = 56
val HALFW: Int
get() = WIDTH.ushr(1)
val HALFH: Int
get() = HEIGHT.ushr(1)
var gameStarted = false
lateinit var ingame: StateInGame
lateinit var gameConfig: GameConfig
lateinit var OSName: String // System.getProperty("os.name")
private set
lateinit var OSVersion: String // System.getProperty("os.version")
private set
val OSName = System.getProperty("os.name")
val OSVersion = System.getProperty("os.version")
lateinit var OperationSystem: String // all caps "WINDOWS, "OSX", "LINUX", "SOLARIS", "UNKNOWN"
private set
val isWin81: Boolean
@@ -268,7 +284,8 @@ constructor(gamename: String) : StateBasedGame(gamename) {
appgc.setVSync(VSYNC)
appgc.setMaximumLogicUpdateInterval(1000 / TARGET_INTERNAL_FPS) // 10 ms
appgc.setMinimumLogicUpdateInterval(1000 / TARGET_INTERNAL_FPS - 1) // 9 ms
appgc.setMultiSample(4)
appgc.setMultiSample(0)
appgc.setShowFPS(false)
@@ -299,9 +316,6 @@ constructor(gamename: String) : StateBasedGame(gamename) {
}
private fun getDefaultDirectory() {
OSName = System.getProperty("os.name")
OSVersion = System.getProperty("os.version")
val OS = System.getProperty("os.name").toUpperCase()
if (OS.contains("WIN")) {
OperationSystem = "WINDOWS"
@@ -327,8 +341,8 @@ constructor(gamename: String) : StateBasedGame(gamename) {
defaultSaveDir = defaultDir + "/Saves"
configDir = defaultDir + "/config.json"
println("os.name: '$OSName'")
println("os.version: '$OSVersion'")
println("[Terrarum] os.name = $OSName")
println("[Terrarum] os.version = $OSVersion")
}
private fun createDirs() {

View File

@@ -41,6 +41,7 @@ object CommandDict {
Pair("inventory", Inventory),
Pair("avtracker", AVTracker),
Pair("actorslist", ActorsList),
Pair("setscale", SetScale),
// Test codes
Pair("bulletintest", SetBulletin),

View File

@@ -0,0 +1,35 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithSprite
/**
* Created by SKYHi14 on 2017-01-20.
*/
object SetScale : ConsoleCommand {
override fun execute(args: Array<String>) {
if (args.size == 2 || args.size == 3) {
try {
val targetID = if (args.size == 3) args[1].toInt() else Terrarum.ingame.player.referenceID
val scale = args[if (args.size == 3) 2 else 1].toDouble()
val target = Terrarum.ingame.getActorByID(targetID)
if (target !is ActorWithSprite) {
EchoError("Target is not ActorWithSprite")
}
else {
target.scale = scale
}
}
catch (e: NumberFormatException) {
EchoError("Wrong number input")
}
}
else printUsage()
}
override fun printUsage() {
Echo("Usage: setscale scale | setscale actorID scale")
}
}

View File

@@ -1,7 +1,7 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithSprite
import net.torvald.terrarum.gameactors.PhysTestBall
import net.torvald.terrarum.mapdrawer.TilesDrawer
import net.torvald.terrarum.Terrarum

View File

@@ -20,6 +20,6 @@ object SpawnTapestry : ConsoleCommand {
}
override fun printUsage() {
println("Usage: spawntapestry <tapestry_file>")
Echo("Usage: spawntapestry <tapestry_file>")
}
}

View File

@@ -3,7 +3,7 @@ package net.torvald.terrarum.console
import net.torvald.terrarum.StateInGame
import net.torvald.terrarum.mapdrawer.FeaturesDrawer
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithSprite
/**
* Created by minjaesong on 16-01-24.
@@ -31,8 +31,8 @@ internal object Teleport : ConsoleCommand {
EchoError("missing 'to' on teleport command")
return
}
val fromActor: ActorWithBody
val targetActor: ActorWithBody
val fromActor: ActorWithSprite
val targetActor: ActorWithSprite
try {
val fromActorID = args[1].toInt()
val targetActorID = if (args[3].toLowerCase() == "player")
@@ -43,13 +43,13 @@ internal object Teleport : ConsoleCommand {
// if from == target, ignore the action
if (fromActorID == targetActorID) return
if (Terrarum.ingame.getActorByID(fromActorID) !is ActorWithBody ||
Terrarum.ingame.getActorByID(targetActorID) !is ActorWithBody) {
if (Terrarum.ingame.getActorByID(fromActorID) !is ActorWithSprite ||
Terrarum.ingame.getActorByID(targetActorID) !is ActorWithSprite) {
throw IllegalArgumentException()
}
else {
fromActor = Terrarum.ingame.getActorByID(fromActorID) as ActorWithBody
targetActor = Terrarum.ingame.getActorByID(targetActorID) as ActorWithBody
fromActor = Terrarum.ingame.getActorByID(fromActorID) as ActorWithSprite
targetActor = Terrarum.ingame.getActorByID(targetActorID) as ActorWithSprite
}
}
catch (e: NumberFormatException) {
@@ -72,7 +72,7 @@ internal object Teleport : ConsoleCommand {
return
}
val actor: ActorWithBody
val actor: ActorWithSprite
val x: Int
val y: Int
try {
@@ -80,11 +80,11 @@ internal object Teleport : ConsoleCommand {
y = args[4].toInt() * FeaturesDrawer.TILE_SIZE + FeaturesDrawer.TILE_SIZE / 2
val actorID = args[1].toInt()
if (Terrarum.ingame.getActorByID(actorID) !is ActorWithBody) {
if (Terrarum.ingame.getActorByID(actorID) !is ActorWithSprite) {
throw IllegalArgumentException()
}
else {
actor = Terrarum.ingame.getActorByID(actorID) as ActorWithBody
actor = Terrarum.ingame.getActorByID(actorID) as ActorWithSprite
}
}
catch (e: NumberFormatException) {

View File

@@ -6,7 +6,7 @@ import net.torvald.terrarum.console.SetAV
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorValue
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithSprite
import net.torvald.terrarum.mapdrawer.FeaturesDrawer
import java.awt.BorderLayout
import java.awt.Color
@@ -30,7 +30,7 @@ class ActorValueTracker constructor() : JFrame() {
private val avPosArea = JTextArea()
private val avPosScroller = JScrollPane(avPosArea)
private var actor: ActorWithBody? = null
private var actor: ActorWithSprite? = null
private var actorValue: ActorValue? = null
private val modavInputKey = JTextField()
@@ -101,7 +101,7 @@ class ActorValueTracker constructor() : JFrame() {
actorValue = actor!!.actorValue
}
else if (actorIDField.text.isNotBlank()) {
actor = Terrarum.ingame.getActorByID(actorIDField.text.toInt()) as ActorWithBody
actor = Terrarum.ingame.getActorByID(actorIDField.text.toInt()) as ActorWithSprite
actorValue = actor!!.actorValue
}
}
@@ -165,7 +165,7 @@ class ActorValueTracker constructor() : JFrame() {
this.title = "AVTracker — $actor"
if (actor is ActorWithBody) {
if (actor is ActorWithSprite) {
this.actor = actor
}

View File

@@ -64,4 +64,9 @@ abstract class Actor(val renderOrder: ActorOrder) : Comparable<Actor>, Runnable
}
enum class ActorOrder { BEHIND, MIDDLE, MIDTOP, FRONT }
enum class ActorOrder {
BEHIND, // tapestries, some particles (obstructed by terrain)
MIDDLE, // actors
MIDTOP, // bullets, thrown items
FRONT // fake tiles
}

View File

@@ -361,7 +361,7 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null)
* this code base, ACCELERATION must be changed (in other words, we must deal with JERK) accordingly
* to the FRICTION.
*
* So I'm adding walkX/Y and getting the ActorWithBody.setNewNextHitbox to use the velocity value of
* So I'm adding walkX/Y and getting the ActorWithSprite.setNewNextHitbox to use the velocity value of
* walkX/Y + velocity, which is stored in variable moveDelta.
*
* Be warned.

View File

@@ -0,0 +1,14 @@
package net.torvald.terrarum.gameactors
import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics
/**
* Created by SKYHi14 on 2017-01-21.
*/
abstract class ActorVisible(renderOrder: ActorOrder) : Actor(renderOrder) {
open val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0)
override abstract fun update(gc: GameContainer, delta: Int)
abstract fun drawBody(g: Graphics)
abstract fun drawGlow(g: Graphics)
}

View File

@@ -7,21 +7,29 @@ import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.mapdrawer.FeaturesDrawer
import net.torvald.terrarum.tileproperties.TileCodex
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.gamecontroller.Key
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.mapdrawer.FeaturesDrawer.TILE_SIZE
import net.torvald.terrarum.tileproperties.Tile
import net.torvald.terrarum.tileproperties.TileProp
import org.dyn4j.Epsilon
import org.dyn4j.geometry.Vector2
import org.newdawn.slick.Color
import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics
import org.newdawn.slick.Image
import java.util.*
/**
* Base class for every actor that has physical (or echo) body. This includes furnishings, paintings, gadgets, etc.
* Base class for every actor that has animated sprites. This includes furnishings, paintings, gadgets, etc.
* Also has all the physics
*
* @param renderOrder Rendering order (BEHIND, MIDDLE, MIDTOP, FRONT)
* @param physics
*
* Created by minjaesong on 16-01-13.
*/
open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
open class ActorWithSprite(renderOrder: ActorOrder, physics: Boolean = true) : ActorVisible(renderOrder) {
/** !! ActorValue macros are on the very bottom of the source !! **/
@@ -38,14 +46,12 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
protected var hitboxTranslateY: Double = 0.0// relative to spritePosY
protected var baseHitboxW: Int = 0
protected var baseHitboxH: Int = 0
protected var baseSpriteWidth: Int = 0
protected var baseSpriteHeight: Int = 0
/**
* * Position: top-left point
* * Unit: pixel
* !! external class should not hitbox.set(); use setHitboxDimension() and setPosition()
*/
val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0) // Hitbox is implemented using Double;
override val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0) // Hitbox is implemented using Double;
@Transient val nextHitbox = Hitbox(0.0, 0.0, 0.0, 0.0) // 52 mantissas ought to be enough for anybody...
val tilewiseHitbox: Hitbox
@@ -100,7 +106,10 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
get() = (actorValue.getAsDouble(AVKey.SCALE) ?: 1.0) *
(actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0)
set(value) {
val scaleDelta = value - scale
actorValue[AVKey.SCALE] = value / (actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0)
// reposition
translatePosition(-baseHitboxW * scaleDelta / 2, -baseHitboxH * scaleDelta)
}
@Transient val MASS_LOWEST = 0.1 // Kilograms
/** Apparent mass. Use "avBaseMass" for base mass */
@@ -110,7 +119,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
if (value <= 0)
throw IllegalArgumentException("mass cannot be less than or equal to zero.")
else if (value < MASS_LOWEST) {
println("[ActorWithBody] input too small; using $MASS_LOWEST instead.")
println("[ActorWithSprite] input too small; using $MASS_LOWEST instead.")
actorValue[AVKey.BASEMASS] = MASS_LOWEST
}
@@ -123,7 +132,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
if (value < 0)
throw IllegalArgumentException("invalid elasticity value $value; valid elasticity value is [0, 1].")
else if (value >= ELASTICITY_MAX) {
println("[ActorWithBody] Elasticity were capped to $ELASTICITY_MAX.")
println("[ActorWithSprite] Elasticity were capped to $ELASTICITY_MAX.")
field = ELASTICITY_MAX
}
else
@@ -149,7 +158,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
var density = 1000.0
set(value) {
if (value < 0)
throw IllegalArgumentException("[ActorWithBody] $value: density cannot be negative.")
throw IllegalArgumentException("[ActorWithSprite] $value: density cannot be negative.")
field = value
}
@@ -164,7 +173,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
/** Default to 'true' */
var isVisible = true
/** Default to 'true' */
var isUpdate = true
var isUpdate = physics
var isNoSubjectToGrav = false
var isNoCollideWorld = false
var isNoSubjectToFluidResistance = false
@@ -177,19 +186,6 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
*/
@Volatile var isChronostasis = false
/**
* Constants
*/
@Transient private val METER = 24.0
/**
* [m / s^2] * SI_TO_GAME_ACC -> [px / InternalFrame^2]
*/
@Transient private val SI_TO_GAME_ACC = METER / (Terrarum.TARGET_FPS * Terrarum.TARGET_FPS).toDouble()
/**
* [m / s] * SI_TO_GAME_VEL -> [px / InternalFrame]
*/
@Transient private val SI_TO_GAME_VEL = METER / Terrarum.TARGET_FPS
/**
* Gravitational Constant G. Load from gameworld.
* [m / s^2]
@@ -203,7 +199,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
get() = actorValue.getAsDouble(AVKey.DRAGCOEFF) ?: DRAG_COEFF_DEFAULT
set(value) {
if (value < 0)
throw IllegalArgumentException("[ActorWithBody] drag coefficient cannot be negative.")
throw IllegalArgumentException("[ActorWithSprite] drag coefficient cannot be negative.")
actorValue[AVKey.DRAGCOEFF] = value
}
@@ -260,23 +256,33 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
// some initialiser goes here...
}
fun makeNewSprite(w: Int, h: Int) {
sprite = SpriteAnimation(this)
sprite!!.setDimension(w, h)
fun makeNewSprite(w: Int, h: Int, image: Image) {
sprite = SpriteAnimation(this, w, h)
sprite!!.setSpriteImage(image)
}
fun makeNewSpriteGlow(w: Int, h: Int) {
spriteGlow = SpriteAnimation(this)
spriteGlow!!.setDimension(w, h)
fun makeNewSprite(w: Int, h: Int, imageref: String) {
sprite = SpriteAnimation(this, w, h)
sprite!!.setSpriteImage(imageref)
}
fun makeNewSpriteGlow(w: Int, h: Int, image: Image) {
spriteGlow = SpriteAnimation(this, w, h)
spriteGlow!!.setSpriteImage(image)
}
fun makeNewSpriteGlow(w: Int, h: Int, imageref: String) {
spriteGlow = SpriteAnimation(this, w, h)
spriteGlow!!.setSpriteImage(imageref)
}
/**
* @param w
* @param h
* @param tx positive: translate drawn sprite to LEFT.
* @param ty positive: translate drawn sprite to DOWN.
* @see ActorWithBody.drawBody
* @see ActorWithBody.drawGlow
* @param tx positive: translate sprite to LEFT.
* @param ty positive: translate sprite to DOWN.
* @see ActorWithSprite.drawBody
* @see ActorWithSprite.drawGlow
*/
fun setHitboxDimension(w: Int, h: Int, tx: Int, ty: Int) {
baseHitboxH = h
@@ -296,18 +302,23 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
*/
fun setPosition(x: Double, y: Double) {
hitbox.setFromWidthHeight(
x - (baseHitboxW / 2 - hitboxTranslateX) * (1 - scale),
y - (baseHitboxH - hitboxTranslateY) * (1 - scale),
x - (baseHitboxW / 2 - hitboxTranslateX) * scale,
y - (baseHitboxH - hitboxTranslateY) * scale,
baseHitboxW * scale,
baseHitboxH * scale)
nextHitbox.setFromWidthHeight(
x - (baseHitboxW / 2 - hitboxTranslateX) * (1 - scale),
y - (baseHitboxH - hitboxTranslateY) * (1 - scale),
x - (baseHitboxW / 2 - hitboxTranslateX) * scale,
y - (baseHitboxH - hitboxTranslateY) * scale,
baseHitboxW * scale,
baseHitboxH * scale)
}
private fun translatePosition(dx: Double, dy: Double) {
hitbox.translate(dx, dy)
nextHitbox.translate(dx, dy)
}
val centrePosVector: Vector2
get() = Vector2(hitbox.centeredX, hitbox.centeredY)
val centrePosPoint: Point2d
@@ -344,12 +355,6 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
isNoSubjectToFluidResistance = isPlayerNoClip
}
// set sprite dimension vars if there IS sprite for the actor
if (sprite != null) {
baseSpriteHeight = sprite!!.height
baseSpriteWidth = sprite!!.width
}
/**
* Actual physics thing (altering velocity) starts from here
*/
@@ -987,50 +992,64 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
private fun updateHitbox() = hitbox.reassign(nextHitbox)
open fun drawGlow(g: Graphics) {
override open fun drawGlow(g: Graphics) {
if (isVisible && spriteGlow != null) {
blendLightenOnly()
if (!sprite!!.flippedHorizontal()) {
spriteGlow!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat(),
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
// Q&D fix for Roundworld anomaly
spriteGlow!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat() + world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
spriteGlow!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat() - world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
}
else {
spriteGlow!!.render(g,
(hitbox.posX - scale).toFloat(),
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
// Q&D fix for Roundworld anomaly
spriteGlow!!.render(g,
(hitbox.posX - scale).toFloat() + world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
spriteGlow!!.render(g,
(hitbox.posX - scale).toFloat() - world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
}
}
// debug hitbox
if (KeyToggler.isOn(Key.F11)) {
g.color = Color(1f, 0f, 1f, 1f)
blendNormal()
g.lineWidth = 1f
g.drawRect(
hitbox.posX.toFloat(),
hitbox.posY.toFloat(),
hitbox.width.toFloat(),
hitbox.height.toFloat()
)
}
}
open fun drawBody(g: Graphics) {
override open fun drawBody(g: Graphics) {
if (isVisible && sprite != null) {
@@ -1043,36 +1062,36 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
if (!sprite!!.flippedHorizontal()) {
sprite!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat(),
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
// Q&D fix for Roundworld anomaly
sprite!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat() + world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
sprite!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat() - world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
}
else {
sprite!!.render(g,
(hitbox.posX - scale).toFloat(),
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
// Q&D fix for Roundworld anomaly
sprite!!.render(g,
(hitbox.posX - scale).toFloat() + world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
sprite!!.render(g,
(hitbox.posX - scale).toFloat() - world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat()
)
}
@@ -1129,9 +1148,9 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
// warnings
if (sprite == null && isVisible)
println("[ActorWithBody] Caution: actor ${this.javaClass.simpleName} is echo but the sprite was not set.")
println("[ActorWithSprite] Caution: actor ${this.javaClass.simpleName} is echo but the sprite was not set.")
else if (sprite != null && !isVisible)
println("[ActorWithBody] Caution: actor ${this.javaClass.simpleName} is invisible but the sprite was given.")
println("[ActorWithSprite] Caution: actor ${this.javaClass.simpleName} is invisible but the sprite was given.")
assertPrinted = true
}
@@ -1190,13 +1209,30 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
companion object {
/**
* Constants
*/
@Transient private val METER = 24.0
/**
* [m / s^2] * SI_TO_GAME_ACC -> [px / InternalFrame^2]
*/
@Transient val SI_TO_GAME_ACC = METER / (Terrarum.TARGET_FPS * Terrarum.TARGET_FPS).toDouble()
/**
* [m / s] * SI_TO_GAME_VEL -> [px / InternalFrame]
*/
@Transient val SI_TO_GAME_VEL = METER / Terrarum.TARGET_FPS
/**
* Enumerations that exported to JSON
*/
@Transient const val COLLISION_NOCOLLIDE = 0
@Transient const val COLLISION_KINEMATIC = 1 // does not displaced by external forces when collided, but it still can move (e.g. player, elevator)
@Transient const val COLLISION_DYNAMIC = 2 // displaced by external forces
@Transient const val COLLISION_STATIC = 3 // does not displaced by external forces, target of collision (e.g. nonmoving static obj)
/** does not displaced by external forces when collided, but it still can move (e.g. player, elevator) */
@Transient const val COLLISION_KINEMATIC = 1
/** displaced by external forces */
@Transient const val COLLISION_DYNAMIC = 2
/** does not displaced by external forces, target of collision (e.g. nonmoving static obj) */
@Transient const val COLLISION_STATIC = 3
@Transient const val COLLISION_KNOCKBACK_GIVER = 4 // mobs
@Transient const val COLLISION_KNOCKBACK_TAKER = 5 // benevolent NPCs
@Transient const val BLEND_NORMAL = 4

View File

@@ -18,8 +18,8 @@ object CreatureBuilder {
* @Param jsonFileName with extension
*/
@Throws(IOException::class, SlickException::class)
operator fun invoke(jsonFileName: String): ActorWithBody {
val actor = ActorWithBody(ActorOrder.MIDDLE)
operator fun invoke(jsonFileName: String): ActorWithSprite {
val actor = ActorWithSprite(ActorOrder.MIDDLE)
InjectCreatureRaw(actor.actorValue, jsonFileName)
return actor

View File

@@ -9,7 +9,7 @@ import org.newdawn.slick.Graphics
/**
* Created by minjaesong on 16-03-15.
*/
class DroppedItem(private val item: InventoryItem) : ActorWithBody(ActorOrder.MIDTOP) {
class DroppedItem(private val item: InventoryItem) : ActorWithSprite(ActorOrder.MIDTOP) {
init {
if (item.id >= ItemCodex.ITEM_COUNT_MAX)

View File

@@ -5,7 +5,7 @@ import net.torvald.spriteanimation.SpriteAnimation
/**
* Created by minjaesong on 16-06-17.
*/
open class FixtureBase : ActorWithBody(ActorOrder.BEHIND) {
open class FixtureBase(physics: Boolean = true) : ActorWithSprite(ActorOrder.BEHIND, physics) {
/**
* 0: Open
* 1: Blocked

View File

@@ -25,8 +25,7 @@ class FixtureTikiTorch : FixtureBase(), Luminous {
lightBoxList = ArrayList(1)
lightBoxList.add(Hitbox(3.0, 0.0, 4.0, 3.0))
makeNewSprite(10, 27)
sprite!!.setSpriteImage("assets/graphics/sprites/fixtures/tiki_torch.tga")
makeNewSprite(10, 27, "assets/graphics/sprites/fixtures/tiki_torch.tga")
sprite!!.setDelay(200)
sprite!!.setRowsAndFrames(1, 1)

View File

@@ -11,7 +11,7 @@ import org.newdawn.slick.Input
*
* Created by minjaesong on 16-10-10.
*/
open class HistoricalFigure(val born: GameDate, val dead: GameDate? = null) : ActorWithBody(ActorOrder.MIDDLE) {
open class HistoricalFigure(val born: GameDate, val dead: GameDate? = null) : ActorWithSprite(ActorOrder.MIDDLE) {
init {
this.actorValue["_bornyear"] = born.year

View File

@@ -31,7 +31,7 @@ open class HumanoidNPC(override val scriptPath: String, born: GameDate) : ActorH
private val aiLuaAPI: AILuaAPI
companion object {
val DEFAULT_COLLISION_TYPE = ActorWithBody.COLLISION_DYNAMIC
val DEFAULT_COLLISION_TYPE = ActorWithSprite.COLLISION_DYNAMIC
}
init {

View File

@@ -0,0 +1,68 @@
package net.torvald.terrarum.gameactors
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithSprite.Companion.SI_TO_GAME_ACC
import net.torvald.terrarum.mapdrawer.FeaturesDrawer.TILE_SIZE
import net.torvald.terrarum.tileproperties.Tile
import net.torvald.terrarum.tileproperties.TileCodex
import org.dyn4j.geometry.Vector2
import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics
import org.newdawn.slick.Image
/**
* Actors with static sprites and very simple physics
*
* Created by SKYHi14 on 2017-01-20.
*/
open class ParticleBase(renderOrder: ActorOrder, maxLifeTime: Int? = null) : ActorVisible(renderOrder), Projectile {
override var actorValue = ActorValue()
override @Volatile var flagDespawn = false
override fun run() {
TODO("not implemented")
}
var isNoSubjectToGrav = false
var dragCoefficient = 3.0
private val lifetimeMax = maxLifeTime ?: 5000
private var lifetimeCounter = 0
open val velocity = Vector2(0.0, 0.0)
open lateinit var image: Image
init {
}
override fun update(gc: GameContainer, delta: Int) {
lifetimeCounter += delta
if (velocity.isZero || lifetimeCounter >= lifetimeMax ||
// simple stuck check
TileCodex[Terrarum.ingame.world.getTileFromTerrain(
hitbox.pointedX.div(TILE_SIZE).floorInt(),
hitbox.pointedY.div(TILE_SIZE).floorInt()
) ?: Tile.STONE].isSolid) {
flagDespawn = true
}
// gravity, winds, etc. (external forces)
if (!isNoSubjectToGrav) {
velocity += Terrarum.ingame.world.gravitation / dragCoefficient * SI_TO_GAME_ACC
}
// combine external forces
hitbox.translate(velocity)
}
override fun drawBody(g: Graphics) {
g.drawImage(image, hitbox.centeredX.toFloat(), hitbox.centeredY.toFloat())
}
override fun drawGlow(g: Graphics) {
}
}

View File

@@ -0,0 +1,24 @@
package net.torvald.terrarum.gameactors
import org.dyn4j.geometry.Vector2
import org.newdawn.slick.Image
/**
* Created by SKYHi14 on 2017-01-20.
*/
class ParticleTestRain(posX: Double, posY: Double) : ParticleBase(ActorOrder.BEHIND, 6000) {
init {
image = Image("./assets/graphics/weathers/raindrop.tga")
val w = image.width.toDouble()
val h = image.height.toDouble()
hitbox.setFromWidthHeight(
posX - w.times(0.5),
posY - h.times(0.5),
w, h
)
velocity.y = 16.0
}
}

View File

@@ -10,7 +10,7 @@ import org.newdawn.slick.Graphics
/**
* Created by minjaesong on 16-03-05.
*/
class PhysTestBall : ActorWithBody(ActorOrder.MIDDLE) {
class PhysTestBall : ActorWithSprite(ActorOrder.MIDDLE) {
private var color = Color.orange

View File

@@ -9,7 +9,7 @@ import net.torvald.terrarum.mapdrawer.FeaturesDrawer
*/
object PlayerBuilderCynthia {
operator fun invoke(): ActorWithBody {
operator fun invoke(): ActorWithSprite {
//val p: Player = Player(GameDate(100, 143)) // random value thrown
val p: HumanoidNPC = HumanoidNPC("/net/torvald/terrarum/gameactors/ai/scripts/PokemonNPCAI.lua",
GameDate(100, 143)) // random value thrown
@@ -19,8 +19,7 @@ object PlayerBuilderCynthia {
p.actorValue[AVKey.NAME] = "Cynthia"
p.makeNewSprite(26, 42)
p.sprite!!.setSpriteImage("assets/graphics/sprites/test_player_2.tga")
p.makeNewSprite(26, 42, "assets/graphics/sprites/test_player_2.tga")
p.sprite!!.setDelay(200)
p.sprite!!.setRowsAndFrames(1, 1)

View File

@@ -26,13 +26,11 @@ object PlayerBuilderSigrid {
p.referenceID = 0x51621D // the only constant of this procedural universe
p.makeNewSprite(28, 51)
p.sprite!!.setSpriteImage("assets/graphics/sprites/test_player.tga")
p.makeNewSprite(28, 51, "assets/graphics/sprites/test_player.tga")
p.sprite!!.setDelay(200)
p.sprite!!.setRowsAndFrames(1, 1)
p.makeNewSpriteGlow(28, 51)
p.spriteGlow!!.setSpriteImage("assets/graphics/sprites/test_player_glow.tga")
p.makeNewSpriteGlow(28, 51, "assets/graphics/sprites/test_player_glow.tga")
p.spriteGlow!!.setDelay(200)
p.spriteGlow!!.setRowsAndFrames(1, 1)
@@ -66,7 +64,7 @@ object PlayerBuilderSigrid {
//p.actorValue["__selectedtile"] = 147 // test code; replace with <tile_item>.primaryUse(gc, delta)
p.actorValue["__aimhelper"] = true // TODO when you'll gonna implement it?
p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT)!!, 10, 0)
p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT)!!, 11, -2) // FIXME offsetY of -2: Have no idea about the error; it's just supposed to be zero
p.inventory = ActorInventory(0x7FFFFFFF, true)

View File

@@ -4,6 +4,8 @@ import net.torvald.colourutil.CIELabUtil.darkerLab
import net.torvald.point.Point2d
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.tileproperties.Tile
import net.torvald.terrarum.tileproperties.TileCodex
import org.dyn4j.geometry.Vector2
import org.newdawn.slick.Color
import org.newdawn.slick.GameContainer
@@ -15,11 +17,13 @@ import java.util.*
*
* Created by minjaesong on 16-08-29.
*/
// TODO simplified, lightweight physics (does not call PhysicsSolver)
open class ProjectileSimple(
private val type: Int,
fromPoint: Vector2, // projected coord
toPoint: Vector2 // arriving coord
) : ActorWithBody(ActorOrder.MIDTOP), Luminous, Projectile {
) : ActorWithSprite(ActorOrder.MIDTOP), Luminous, Projectile {
val damage: Int
val displayColour: Color
@@ -69,7 +73,12 @@ open class ProjectileSimple(
override fun update(gc: GameContainer, delta: Int) {
// hit something and despawn
lifetimeCounter += delta
if ((ccdCollided || grounded) || lifetimeCounter >= lifetimeMax) flagDespawn()
if (ccdCollided || grounded || lifetimeCounter >= lifetimeMax ||
// stuck check
TileCodex[Terrarum.ingame.world.getTileFromTerrain(feetPosTile[0], feetPosTile[1]) ?: Tile.STONE].isSolid
) {
flagDespawn()
}
posPre.set(centrePosPoint)

View File

@@ -10,13 +10,14 @@ import org.newdawn.slick.Image
/**
* Created by SKYHi14 on 2017-01-07.
*/
class TapestryObject(val image: Image, val artName: String, val artAuthor: String) : FixtureBase() {
class TapestryObject(val image: Image, val artName: String, val artAuthor: String) : FixtureBase(physics = false) {
// physics = false only speeds up for ~2 frames with 50 tapestries
init {
makeNewSprite(image.width, image.height)
image.filter = Image.FILTER_NEAREST
makeNewSprite(image.width, image.height, image)
setHitboxDimension(image.width, image.height, 0, 0)
sprite!!.setSpriteImage(image)
isNoSubjectToGrav = true
setPosition(Terrarum.appgc.mouseX, Terrarum.appgc.mouseY)
}

View File

@@ -3,7 +3,7 @@ package net.torvald.terrarum.gameactors
/**
* Created by minjaesong on 16-04-26.
*/
class WeaponSwung(val itemID: Int) : ActorWithBody(ActorOrder.MIDTOP), Luminous {
class WeaponSwung(val itemID: Int) : ActorWithSprite(ActorOrder.MIDTOP), Luminous {
// just let the solver use AABB; it's cheap but works just enough
/**

View File

@@ -3,7 +3,7 @@ package net.torvald.terrarum.gameactors.ai
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.AIControlled
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithSprite
import net.torvald.terrarum.mapdrawer.LightmapRenderer
import net.torvald.terrarum.tileproperties.Tile
import net.torvald.terrarum.tileproperties.TileCodex
@@ -14,7 +14,7 @@ import org.luaj.vm2.lib.ZeroArgFunction
/**
* Created by minjaesong on 16-10-24.
*/
internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
internal class AILuaAPI(g: Globals, actor: ActorWithSprite) {
// FIXME when actor jumps, the actor releases left/right stick
@@ -42,6 +42,7 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
g["ai"]["getNearbyTiles"] = GetNearbyTiles(actor)
g["ai"]["getFloorsHeight"] = GetFloorsHeight(actor)
g["ai"]["getCeilingsHeight"] = GetCeilingsHeight(actor)
g["ai"]["getLedgesHeight"] = GetLedgesHeight(actor)
g["game"] = LuaValue.tableOf()
g["game"]["version"] = GameVersion()
@@ -50,9 +51,9 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
companion object {
/**
* Reads arbitrary ActorWithBody and returns its information as Lua table
* Reads arbitrary ActorWithSprite and returns its information as Lua table
*/
fun composeActorObject(actor: ActorWithBody): LuaTable {
fun composeActorObject(actor: ActorWithSprite): LuaTable {
val t: LuaTable = LuaTable()
t["name"] = actor.actorValue.getAsString(AVKey.NAME).toLua()
@@ -94,7 +95,7 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
operator fun LuaTable.set(index: Int, value: Int) { this[index] = value.toLua() }
}
class GetSelfActorInfo(val actor: ActorWithBody) : ZeroArgFunction() {
class GetSelfActorInfo(val actor: ActorWithSprite) : ZeroArgFunction() {
override fun call(): LuaValue {
return composeActorObject(actor)
}
@@ -130,13 +131,13 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
}
}
class GetX(val actor: ActorWithBody) : ZeroArgFunction() {
class GetX(val actor: ActorWithSprite) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(actor.hitbox.centeredX)
}
}
class GetY(val actor: ActorWithBody) : ZeroArgFunction() {
class GetY(val actor: ActorWithSprite) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(actor.hitbox.centeredY)
}
@@ -219,7 +220,7 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
}
}
class GetNearbyTiles(val actor: ActorWithBody) : OneArgFunction() {
class GetNearbyTiles(val actor: ActorWithSprite) : OneArgFunction() {
/** @param radius
*
* 3 will return 7x7 array, 0 will return 1x1, 1 will return 3x3
@@ -261,7 +262,7 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
}
}
class GetFloorsHeight(val actor: ActorWithBody) : OneArgFunction() {
class GetFloorsHeight(val actor: ActorWithSprite) : OneArgFunction() {
/** @param radius
*
* 3 will return len:7 array, 0 will return len:1, 1 will return len:3
@@ -304,14 +305,13 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
}
}
class GetCeilingsHeight(val actor: ActorWithBody) : OneArgFunction() {
/** @param radius
class GetCeilingsHeight(val actor: ActorWithSprite) : OneArgFunction() {
/** @param arg radius
*
* 3 will return 7x7 array, 0 will return 1x1, 1 will return 3x3
*
* Index: [-3] .. [0] .. [3] for radius
* Return value: floor height
* (-1): tile you can stand on
* 0: body tile (legs area)
* 1: body tile (may be vary depend on the size of the actor)
* 2+: tiles up there
@@ -348,6 +348,48 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
}
}
class GetLedgesHeight(val actor: ActorWithSprite) : OneArgFunction() {
/** @param arg radius
* ==
* <- (non-solid found)
* ==
* ==
* ==
* == @ -> ledge height: 4
* =================
*/
override fun call(arg: LuaValue): LuaValue {
val radius = arg.checkint()
val searchUpLimit = 12
if (radius < 0) {
return LuaValue.NONE
}
else if (radius > 8) {
throw IllegalArgumentException("Radius too large -- must be 8 or less")
}
else {
val luatable = LuaTable()
val feetTilePos = actor.feetPosTile
for (x in feetTilePos[0] - radius..feetTilePos[0] + radius) {
// search up
var searchUpCounter = 0
while (true) {
val tile = Terrarum.ingame.world.getTileFromTerrain(x, feetTilePos[1] - searchUpCounter) ?: Tile.STONE
if (!TileCodex[tile].isSolid || searchUpCounter >= searchUpLimit) {
luatable[x - feetTilePos[0]] = searchUpCounter
break
}
searchUpCounter++
}
}
return luatable
}
}
}

View File

@@ -20,11 +20,11 @@ function generateCountMax()
end
function moveToDirection(delta)
local tiles = ai.getNearbyTiles(1)
local pits = ai.getFloorsHeight(2)
local ledges = ai.getLedgesHeight(1)
if moveMode == "left" then
if bit32.band(bit32.bor(tiles[0][-1], tiles[-1][-1]), 1) == 1 then
if pits[-1] == 1 then
ai.moveLeft(0.8)
if ledges[-1] <= jumpheight then -- no futile jumps
ai.jump()
@@ -33,7 +33,7 @@ function moveToDirection(delta)
ai.moveLeft(0.5)
end
elseif moveMode == "right" then
if bit32.band(bit32.bor(tiles[0][1], tiles[-1][1]), 1) == 1 then
if pits[1] == 1 then
ai.moveRight(0.8)
if ledges[1] <= jumpheight then -- no futile jumps
ai.jump()

View File

@@ -2,7 +2,7 @@ package net.torvald.terrarum.gameactors.physicssolver
import com.jme3.math.FastMath
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithSprite
import java.util.*
/**
@@ -20,9 +20,9 @@ object CollisionSolver {
private val collListX = ArrayList<CollisionMarkings>(COLL_LIST_SIZE)
private val collListY = ArrayList<CollisionMarkings>(COLL_LIST_SIZE)
private val collCandidateX = ArrayList<Pair<ActorWithBody, ActorWithBody>>(COLL_CANDIDATES_SIZE)
private val collCandidateY = ArrayList<Pair<ActorWithBody, ActorWithBody>>(COLL_CANDIDATES_SIZE)
private var collCandidates = ArrayList<Pair<ActorWithBody, ActorWithBody>>(COLL_FINAL_CANDIDATES_SIZE)
private val collCandidateX = ArrayList<Pair<ActorWithSprite, ActorWithSprite>>(COLL_CANDIDATES_SIZE)
private val collCandidateY = ArrayList<Pair<ActorWithSprite, ActorWithSprite>>(COLL_CANDIDATES_SIZE)
private var collCandidates = ArrayList<Pair<ActorWithSprite, ActorWithSprite>>(COLL_FINAL_CANDIDATES_SIZE)
private val collCandidateStack = Stack<CollisionMarkings>()
@@ -40,7 +40,7 @@ object CollisionSolver {
// mark list x
Terrarum.ingame.actorContainer.forEach { it ->
if (it is ActorWithBody) {
if (it is ActorWithSprite) {
collListX.add(CollisionMarkings(it.hitbox.hitboxStart.x, STARTPOINT, it))
collListX.add(CollisionMarkings(it.hitbox.hitboxEnd.x, ENDPOINT, it))
}
@@ -73,7 +73,7 @@ object CollisionSolver {
// mark list y
Terrarum.ingame.actorContainer.forEach { it ->
if (it is ActorWithBody) {
if (it is ActorWithSprite) {
collListY.add(CollisionMarkings(it.hitbox.hitboxStart.y, STARTPOINT, it))
collListY.add(CollisionMarkings(it.hitbox.hitboxEnd.y, ENDPOINT, it))
}
@@ -89,7 +89,7 @@ object CollisionSolver {
else if (it.kind == ENDPOINT) {
val mark_this = it
val mark_other = collCandidateStack.pop()
val collCandidate: Pair<ActorWithBody, ActorWithBody>
val collCandidate: Pair<ActorWithSprite, ActorWithSprite>
// make sure actor with lower ID comes first
if (mark_this.actor < mark_other.actor)
collCandidate = Pair(mark_this.actor, mark_other.actor)
@@ -137,7 +137,7 @@ object CollisionSolver {
return indexOfEqFn(this, other) >= 0
}
private fun solveCollision(a: ActorWithBody, b: ActorWithBody) {
private fun solveCollision(a: ActorWithSprite, b: ActorWithSprite) {
// some of the Pair(a, b) are either duplicates or erroneously reported.
// e.g. (A, B), (B, C) and then (A, C);
// in some situation (A, C) will not making any contact with each other
@@ -170,11 +170,11 @@ object CollisionSolver {
}
}
private infix fun ActorWithBody.makesCollisionWith(other: ActorWithBody) =
this.collisionType != ActorWithBody.COLLISION_NOCOLLIDE &&
other.collisionType != ActorWithBody.COLLISION_NOCOLLIDE
private infix fun ActorWithSprite.makesCollisionWith(other: ActorWithSprite) =
this.collisionType != ActorWithSprite.COLLISION_NOCOLLIDE &&
other.collisionType != ActorWithSprite.COLLISION_NOCOLLIDE
private infix fun ActorWithBody.isCollidingWith(other: ActorWithBody): Boolean {
private infix fun ActorWithSprite.isCollidingWith(other: ActorWithSprite): Boolean {
val ax = this.hitbox.centeredX
val ay = this.hitbox.centeredY
val bx = other.hitbox.centeredX
@@ -205,7 +205,7 @@ object CollisionSolver {
data class CollisionMarkings(
val pos: Double,
val kind: Int,
val actor: ActorWithBody
val actor: ActorWithSprite
)
/**

View File

@@ -1,6 +1,6 @@
package net.torvald.terrarum.gameactors.physicssolver
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithSprite
/**
* Created by minjaesong on 16-05-01.
@@ -11,7 +11,7 @@ object VelocitySolver {
}
private fun applyGravity(actor: ActorWithBody) {
private fun applyGravity(actor: ActorWithSprite) {
}

View File

@@ -24,7 +24,7 @@ object WorldSimulator {
const val FLUID_UPDATING_SQUARE_RADIUS = 64 // larger value will have dramatic impact on performance
const private val DOUBLE_RADIUS = FLUID_UPDATING_SQUARE_RADIUS * 2
private val fluidMap = Array<IntArray>(DOUBLE_RADIUS, { IntArray(DOUBLE_RADIUS) })
private val fluidMap = Array<ByteArray>(DOUBLE_RADIUS, { ByteArray(DOUBLE_RADIUS) })
private val fluidTypeMap = Array<ByteArray>(DOUBLE_RADIUS, { ByteArray(DOUBLE_RADIUS) })
const val DISPLACE_CAP = 4
@@ -38,23 +38,28 @@ object WorldSimulator {
val colourNone = Color(0x808080)
val colourWater = Color(0x66BBFF)
private val world = Terrarum.ingame.world
// TODO future Kotlin feature -- typealias AnyPlayer: HistoricalFigure
operator fun invoke(world: GameWorld, p: HistoricalFigure, delta: Int) {
operator fun invoke(p: HistoricalFigure, delta: Int) {
updateXFrom = p.hitbox.centeredX.div(FeaturesDrawer.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt()
updateYFrom = p.hitbox.centeredY.div(FeaturesDrawer.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt()
updateXTo = updateXFrom + DOUBLE_RADIUS
updateYTo = updateYFrom + DOUBLE_RADIUS
moveFluids(world, delta)
displaceFallables(world, delta)
moveFluids(delta)
displaceFallables(delta)
}
/**
* displace fluids. Note that the code assumes the gravity pulls things downward ONLY,
* which means you'll need to modify the code A LOT if you're going to implement zero- or
* reverse-gravity.
*
* Procedure: CP world fluidmap -> sim on fluidmap -> CP fluidmap world
* TODO multithread
*/
fun moveFluids(world: GameWorld, delta: Int) {
fun moveFluids(delta: Int) {
////////////////////
// build fluidmap //
////////////////////
@@ -74,7 +79,7 @@ object WorldSimulator {
if (tile.isFluid()) {
// move down if not obstructed
if (!tileBottom.isSolid()) {
/*if (!tileBottom.isSolid()) {
val drainage = drain(world, x, y, DISPLACE_CAP)
pour(world, x, y + 1, drainage)
}
@@ -106,7 +111,11 @@ object WorldSimulator {
// nowhere open; do default (fill top)
else {
pour(world, x, y - 1, DISPLACE_CAP)
}*/
if (!tileBottom.isSolid()) {
pour(x, y + 1, drain(x, y, FLUID_MAX))
}
}
}
}
@@ -123,7 +132,7 @@ object WorldSimulator {
* displace fallable tiles. It is scanned bottom-left first. To achieve the sens ofreal
* falling, each tiles are displaced by ONLY ONE TILE below.
*/
fun displaceFallables(world: GameWorld, delta: Int) {
fun displaceFallables(delta: Int) {
for (y in updateYFrom..updateYTo) {
for (x in updateXFrom..updateXTo) {
val tile = world.getTileFromTerrain(x, y) ?: Tile.STONE
@@ -135,7 +144,7 @@ object WorldSimulator {
// remove tileThis to create air pocket
world.setTileTerrain(x, y, Tile.AIR)
pour(world, x, y, drain(world, x, y, tileBelow.fluidLevel()))
pour(x, y, drain(x, y, tileBelow.fluidLevel().toInt()))
// place our tile
world.setTileTerrain(x, y + 1, tile)
}
@@ -156,7 +165,7 @@ object WorldSimulator {
for (x in 0..fluidMap[0].size - 1) {
val data = fluidMap[y][x]
if (TilesDrawer.tileInCamera(x + updateXFrom, y + updateYFrom)) {
if (data == 0)
if (data == 0.toByte())
g.color = colourNone
else
g.color = colourWater
@@ -188,7 +197,7 @@ object WorldSimulator {
for (x in updateXFrom..updateXTo) {
val tile = world.getTileFromTerrain(x, y) ?: Tile.STONE
if (tile.isFluid()) {
fluidMap[y - updateYFrom][x - updateXFrom] = tile.fluidLevel()
fluidMap[y - updateYFrom][x - updateXFrom] = tile.fluidLevel().toByte()
fluidTypeMap[y - updateYFrom][x - updateXFrom] = tile.fluidType().toByte()
}
}
@@ -209,8 +218,8 @@ object WorldSimulator {
fun Int.isFluid() = TileCodex[this].isFluid
fun Int.isSolid() = this.fluidLevel() == FLUID_MAX || TileCodex[this].isSolid
//fun Int.viscosity() = TileCodex[this].
fun Int.fluidLevel() = if (!this.isFluid()) 0 else (this % FLUID_MAX) + 1
fun Int.fluidType() = this / FLUID_MAX
fun Int.fluidLevel() = if (!this.isFluid()) 0 else (this % FLUID_MAX).plus(1)
fun Int.fluidType() = (this / 16) // 0 - 255, 255 being water, 254 being lava
fun Int.isEven() = (this and 0x01) == 0
fun Int.isFallable() = TileCodex[this].isFallable
@@ -231,10 +240,11 @@ object WorldSimulator {
* (intended drainage - this) will give you how much fluid is not yet drained.
* TODO add fluidType support
*/
private fun drain(world: GameWorld, x: Int, y: Int, amount: Int): Int {
val displacement = Math.min(fluidMap[y - updateYFrom][x - updateXFrom], amount)
private fun drain(x: Int, y: Int, amount: Int): Int {
val displacement = Math.min(fluidMap[y - updateYFrom][x - updateXFrom].toInt(), amount)
fluidMap[y - updateYFrom][x - updateXFrom] -= displacement
fluidMap[y - updateYFrom][x - updateXFrom] =
(fluidMap[y - updateYFrom][x - updateXFrom] - displacement).toByte()
return displacement
}
@@ -243,7 +253,7 @@ object WorldSimulator {
* @param x and y: world tile coord
* TODO add fluidType support
*/
private fun pour(world: GameWorld, x: Int, y: Int, amount: Int) {
private fun pour(x: Int, y: Int, amount: Int) {
/**
* @param x and y: world tile coord
* @return spillage
@@ -256,10 +266,10 @@ object WorldSimulator {
val addrY = worldYPos - updateYFrom
if (addrX >= 0 && addrY >= 0 && addrX < DOUBLE_RADIUS && addrY < DOUBLE_RADIUS) {
fluidMap[addrY][addrX] += volume
fluidMap[addrY][addrX] = (fluidMap[addrY][addrX] + volume).toByte()
if (fluidMap[addrY][addrX] > FLUID_MAX) {
spil = fluidMap[addrY][addrX] - FLUID_MAX
fluidMap[addrY][addrX] = FLUID_MAX
fluidMap[addrY][addrX] = FLUID_MAX.toByte()
}
}

View File

@@ -5,7 +5,7 @@ import net.torvald.terrarum.KVHashMap
import net.torvald.terrarum.gameactors.CanBeAnItem
import net.torvald.terrarum.gameitem.InventoryItem
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithSprite
import net.torvald.terrarum.gamecontroller.mouseTileX
import net.torvald.terrarum.gamecontroller.mouseTileY
import net.torvald.terrarum.gameitem.EquipPosition
@@ -50,7 +50,7 @@ object ItemCodex {
val mousePoint = Point2d(gc.mouseTileX.toDouble(), gc.mouseTileY.toDouble())
// linear search filter (check for intersection with tilewise mouse point and tilewise hitbox)
Terrarum.ingame.actorContainer.forEach {
if (it is ActorWithBody && it.tilewiseHitbox.intersects(mousePoint))
if (it is ActorWithSprite && it.tilewiseHitbox.intersects(mousePoint))
return
}
// filter passed, do the job

View File

@@ -7,7 +7,7 @@ import com.jme3.math.FastMath
import net.torvald.colourutil.RGB
import net.torvald.colourutil.CIELuvUtil.additiveLuv
import net.torvald.terrarum.concurrent.ThreadParallel
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithSprite
import net.torvald.terrarum.gameactors.abs
import net.torvald.terrarum.gameactors.roundInt
import net.torvald.terrarum.gameworld.GameWorld
@@ -217,7 +217,7 @@ object LightmapRenderer {
private fun buildLanternmap() {
lanternMap.clear()
Terrarum.ingame.actorContainer.forEach { it ->
if (it is Luminous && it is ActorWithBody) {
if (it is Luminous && it is ActorWithSprite) {
// put lanterns to the area the luminantBox is occupying
for (lightBox in it.lightBoxList) {
val lightBoxX = it.hitbox.posX + lightBox.posX
@@ -267,11 +267,6 @@ object LightmapRenderer {
}
// END MIX TILE
// mix luminous actor
/*for ((posX, posY, luminosity) in lanternMap) {
if (posX == x && posY == y)
lightLevelThis = lightLevelThis maxBlend luminosity // maximise to not exceed 1.0 with normal (<= 1.0) light
}*/
for (i in 0..lanternMap.size - 1) {
val lmap = lanternMap[i]
if (lmap.posX == x && lmap.posY == y)

View File

@@ -4,5 +4,5 @@ package net.torvald.terrarum.mapgenerator
* Created by minjaesong on 16-03-31.
*/
interface NoiseFilter {
fun getGrad(func_argX: Int, start: Float, end: Float): Float
fun getGrad(func_argX: Int, start: Double, end: Double): Double
}

View File

@@ -30,7 +30,7 @@ import com.jme3.math.FastMath
* Created by minjaesong on 16-03-31.
*/
object NoiseFilterCubic : NoiseFilter {
override fun getGrad(func_argX: Int, start: Float, end: Float): Float {
override fun getGrad(func_argX: Int, start: Double, end: Double): Double {
val graph_gradient = -FastMath.pow(FastMath.pow((1 - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat(), 3f), -1f) * // 1/4 -> 3/4 -> 9/16 -> 16/9
(start - end) / FastMath.pow(WorldGenerator.HEIGHT.toFloat(), 3f) *
FastMath.pow((func_argX - WorldGenerator.HEIGHT).toFloat(), 3f) + end

View File

@@ -30,7 +30,7 @@ import com.jme3.math.FastMath
* Created by minjaesong on 16-03-31.
*/
object NoiseFilterMinusQuadratic : NoiseFilter {
override fun getGrad(func_argX: Int, start: Float, end: Float): Float {
override fun getGrad(func_argX: Int, start: Double, end: Double): Double {
val graph_gradient = -FastMath.pow(FastMath.sqr((1 - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat()), -1f) * // 1/4 -> 3/4 -> 9/16 -> 16/9
(start - end) / FastMath.sqr(WorldGenerator.HEIGHT.toFloat()) *
FastMath.sqr((func_argX - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat()) + start

View File

@@ -31,7 +31,7 @@ import com.jme3.math.FastMath
* Created by minjaesong on 16-03-31.
*/
object NoiseFilterQuadratic : NoiseFilter {
override fun getGrad(func_argX: Int, start: Float, end: Float): Float {
override fun getGrad(func_argX: Int, start: Double, end: Double): Double {
val graph_gradient = FastMath.pow(FastMath.sqr((1 - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat()), -1f) * // 1/4 -> 3/4 -> 9/16 -> 16/9
(start - end) / FastMath.sqr(WorldGenerator.HEIGHT.toFloat()) *
FastMath.sqr((func_argX - WorldGenerator.HEIGHT).toFloat()) + end

View File

@@ -6,7 +6,7 @@ import com.jme3.math.FastMath
* Created by minjaesong on 16-03-31.
*/
object NoiseFilterSqrt : NoiseFilter {
override fun getGrad(func_argX: Int, start: Float, end: Float): Float {
override fun getGrad(func_argX: Int, start: Double, end: Double): Double {
val graph_gradient = (end - start) / FastMath.sqrt((WorldGenerator.HEIGHT - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat()) * FastMath.sqrt((func_argX - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat()) + start
if (func_argX < WorldGenerator.TERRAIN_AVERAGE_HEIGHT) {

View File

@@ -4,7 +4,7 @@ package net.torvald.terrarum.mapgenerator
* Created by minjaesong on 16-03-31.
*/
object NoiseFilterUniform : NoiseFilter {
override fun getGrad(func_argX: Int, start: Float, end: Float): Float {
return 1f
override fun getGrad(func_argX: Int, start: Double, end: Double): Double {
return 1.0
}
}

View File

@@ -32,11 +32,11 @@ object WorldGenerator {
var TERRAIN_AVERAGE_HEIGHT: Int = 0
private var minimumFloatingIsleHeight: Int = 0
private val NOISE_GRAD_START = 0.67f
private val NOISE_GRAD_END = 0.56f
private val NOISE_GRAD_START = 0.67
private val NOISE_GRAD_END = 0.56
private val NOISE_SIMPLEX_ORE_START = 1.42f
private val NOISE_SIMPLEX_ORE_END = 1.28f
private val NOISE_SIMPLEX_ORE_START = 1.42
private val NOISE_SIMPLEX_ORE_END = 1.28
private val HILL_WIDTH = 256 // power of two!
//private val MAX_HILL_HEIGHT = 100
@@ -51,8 +51,8 @@ object WorldGenerator {
private var GLACIER_MOUNTAIN_WIDTH = 900
private val GLACIER_MOUNTAIN_HEIGHT = 300
private val CAVEGEN_THRE_START = 0.95f
private val CAVEGEN_THRE_END = 0.67f
private val CAVEGEN_THRE_START = 0.95
private val CAVEGEN_THRE_END = 0.67
private var worldOceanPosition: Int = -1
@@ -113,12 +113,12 @@ object WorldGenerator {
*/
val noiseArray = arrayOf(
TaggedJoise("Carving caves", noiseRidged(1.7f, 1.4f), 1f, TILE_MACRO_ALL, TILE_MACRO_ALL, Tile.AIR, NoiseFilterSqrt, CAVEGEN_THRE_START, CAVEGEN_THRE_END)
, TaggedJoise("Collapsing caves", noiseBlobs(0.5f, 0.5f), 0.3f, Tile.AIR, Tile.STONE, Tile.STONE, NoiseFilterUniform)
TaggedJoise("Carving caves", noiseRidged(1.7, 1.4), 1.0, TILE_MACRO_ALL, TILE_MACRO_ALL, Tile.AIR, NoiseFilterSqrt, CAVEGEN_THRE_START, CAVEGEN_THRE_END)
, TaggedJoise("Collapsing caves", noiseBlobs(0.5), 0.3, Tile.AIR, Tile.STONE, Tile.STONE, NoiseFilterUniform)
//
//, TaggedJoise("Putting stone patches on the ground", noiseBlobs(0.8f, 0.8f), 1.02f, intArrayOf(Tile.DIRT, Tile.GRASS), Tile.DIRT, Tile.STONE, NoiseFilterQuadratic, NOISE_GRAD_END, NOISE_GRAD_START)
//, TaggedJoise("Placing dirt spots in the cave", noiseBlobs(0.5f, 0.5f), 0.98f, Tile.STONE, Tile.STONE, Tile.DIRT, NoiseFilterQuadratic, NOISE_GRAD_END, NOISE_GRAD_START)
//, TaggedJoise("Quarrying some stone into gravels", noiseBlobs(0.5f, 0.5f), 0.98f, Tile.STONE, Tile.STONE, Tile.GRAVEL, NoiseFilterQuadratic, NOISE_GRAD_END, NOISE_GRAD_START)
//, TaggedJoise("Putting stone patches on the ground", noiseBlobs(0.8), 1.02f, intArrayOf(Tile.DIRT, Tile.GRASS), Tile.DIRT, Tile.STONE, NoiseFilterQuadratic, NOISE_GRAD_END, NOISE_GRAD_START)
//, TaggedJoise("Placing dirt spots in the cave", noiseBlobs(0.5), 0.98f, Tile.STONE, Tile.STONE, Tile.DIRT, NoiseFilterQuadratic, NOISE_GRAD_END, NOISE_GRAD_START)
//, TaggedJoise("Quarrying some stone into gravels", noiseBlobs(0.5), 0.98f, Tile.STONE, Tile.STONE, Tile.GRAVEL, NoiseFilterQuadratic, NOISE_GRAD_END, NOISE_GRAD_START)
//
//, TaggedJoise("Growing copper veins", noiseRidged(1.7f, 1.7f), 1.68f, Tile.STONE, Tile.STONE, Tile.ORE_COPPER)
//, TaggedJoise("Cutting copper veins", noiseBlobs(0.4f, 0.4f), 0.26f, Tile.ORE_COPPER, Tile.STONE, Tile.STONE)
@@ -165,7 +165,7 @@ object WorldGenerator {
/* 1. Raise */
private fun noiseRidged(xStretch: Float, yStretch: Float): Joise {
private fun noiseRidged(xStretch: Double, yStretch: Double): Joise {
val ridged = ModuleFractal()
ridged.setType(ModuleFractal.FractalType.RIDGEMULTI)
ridged.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
@@ -185,18 +185,21 @@ object WorldGenerator {
return Joise(ridged_scale)
}
private fun noiseBlobs(xStretch: Float, yStretch: Float): Joise {
val gradval = ModuleBasisFunction()
gradval.seed = SEED xor random.nextLong()
gradval.setType(ModuleBasisFunction.BasisType.GRADVAL)
gradval.setInterpolation(ModuleBasisFunction.InterpolationType.QUINTIC)
private fun noiseBlobs(frequency: Double): Joise {
val ridged = ModuleFractal()
ridged.setType(ModuleFractal.FractalType.FBM)
ridged.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
ridged.setNumOctaves(2)
ridged.setFrequency(frequency)
ridged.seed = Random().nextLong()
val gradval_scale = ModuleScaleDomain()
gradval_scale.setScaleX(1.0 / xStretch)
gradval_scale.setScaleY(1.0 / yStretch)
gradval_scale.setSource(gradval)
val brownian_select = ModuleSelect()
brownian_select.setControlSource(ridged)
brownian_select.setThreshold(0.8)
brownian_select.setLowSource(0.0)
brownian_select.setHighSource(1.0)
return Joise(gradval_scale)
return Joise(ridged)
}
/**
@@ -596,8 +599,8 @@ object WorldGenerator {
*/
private fun carveByMap(noisemap: Any, scarcity: Float, tile: Int, message: String,
filter: NoiseFilter = NoiseFilterQuadratic,
filterStart: Float = NOISE_GRAD_START,
filterEnd: Float = NOISE_GRAD_END) {
filterStart: Double = NOISE_GRAD_START,
filterEnd: Double = NOISE_GRAD_END) {
println("[mapgenerator] " + message)
for (y in 0..HEIGHT - 1) {
@@ -626,8 +629,8 @@ object WorldGenerator {
private fun fillByMap(noisemap: Any, scarcity: Float, replaceFrom: Int, replaceTo: Int, message: String,
filter: NoiseFilter = NoiseFilterQuadratic,
filterStart: Float = NOISE_GRAD_START,
filterEnd: Float = NOISE_GRAD_END) {
filterStart: Double = NOISE_GRAD_START,
filterEnd: Double = NOISE_GRAD_END) {
println("[mapgenerator] " + message)
for (y in 0..HEIGHT - 1) {
@@ -657,8 +660,8 @@ object WorldGenerator {
private fun fillByMap(noisemap: Any, scarcity: Float, replaceFrom: Int, tile: IntArray, message: String,
filter: NoiseFilter = NoiseFilterQuadratic,
filterStart: Float = NOISE_GRAD_START,
filterEnd: Float = NOISE_GRAD_END) {
filterStart: Double = NOISE_GRAD_START,
filterEnd: Double = NOISE_GRAD_END) {
println("[mapgenerator] " + message)
for (y in 0..HEIGHT - 1) {
@@ -953,10 +956,10 @@ object WorldGenerator {
data class TaggedSimplexNoise(var noiseModule: SimplexNoise, var xStretch: Float, var yStretch: Float)
data class TaggedJoise(var message: String,
var noiseModule: Joise, var scarcity: Float,
var noiseModule: Joise, var scarcity: Double,
var replaceFromTerrain: Any, var replaceFromWall: Int,
var replaceTo: Any,
var filter: NoiseFilter = NoiseFilterQuadratic,
var filterArg1: Float = NOISE_GRAD_START,
var filterArg2: Float = NOISE_GRAD_END)
var filterArg1: Double = NOISE_GRAD_START,
var filterArg2: Double = NOISE_GRAD_END)
}

View File

@@ -12,16 +12,14 @@ import java.io.IOException
*/
object TileCodex {
private lateinit var tileProps: Array<TileProp>
private var tileProps: Array<TileProp>
val CSV_PATH = "/net/torvald/terrarum/tileproperties/tileprop.csv"
const val TILE_UNIQUE_MAX = MapLayer.RANGE * PairedMapLayer.RANGE
init {
tileProps = Array<TileProp>(TILE_UNIQUE_MAX + 1,
{i -> TileProp() }
)
tileProps = Array<TileProp>(TILE_UNIQUE_MAX + 1, { i -> TileProp() })
for (i in tileProps.indices) {
tileProps[i] = TileProp()
@@ -83,6 +81,7 @@ object TileCodex {
prop.isSolid = boolVal(record, "solid")
prop.isWallable = boolVal(record, "wall")
prop.isFallable = boolVal(record, "fall")
prop.isVertFriction = boolVal(record, "fv")
prop.dynamicLuminosityFunction = intVal(record, "dlfn")

View File

@@ -24,6 +24,7 @@ class TileProp {
var isFluid: Boolean = false
var isSolid: Boolean = false
var isWallable: Boolean = false
var isVertFriction: Boolean = false
/**
* @param luminosity Raw RGB value, without alpha

View File

@@ -5,137 +5,137 @@ package net.torvald.terrarum.tileproperties
*/
object TilePropCSV {
operator fun invoke() = """
"id";"dmg";"name" ; "opacity";"strength";"dsty";"mate";"fluid";"solid";"wall"; "lumcolor";"drop";"ddmg";"fall";"dlfn";"vscs";"friction"
"0"; "0";"TILE_AIR" ; "8396808"; "0"; "1";"null"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0";"N/A";"4"
"1"; "0";"TILE_STONE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "1"; "0"; "1"; "0"; "0"; "0";"N/A";"16"
"1"; "1";"TILE_STONE_QUARRIED" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "1"; "0"; "1"; "1"; "0"; "0";"N/A";"16"
"1"; "2";"TILE_STONE_TILE_WHITE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "1"; "0"; "1"; "2"; "0"; "0";"N/A";"16"
"1"; "3";"TILE_STONE_BRICKS" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "1"; "0"; "1"; "3"; "0"; "0";"N/A";"16"
"2"; "0";"TILE_DIRT" ; "33587232"; "6";"1400";"dirt"; "0"; "1"; "1"; "0"; "2"; "0"; "0"; "0";"N/A";"16"
"2"; "1";"TILE_GRASS" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "1"; "0"; "0";"N/A";"16"
"2"; "2";"TILE_FOLIAGE_GREEN" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "2"; "0"; "0";"N/A";"16"
"2"; "3";"TILE_FOLIAGE_LIME" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "3"; "0"; "0";"N/A";"16"
"2"; "4";"TILE_FOLIAGE_GOLD" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "4"; "0"; "0";"N/A";"16"
"2"; "5";"TILE_FOLIAGE_RED" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "5"; "0"; "0";"N/A";"16"
"2"; "6";"TILE_FOLIAGE_ICEBLUE" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "6"; "0"; "0";"N/A";"16"
"2"; "7";"TILE_FOLIAGE_PURPLE" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "7"; "0"; "0";"N/A";"16"
"3"; "0";"TILE_PLANK_NORMAL" ; "33587232"; "12"; "740";"wood"; "0"; "1"; "1"; "0"; "3"; "0"; "0"; "0";"N/A";"16"
"3"; "1";"TILE_PLANK_EBONY" ; "33587232"; "12";"1200";"wood"; "0"; "1"; "1"; "0"; "3"; "1"; "0"; "0";"N/A";"16"
"3"; "2";"TILE_PLANK_BIRCH" ; "33587232"; "12"; "670";"wood"; "0"; "1"; "1"; "0"; "3"; "2"; "0"; "0";"N/A";"16"
"3"; "3";"TILE_PLANK_BLOODROSE" ; "33587232"; "12"; "900";"wood"; "0"; "1"; "1"; "0"; "3"; "3"; "0"; "0";"N/A";"16"
"4"; "0";"TILE_TRUNK_NORMAL" ; "33587232"; "12"; "740";"wood"; "0"; "1"; "0"; "0"; "3"; "0"; "0"; "0";"N/A";"16"
"4"; "1";"TILE_TRUNK_EBONY" ; "33587232"; "12";"1200";"wood"; "0"; "1"; "0"; "0"; "3"; "1"; "0"; "0";"N/A";"16"
"4"; "2";"TILE_TRUNK_BIRCH" ; "33587232"; "12"; "670";"wood"; "0"; "1"; "0"; "0"; "3"; "2"; "0"; "0";"N/A";"16"
"4"; "3";"TILE_TRUNK_BLOODROSE" ; "33587232"; "12"; "900";"wood"; "0"; "1"; "0"; "0"; "3"; "3"; "0"; "0";"N/A";"16"
"5"; "0";"TILE_SAND" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "0"; "1"; "0";"N/A";"16"
"5"; "1";"TILE_SAND_WHITE" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "1"; "1"; "0";"N/A";"16"
"5"; "2";"TILE_SAND_RED" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "2"; "1"; "0";"N/A";"16"
"5"; "3";"TILE_SAND_DESERT" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "3"; "1"; "0";"N/A";"16"
"5"; "4";"TILE_SAND_BLACK" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "4"; "1"; "0";"N/A";"16"
"5"; "5";"TILE_SAND_GREEN" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "5"; "1"; "0";"N/A";"16"
"6"; "0";"TILE_GRAVEL" ; "33587232"; "6";"2400";"grvl"; "0"; "1"; "0"; "0"; "6"; "0"; "1"; "0";"N/A";"16"
"6"; "1";"TILE_GRAVEL_GREY" ; "33587232"; "6";"2400";"grvl"; "0"; "1"; "0"; "0"; "6"; "1"; "1"; "0";"N/A";"16"
"7"; "0";"TILE_ORE_MALACHITE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "0"; "0"; "0";"N/A";"16"
"7"; "1";"TILE_ORE_HEMATITE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "1"; "0"; "0";"N/A";"16"
"7"; "2";"TILE_ORE_NATURAL_GOLD" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "2"; "0"; "0";"N/A";"16"
"7"; "3";"TILE_ORE_NATURAL_SILVER" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "3"; "0"; "0";"N/A";"16"
"7"; "4";"TILE_ORE_RUTILE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "4"; "0"; "0";"N/A";"16"
"7"; "5";"TILE_ORE_AURICHALCUMITE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "5"; "0"; "0";"N/A";"16"
"8"; "0";"TILE_GEM_RUBY" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "0"; "0"; "0";"N/A";"16"
"8"; "1";"TILE_GEM_EMERALD" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "1"; "0"; "0";"N/A";"16"
"8"; "2";"TILE_GEM_SAPPHIRE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "2"; "0"; "0";"N/A";"16"
"8"; "3";"TILE_GEM_TOPAZ" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "3"; "0"; "0";"N/A";"16"
"8"; "4";"TILE_GEM_DIAMOND" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "4"; "0"; "0";"N/A";"16"
"8"; "5";"TILE_GEM_AMETHYST" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "5"; "0"; "0";"N/A";"16"
"9"; "0";"TILE_SNOW" ; "33587232"; "6"; "500";"snow"; "0"; "1"; "1"; "0"; "9"; "0"; "0"; "0";"N/A";"16"
"9"; "1";"TILE_ICE_FRAGILE" ; "13644813"; "1"; "930";"icei"; "0"; "1"; "0"; "0"; "9"; "1"; "0"; "0";"N/A";"16"
"9"; "2";"TILE_ICE_NATURAL" ; "27289626"; "25"; "930";"icei"; "0"; "1"; "1"; "0"; "9"; "2"; "0"; "0";"N/A"; "4"
"9"; "3";"TILE_ICE_CLEAR_MAGICAL" ; "33587232"; "25";"3720";"icex"; "0"; "1"; "1"; "19955770"; "9"; "3"; "0"; "0";"N/A"; "4"
"9"; "4";"TILE_GLASS_CRUDE" ; "3146755"; "1";"2500";"glas"; "0"; "1"; "1"; "0"; "9"; "4"; "0"; "0";"N/A";"16"
"9"; "5";"TILE_GLASS_CLEAN" ; "1049601"; "1";"2203";"glas"; "0"; "1"; "1"; "0"; "9"; "5"; "0"; "0";"N/A";"16"
"10"; "0";"TILE_PLATFORM_STONE" ; "8396808"; "1"; "N/A";"rock"; "0"; "0"; "0"; "0"; "10"; "0"; "0"; "0";"N/A";"16"
"10"; "1";"TILE_PLATFORM_WOODEN" ; "8396808"; "1"; "N/A";"wood"; "0"; "0"; "0"; "0"; "10"; "1"; "0"; "0";"N/A";"16"
"10"; "2";"TILE_PLATFORM_EBONY" ; "8396808"; "1"; "N/A";"wood"; "0"; "0"; "0"; "0"; "10"; "2"; "0"; "0";"N/A";"16"
"10"; "3";"TILE_PLATFORM_BIRCH" ; "8396808"; "1"; "N/A";"wood"; "0"; "0"; "0"; "0"; "10"; "3"; "0"; "0";"N/A";"16"
"10"; "4";"TILE_PLATFORM_BLOODROSE" ; "8396808"; "1"; "N/A";"wood"; "0"; "0"; "0"; "0"; "10"; "4"; "0"; "0";"N/A";"16"
"11"; "0";"TILE_TORCH" ; "8396808"; "0"; "N/A";"fxtr"; "0"; "0"; "0"; "267553792"; "11"; "0"; "0"; "1";"N/A";"16"
"11"; "1";"TILE_TORCH_FROST" ; "8396808"; "0"; "N/A";"fxtr"; "0"; "0"; "0"; "81916159"; "11"; "1"; "0"; "1";"N/A";"16"
"12"; "0";"TILE_TORCH" ; "8396808"; "0"; "N/A";"fxtr"; "0"; "0"; "0"; "0"; "11"; "0"; "0"; "0";"N/A";"16"
"12"; "1";"TILE_TORCH_FROST" ; "8396808"; "0"; "N/A";"fxtr"; "0"; "0"; "0"; "0"; "11"; "1"; "0"; "0";"N/A";"16"
"13"; "0";"TILE_ILLUMINATOR_WHITE" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "239319274"; "13"; "0"; "0"; "0";"N/A";"16"
"13"; "1";"TILE_ILLUMINATOR_YELLOW" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "267607040"; "13"; "1"; "0"; "0";"N/A";"16"
"13"; "2";"TILE_ILLUMINATOR_ORANGE" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "267546624"; "13"; "2"; "0"; "0";"N/A";"16"
"13"; "3";"TILE_ILLUMINATOR_RED" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "246415360"; "13"; "3"; "0"; "0";"N/A";"16"
"13"; "4";"TILE_ILLUMINATOR_FUCHSIA" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "246415543"; "13"; "4"; "0"; "0";"N/A";"16"
"13"; "5";"TILE_ILLUMINATOR_PURPLE" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "191889643"; "13"; "5"; "0"; "0";"N/A";"16"
"13"; "6";"TILE_ILLUMINATOR_BLUE" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "52479"; "13"; "6"; "0"; "0";"N/A";"16"
"13"; "7";"TILE_ILLUMINATOR_CYAN" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "219391"; "13"; "7"; "0"; "0";"N/A";"16"
"13"; "8";"TILE_ILLUMINATOR_GREEN" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "56884224"; "13"; "8"; "0"; "0";"N/A";"16"
"13"; "9";"TILE_ILLUMINATOR_GREEN_DARK";"8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "33660928"; "13"; "9"; "0"; "0";"N/A";"16"
"13"; "10";"TILE_ILLUMINATOR_BROWN" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "89161728"; "13"; "10"; "0"; "0";"N/A";"16"
"13"; "11";"TILE_ILLUMINATOR_TAN" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "157392948"; "13"; "11"; "0"; "0";"N/A";"16"
"13"; "12";"TILE_ILLUMINATOR_GREY_LIGHT";"8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "198374589"; "13"; "12"; "0"; "0";"N/A";"16"
"13"; "13";"TILE_ILLUMINATOR_GREY_MED"; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "122803317"; "13"; "13"; "0"; "0";"N/A";"16"
"13"; "14";"TILE_ILLUMINATOR_GREY_DARK"; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "68224065"; "13"; "14"; "0"; "0";"N/A";"16"
"13"; "15";"TILE_ILLUMINATOR_BLACK" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "116392191"; "13"; "15"; "0"; "0";"N/A";"16"
"14"; "0";"TILE_ILLUMINATOR_WHITE" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "0"; "0"; "0";"N/A";"16"
"14"; "1";"TILE_ILLUMINATOR_YELLOW" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "1"; "0"; "0";"N/A";"16"
"14"; "2";"TILE_ILLUMINATOR_ORANGE" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "2"; "0"; "0";"N/A";"16"
"14"; "3";"TILE_ILLUMINATOR_RED" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "3"; "0"; "0";"N/A";"16"
"14"; "4";"TILE_ILLUMINATOR_FUCHSIA" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "4"; "0"; "0";"N/A";"16"
"14"; "5";"TILE_ILLUMINATOR_PURPLE" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "5"; "0"; "0";"N/A";"16"
"14"; "6";"TILE_ILLUMINATOR_BLUE" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "6"; "0"; "0";"N/A";"16"
"14"; "7";"TILE_ILLUMINATOR_CYAN" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "7"; "0"; "0";"N/A";"16"
"14"; "8";"TILE_ILLUMINATOR_GREEN" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "8"; "0"; "0";"N/A";"16"
"14"; "9";"TILE_ILLUMINATOR_GREEN_DARK";"33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "9"; "0"; "0";"N/A";"16"
"14"; "10";"TILE_ILLUMINATOR_BROWN" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "10"; "0"; "0";"N/A";"16"
"14"; "11";"TILE_ILLUMINATOR_TAN" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "11"; "0"; "0";"N/A";"16"
"14"; "12";"TILE_ILLUMINATOR_GREY_LIGHT";"33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "12"; "0"; "0";"N/A";"16"
"14"; "13";"TILE_ILLUMINATOR_GREY_MED"; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "13"; "0"; "0";"N/A";"16"
"14"; "14";"TILE_ILLUMINATOR_GREY_DARK";"33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "14"; "0"; "0";"N/A";"16"
"14"; "15";"TILE_ILLUMINATOR_BLACK" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "15"; "0"; "0";"N/A";"16"
"15"; "0";"TILE_SANDSTONE" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "0"; "0"; "0";"N/A";"16"
"15"; "1";"TILE_SANDSTONE_WHITE" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "1"; "0"; "0";"N/A";"16"
"15"; "2";"TILE_SANDSTONE_RED" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "2"; "0"; "0";"N/A";"16"
"15"; "3";"TILE_SANDSTONE_DESERT" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "3"; "0"; "0";"N/A";"16"
"15"; "4";"TILE_SANDSTONE_BLACK" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "4"; "0"; "0";"N/A";"16"
"15"; "5";"TILE_SANDSTONE_BLACK" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "5"; "0"; "0";"N/A";"16"
"16"; "0";"TILE_LANTERN_IRON_REGULAR"; "8396808"; "0"; "N/A";"fxtr"; "0"; "0"; "0"; "266453040"; "16"; "0"; "0"; "0";"N/A";"16"
"16"; "1";"TILE_SUNSTONE" ; "33587232"; "0"; "N/A";"rock"; "0"; "1"; "0"; "0"; "16"; "1"; "0"; "2";"N/A";"16"
"16"; "2";"TILE_DAYLIGHT_CAPACITOR" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "0"; "0"; "16"; "2"; "0"; "3";"N/A";"16"
"254"; "0";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "1";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "2";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "3";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "4";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "5";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "6";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "7";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "8";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "9";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "10";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "11";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "12";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "13";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "14";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"254"; "15";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32";"16"
"255"; "0";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "1";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "2";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "3";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "4";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "5";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "6";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "7";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "8";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "9";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "10";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "11";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "12";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "13";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "14";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"255"; "15";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16";"16"
"256"; "0";"TILE_NULL" ; "0"; "-1";"2600";"null"; "0"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0";"N/A";"16"
"id";"dmg";"name" ; "opacity";"strength";"dsty";"mate";"fluid";"solid";"wall"; "lumcolor";"drop";"ddmg";"fall";"dlfn";"vscs";"fv";"friction"
"0"; "0";"TILE_AIR" ; "8396808"; "0"; "1";"null"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "0"; "N/A"; "0";"4"
"1"; "0";"TILE_STONE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "1"; "0"; "1"; "0"; "0"; "0"; "N/A"; "0";"16"
"1"; "1";"TILE_STONE_QUARRIED" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "1"; "0"; "1"; "1"; "0"; "0"; "N/A"; "0";"16"
"1"; "2";"TILE_STONE_TILE_WHITE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "1"; "0"; "1"; "2"; "0"; "0"; "N/A"; "0";"16"
"1"; "3";"TILE_STONE_BRICKS" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "1"; "0"; "1"; "3"; "0"; "0"; "N/A"; "0";"16"
"2"; "0";"TILE_DIRT" ; "33587232"; "6";"1400";"dirt"; "0"; "1"; "1"; "0"; "2"; "0"; "0"; "0"; "N/A"; "0";"16"
"2"; "1";"TILE_GRASS" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "1"; "0"; "0"; "N/A"; "0";"16"
"2"; "2";"TILE_FOLIAGE_GREEN" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "2"; "0"; "0"; "N/A"; "0";"16"
"2"; "3";"TILE_FOLIAGE_LIME" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "3"; "0"; "0"; "N/A"; "0";"16"
"2"; "4";"TILE_FOLIAGE_GOLD" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "4"; "0"; "0"; "N/A"; "0";"16"
"2"; "5";"TILE_FOLIAGE_RED" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "5"; "0"; "0"; "N/A"; "0";"16"
"2"; "6";"TILE_FOLIAGE_ICEBLUE" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "6"; "0"; "0"; "N/A"; "0";"16"
"2"; "7";"TILE_FOLIAGE_PURPLE" ; "33587232"; "6";"1400";"grss"; "0"; "1"; "1"; "0"; "2"; "7"; "0"; "0"; "N/A"; "0";"16"
"3"; "0";"TILE_PLANK_NORMAL" ; "33587232"; "12"; "740";"wood"; "0"; "1"; "1"; "0"; "3"; "0"; "0"; "0"; "N/A"; "0";"16"
"3"; "1";"TILE_PLANK_EBONY" ; "33587232"; "12";"1200";"wood"; "0"; "1"; "1"; "0"; "3"; "1"; "0"; "0"; "N/A"; "0";"16"
"3"; "2";"TILE_PLANK_BIRCH" ; "33587232"; "12"; "670";"wood"; "0"; "1"; "1"; "0"; "3"; "2"; "0"; "0"; "N/A"; "0";"16"
"3"; "3";"TILE_PLANK_BLOODROSE" ; "33587232"; "12"; "900";"wood"; "0"; "1"; "1"; "0"; "3"; "3"; "0"; "0"; "N/A"; "0";"16"
"4"; "0";"TILE_TRUNK_NORMAL" ; "33587232"; "12"; "740";"wood"; "0"; "1"; "0"; "0"; "3"; "0"; "0"; "0"; "N/A"; "0";"16"
"4"; "1";"TILE_TRUNK_EBONY" ; "33587232"; "12";"1200";"wood"; "0"; "1"; "0"; "0"; "3"; "1"; "0"; "0"; "N/A"; "0";"16"
"4"; "2";"TILE_TRUNK_BIRCH" ; "33587232"; "12"; "670";"wood"; "0"; "1"; "0"; "0"; "3"; "2"; "0"; "0"; "N/A"; "0";"16"
"4"; "3";"TILE_TRUNK_BLOODROSE" ; "33587232"; "12"; "900";"wood"; "0"; "1"; "0"; "0"; "3"; "3"; "0"; "0"; "N/A"; "0";"16"
"5"; "0";"TILE_SAND" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "0"; "1"; "0"; "N/A"; "0";"16"
"5"; "1";"TILE_SAND_WHITE" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "1"; "1"; "0"; "N/A"; "0";"16"
"5"; "2";"TILE_SAND_RED" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "2"; "1"; "0"; "N/A"; "0";"16"
"5"; "3";"TILE_SAND_DESERT" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "3"; "1"; "0"; "N/A"; "0";"16"
"5"; "4";"TILE_SAND_BLACK" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "4"; "1"; "0"; "N/A"; "0";"16"
"5"; "5";"TILE_SAND_GREEN" ; "33587232"; "6";"2400";"sand"; "0"; "1"; "0"; "0"; "5"; "5"; "1"; "0"; "N/A"; "0";"16"
"6"; "0";"TILE_GRAVEL" ; "33587232"; "6";"2400";"grvl"; "0"; "1"; "0"; "0"; "6"; "0"; "1"; "0"; "N/A"; "0";"16"
"6"; "1";"TILE_GRAVEL_GREY" ; "33587232"; "6";"2400";"grvl"; "0"; "1"; "0"; "0"; "6"; "1"; "1"; "0"; "N/A"; "0";"16"
"7"; "0";"TILE_ORE_MALACHITE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "0"; "0"; "0"; "N/A"; "0";"16"
"7"; "1";"TILE_ORE_HEMATITE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "1"; "0"; "0"; "N/A"; "0";"16"
"7"; "2";"TILE_ORE_NATURAL_GOLD" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "2"; "0"; "0"; "N/A"; "0";"16"
"7"; "3";"TILE_ORE_NATURAL_SILVER" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "3"; "0"; "0"; "N/A"; "0";"16"
"7"; "4";"TILE_ORE_RUTILE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "4"; "0"; "0"; "N/A"; "0";"16"
"7"; "5";"TILE_ORE_AURICHALCUMITE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "7"; "5"; "0"; "0"; "N/A"; "0";"16"
"8"; "0";"TILE_GEM_RUBY" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "0"; "0"; "0"; "N/A"; "0";"16"
"8"; "1";"TILE_GEM_EMERALD" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "1"; "0"; "0"; "N/A"; "0";"16"
"8"; "2";"TILE_GEM_SAPPHIRE" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "2"; "0"; "0"; "N/A"; "0";"16"
"8"; "3";"TILE_GEM_TOPAZ" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "3"; "0"; "0"; "N/A"; "0";"16"
"8"; "4";"TILE_GEM_DIAMOND" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "4"; "0"; "0"; "N/A"; "0";"16"
"8"; "5";"TILE_GEM_AMETHYST" ; "33587232"; "25";"2400";"rock"; "0"; "1"; "0"; "0"; "8"; "5"; "0"; "0"; "N/A"; "0";"16"
"9"; "0";"TILE_SNOW" ; "33587232"; "6"; "500";"snow"; "0"; "1"; "1"; "0"; "9"; "0"; "0"; "0"; "N/A"; "0";"16"
"9"; "1";"TILE_ICE_FRAGILE" ; "13644813"; "1"; "930";"icei"; "0"; "1"; "0"; "0"; "9"; "1"; "0"; "0"; "N/A"; "0";"16"
"9"; "2";"TILE_ICE_NATURAL" ; "27289626"; "25"; "930";"icei"; "0"; "1"; "1"; "0"; "9"; "2"; "0"; "0"; "N/A"; "0"; "4"
"9"; "3";"TILE_ICE_CLEAR_MAGICAL" ; "33587232"; "25";"3720";"icex"; "0"; "1"; "1"; "19955770"; "9"; "3"; "0"; "0"; "N/A"; "0"; "4"
"9"; "4";"TILE_GLASS_CRUDE" ; "3146755"; "1";"2500";"glas"; "0"; "1"; "1"; "0"; "9"; "4"; "0"; "0"; "N/A"; "0";"16"
"9"; "5";"TILE_GLASS_CLEAN" ; "1049601"; "1";"2203";"glas"; "0"; "1"; "1"; "0"; "9"; "5"; "0"; "0"; "N/A"; "0";"16"
"10"; "0";"TILE_PLATFORM_STONE" ; "8396808"; "1"; "N/A";"rock"; "0"; "0"; "0"; "0"; "10"; "0"; "0"; "0"; "N/A"; "0";"16"
"10"; "1";"TILE_PLATFORM_WOODEN" ; "8396808"; "1"; "N/A";"wood"; "0"; "0"; "0"; "0"; "10"; "1"; "0"; "0"; "N/A"; "0";"16"
"10"; "2";"TILE_PLATFORM_EBONY" ; "8396808"; "1"; "N/A";"wood"; "0"; "0"; "0"; "0"; "10"; "2"; "0"; "0"; "N/A"; "0";"16"
"10"; "3";"TILE_PLATFORM_BIRCH" ; "8396808"; "1"; "N/A";"wood"; "0"; "0"; "0"; "0"; "10"; "3"; "0"; "0"; "N/A"; "0";"16"
"10"; "4";"TILE_PLATFORM_BLOODROSE" ; "8396808"; "1"; "N/A";"wood"; "0"; "0"; "0"; "0"; "10"; "4"; "0"; "0"; "N/A"; "0";"16"
"11"; "0";"TILE_TORCH" ; "8396808"; "0"; "N/A";"fxtr"; "0"; "0"; "0"; "267553792"; "11"; "0"; "0"; "1"; "N/A"; "0";"16"
"11"; "1";"TILE_TORCH_FROST" ; "8396808"; "0"; "N/A";"fxtr"; "0"; "0"; "0"; "81916159"; "11"; "1"; "0"; "1"; "N/A"; "0";"16"
"12"; "0";"TILE_TORCH" ; "8396808"; "0"; "N/A";"fxtr"; "0"; "0"; "0"; "0"; "11"; "0"; "0"; "0"; "N/A"; "0";"16"
"12"; "1";"TILE_TORCH_FROST" ; "8396808"; "0"; "N/A";"fxtr"; "0"; "0"; "0"; "0"; "11"; "1"; "0"; "0"; "N/A"; "0";"16"
"13"; "0";"TILE_ILLUMINATOR_WHITE" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "239319274"; "13"; "0"; "0"; "0"; "N/A"; "0";"16"
"13"; "1";"TILE_ILLUMINATOR_YELLOW" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "267607040"; "13"; "1"; "0"; "0"; "N/A"; "0";"16"
"13"; "2";"TILE_ILLUMINATOR_ORANGE" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "267546624"; "13"; "2"; "0"; "0"; "N/A"; "0";"16"
"13"; "3";"TILE_ILLUMINATOR_RED" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "246415360"; "13"; "3"; "0"; "0"; "N/A"; "0";"16"
"13"; "4";"TILE_ILLUMINATOR_FUCHSIA" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "246415543"; "13"; "4"; "0"; "0"; "N/A"; "0";"16"
"13"; "5";"TILE_ILLUMINATOR_PURPLE" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "191889643"; "13"; "5"; "0"; "0"; "N/A"; "0";"16"
"13"; "6";"TILE_ILLUMINATOR_BLUE" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "52479"; "13"; "6"; "0"; "0"; "N/A"; "0";"16"
"13"; "7";"TILE_ILLUMINATOR_CYAN" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "219391"; "13"; "7"; "0"; "0"; "N/A"; "0";"16"
"13"; "8";"TILE_ILLUMINATOR_GREEN" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "56884224"; "13"; "8"; "0"; "0"; "N/A"; "0";"16"
"13"; "9";"TILE_ILLUMINATOR_GREEN_DARK";"8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "33660928"; "13"; "9"; "0"; "0"; "N/A"; "0";"16"
"13"; "10";"TILE_ILLUMINATOR_BROWN" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "89161728"; "13"; "10"; "0"; "0"; "N/A"; "0";"16"
"13"; "11";"TILE_ILLUMINATOR_TAN" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "157392948"; "13"; "11"; "0"; "0"; "N/A"; "0";"16"
"13"; "12";"TILE_ILLUMINATOR_GREY_LIGHT";"8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "198374589"; "13"; "12"; "0"; "0"; "N/A"; "0";"16"
"13"; "13";"TILE_ILLUMINATOR_GREY_MED"; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "122803317"; "13"; "13"; "0"; "0"; "N/A"; "0";"16"
"13"; "14";"TILE_ILLUMINATOR_GREY_DARK"; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "68224065"; "13"; "14"; "0"; "0"; "N/A"; "0";"16"
"13"; "15";"TILE_ILLUMINATOR_BLACK" ; "8396808"; "0"; "N/A";"glas"; "0"; "1"; "1"; "116392191"; "13"; "15"; "0"; "0"; "N/A"; "0";"16"
"14"; "0";"TILE_ILLUMINATOR_WHITE" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "0"; "0"; "0"; "N/A"; "0";"16"
"14"; "1";"TILE_ILLUMINATOR_YELLOW" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "1"; "0"; "0"; "N/A"; "0";"16"
"14"; "2";"TILE_ILLUMINATOR_ORANGE" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "2"; "0"; "0"; "N/A"; "0";"16"
"14"; "3";"TILE_ILLUMINATOR_RED" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "3"; "0"; "0"; "N/A"; "0";"16"
"14"; "4";"TILE_ILLUMINATOR_FUCHSIA" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "4"; "0"; "0"; "N/A"; "0";"16"
"14"; "5";"TILE_ILLUMINATOR_PURPLE" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "5"; "0"; "0"; "N/A"; "0";"16"
"14"; "6";"TILE_ILLUMINATOR_BLUE" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "6"; "0"; "0"; "N/A"; "0";"16"
"14"; "7";"TILE_ILLUMINATOR_CYAN" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "7"; "0"; "0"; "N/A"; "0";"16"
"14"; "8";"TILE_ILLUMINATOR_GREEN" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "8"; "0"; "0"; "N/A"; "0";"16"
"14"; "9";"TILE_ILLUMINATOR_GREEN_DARK";"33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "9"; "0"; "0"; "N/A"; "0";"16"
"14"; "10";"TILE_ILLUMINATOR_BROWN" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "10"; "0"; "0"; "N/A"; "0";"16"
"14"; "11";"TILE_ILLUMINATOR_TAN" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "11"; "0"; "0"; "N/A"; "0";"16"
"14"; "12";"TILE_ILLUMINATOR_GREY_LIGHT";"33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "12"; "0"; "0"; "N/A"; "0";"16"
"14"; "13";"TILE_ILLUMINATOR_GREY_MED"; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "13"; "0"; "0"; "N/A"; "0";"16"
"14"; "14";"TILE_ILLUMINATOR_GREY_DARK";"33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "14"; "0"; "0"; "N/A"; "0";"16"
"14"; "15";"TILE_ILLUMINATOR_BLACK" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "1"; "0"; "13"; "15"; "0"; "0"; "N/A"; "0";"16"
"15"; "0";"TILE_SANDSTONE" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "0"; "0"; "0"; "N/A"; "0";"16"
"15"; "1";"TILE_SANDSTONE_WHITE" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "1"; "0"; "0"; "N/A"; "0";"16"
"15"; "2";"TILE_SANDSTONE_RED" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "2"; "0"; "0"; "N/A"; "0";"16"
"15"; "3";"TILE_SANDSTONE_DESERT" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "3"; "0"; "0"; "N/A"; "0";"16"
"15"; "4";"TILE_SANDSTONE_BLACK" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "4"; "0"; "0"; "N/A"; "0";"16"
"15"; "5";"TILE_SANDSTONE_BLACK" ; "33587232"; "25";"1900";"rock"; "0"; "1"; "1"; "0"; "15"; "5"; "0"; "0"; "N/A"; "0";"16"
"16"; "0";"TILE_LANTERN_IRON_REGULAR"; "8396808"; "0"; "N/A";"fxtr"; "0"; "0"; "0"; "266453040"; "16"; "0"; "0"; "0"; "N/A"; "0";"16"
"16"; "1";"TILE_SUNSTONE" ; "33587232"; "0"; "N/A";"rock"; "0"; "1"; "0"; "0"; "16"; "1"; "0"; "2"; "N/A"; "0";"16"
"16"; "2";"TILE_DAYLIGHT_CAPACITOR" ; "33587232"; "0"; "N/A";"glas"; "0"; "1"; "0"; "0"; "16"; "2"; "0"; "3"; "N/A"; "0";"16"
"254"; "0";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "1";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "2";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "3";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "4";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "5";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "6";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "7";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "8";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "9";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "10";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "11";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "12";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "13";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "14";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"254"; "15";"TILE_LAVA" ;"260301048"; "100";"2600";"rock"; "1"; "0"; "0"; "205574144"; "N/A"; "N/A"; "0"; "0"; "32"; "0";"16"
"255"; "0";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "1";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "2";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "3";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "4";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "5";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "6";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "7";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "8";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "9";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "10";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "11";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "12";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "13";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "14";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"255"; "15";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16"
"256"; "0";"TILE_NULL" ; "0"; "-1";"2600";"null"; "0"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "N/A"; "0";"16"
## Notes ##
@@ -155,6 +155,8 @@ object TilePropCSV {
# mate: material, four-letter code
# fv: vertical friction (boolean)
## Illuminators ##

View File

@@ -65,7 +65,12 @@ class ConsoleWindow : UICanvas, KeyboardControlled {
// text and cursor
g.color = Color.white
g.drawString(input, 1f + drawOffX, drawOffY)
g.color = Color(0x7f7f7f)
g.fillRect(inputDrawWidth.toFloat() + drawOffX + 1, drawOffY, 2f, inputDrawHeight.toFloat())
g.color = Color.white
g.fillRect(inputDrawWidth.toFloat() + drawOffX + 1, drawOffY, 1f, inputDrawHeight.toFloat() - 1)
// messages
for (i in 0..MESSAGES_DISPLAY_COUNT - 1) {
@@ -85,13 +90,13 @@ class ConsoleWindow : UICanvas, KeyboardControlled {
historyIndex = -1
// execute
if (key == Key.RETURN && commandInputPool!!.length > 0) {
if (key == Key.RETURN && commandInputPool!!.isNotEmpty()) {
commandHistory.add(commandInputPool!!.toString())
executeCommand()
commandInputPool = StringBuilder()
}
// erase last letter
else if (key == Key.BACKSPACE && commandInputPool!!.length > 0) {
else if (key == Key.BACKSPACE && commandInputPool!!.isNotEmpty()) {
commandInputPool!!.deleteCharAt(commandInputPool!!.length - 1)
}
// append acceptable letter

View File

@@ -7,6 +7,9 @@ import net.torvald.random.HQRNG
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blendMul
import net.torvald.terrarum.blendNormal
import net.torvald.terrarum.gameactors.ParticleTestRain
import net.torvald.terrarum.gamecontroller.Key
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gameworld.WorldTime
import net.torvald.terrarum.getPixel
import org.newdawn.slick.Color
@@ -76,6 +79,16 @@ object WeatherMixer {
fun update(gc: GameContainer, delta: Int) {
currentWeather = weatherList[WEATHER_GENERIC]!![0]
// test rain toggled by F2
if (KeyToggler.isOn(Key.F2)) {
val playerPos = Terrarum.ingame.player.centrePosPoint
val rainParticle = ParticleTestRain(
playerPos.x + HQRNG().nextInt(Terrarum.WIDTH) - Terrarum.HALFW,
playerPos.y - Terrarum.HALFH
)
Terrarum.ingame.addActor(rainParticle)
}
}
fun render(g: Graphics) {