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 5db3aadaf4
commit 4acc797fee
49 changed files with 752 additions and 428 deletions

View File

@@ -20,3 +20,13 @@ Colour overlay is set to 6 500 K as untouched. The value must be
## Sunlight ## ## 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.point.Point2d
import net.torvald.terrarum.gameactors.Actor 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 net.torvald.terrarum.gameactors.sqr
import java.util.* import java.util.*
@@ -23,7 +23,7 @@ class KDHeapifiedTree() {
private val dimension = 2 private val dimension = 2
private val initialSize = 128 private val initialSize = 128
private val nodes = Array<ActorWithBody?>(initialSize, { null }) private val nodes = Array<ActorWithSprite?>(initialSize, { null })
private val root: Int = 0 private val root: Int = 0
@@ -34,13 +34,13 @@ class KDHeapifiedTree() {
private fun Int.getActor() = nodes[this] private fun Int.getActor() = nodes[this]
private fun Int.getLeft() = this * 2 + 1 private fun Int.getLeft() = this * 2 + 1
private fun Int.getRight() = this * 2 + 2 private fun Int.getRight() = this * 2 + 2
private fun Int.set(value: ActorWithBody?) { nodes[this] = value } private fun Int.set(value: ActorWithSprite?) { nodes[this] = value }
private fun Int.setLeftChild(value: ActorWithBody?) { nodes[this.getLeft()] = value } private fun Int.setLeftChild(value: ActorWithSprite?) { nodes[this.getLeft()] = value }
private fun Int.setRightChild(value: ActorWithBody?) { nodes[this.getRight()] = value } private fun Int.setRightChild(value: ActorWithSprite?) { nodes[this.getRight()] = value }
private val zeroPoint = Point2d(0.0, 0.0) 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()) { if (points.isEmpty()) {
index.set(null) index.set(null)
@@ -91,7 +91,7 @@ class KDHeapifiedTree() {
private fun expandArray() { private fun expandArray() {
val prevNodes = nodes.copyOf() val prevNodes = nodes.copyOf()
Array<ActorWithBody?>(prevNodes.size * 2, { null }) Array<ActorWithSprite?>(prevNodes.size * 2, { null })
create(prevNodes.toList(), 0, 0) create(prevNodes.toList(), 0, 0)
} }

View File

@@ -7,19 +7,15 @@ package net.torvald.spriteanimation
import net.torvald.terrarum.StateInGame import net.torvald.terrarum.StateInGame
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import com.jme3.math.FastMath 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.Graphics
import org.newdawn.slick.Image import org.newdawn.slick.Image
import org.newdawn.slick.SlickException import org.newdawn.slick.SlickException
import org.newdawn.slick.SpriteSheet 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 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 currentFrame = 1 // one-based!
private var currentRow = 1 // one-based! private var currentRow = 1 // one-based!
private var nFrames: Int = 1 private var nFrames: Int = 1
@@ -47,11 +43,11 @@ class SpriteAnimation(val parentActor: ActorWithBody) {
* @throws SlickException * @throws SlickException
*/ */
fun setSpriteImage(imagePath: String) { fun setSpriteImage(imagePath: String) {
spriteImage = SpriteSheet(imagePath, this.width, this.height) spriteImage = SpriteSheet(imagePath, cellWidth, cellHeight)
} }
fun setSpriteImage(image: Image) { 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 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 * Sets sheet rows and animation frames. Will default to
* 1, 1 (still image of top left from the sheet) if not called. * 1, 1 (still image of top left from the sheet) if not called.
@@ -115,6 +101,10 @@ class SpriteAnimation(val parentActor: ActorWithBody) {
* @param scale * @param scale
*/ */
@JvmOverloads fun render(g: Graphics, posX: Float, posY: Float, scale: Float = 1f) { @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 // Null checking
if (currentImage == null) { if (currentImage == null) {
currentImage = getScaledSprite(scale) currentImage = getScaledSprite(scale)
@@ -131,8 +121,8 @@ class SpriteAnimation(val parentActor: ActorWithBody) {
flippedImage.draw( flippedImage.draw(
Math.round(posX).toFloat(), Math.round(posX).toFloat(),
FastMath.floor(posY).toFloat(), FastMath.floor(posY).toFloat(),
FastMath.floor(width * scale).toFloat(), FastMath.floor(cellWidth * scale).toFloat(),
FastMath.floor(height * 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.WorldGenerator
import net.torvald.terrarum.mapgenerator.RoguelikeRandomiser import net.torvald.terrarum.mapgenerator.RoguelikeRandomiser
import net.torvald.terrarum.tileproperties.TileCodex import net.torvald.terrarum.tileproperties.TileCodex
import net.torvald.terrarum.tileproperties.TilePropUtil
import net.torvald.terrarum.tilestats.TileStats import net.torvald.terrarum.tilestats.TileStats
import net.torvald.terrarum.ui.* import net.torvald.terrarum.ui.*
import net.torvald.terrarum.weather.WeatherMixer import net.torvald.terrarum.weather.WeatherMixer
@@ -36,6 +37,8 @@ import org.newdawn.slick.state.StateBasedGame
import shader.Shader import shader.Shader
import java.lang.management.ManagementFactory import java.lang.management.ManagementFactory
import java.util.* import java.util.*
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
/** /**
* Created by minjaesong on 15-12-30. * Created by minjaesong on 15-12-30.
@@ -56,10 +59,10 @@ constructor() : BasicGameState() {
val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE) val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
val uiContainer = ArrayList<UIHandler>() val uiContainer = ArrayList<UIHandler>()
private val actorsRenderBehind = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE) private val actorsRenderBehind = ArrayList<ActorVisible>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderMiddle = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE) private val actorsRenderMiddle = ArrayList<ActorVisible>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderMidTop = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE) private val actorsRenderMidTop = ArrayList<ActorVisible>(ACTORCONTAINER_INITIAL_SIZE)
private val actorsRenderFront = ArrayList<ActorWithBody>(ACTORCONTAINER_INITIAL_SIZE) private val actorsRenderFront = ArrayList<ActorVisible>(ACTORCONTAINER_INITIAL_SIZE)
lateinit var consoleHandler: UIHandler lateinit var consoleHandler: UIHandler
lateinit var debugWindow: UIHandler lateinit var debugWindow: UIHandler
@@ -127,8 +130,6 @@ constructor() : BasicGameState() {
// add new player and put it to actorContainer // add new player and put it to actorContainer
playableActorDelegate = PlayableActorDelegate(PlayerBuilderSigrid()) playableActorDelegate = PlayableActorDelegate(PlayerBuilderSigrid())
//player = PBCynthia.create()
//player.setNoClip(true);
addActor(player) addActor(player)
@@ -185,8 +186,9 @@ constructor() : BasicGameState() {
/////////////////////////// ///////////////////////////
// world-related updates // // world-related updates //
/////////////////////////// ///////////////////////////
TilePropUtil.dynamicLumFuncTickClock()
world.updateWorldTime(delta) world.updateWorldTime(delta)
WorldSimulator(world, player, delta) WorldSimulator(player, delta)
WeatherMixer.update(gc, delta) WeatherMixer.update(gc, delta)
TileStats.update() TileStats.update()
if (!(CommandDict["setgl"] as SetGlobalLightOverride).lightOverride) if (!(CommandDict["setgl"] as SetGlobalLightOverride).lightOverride)
@@ -255,9 +257,13 @@ constructor() : BasicGameState() {
private fun repossessActor() { private fun repossessActor() {
// check if currently pocessed actor is removed from game // check if currently pocessed actor is removed from game
if (!hasActor(player)) if (!hasActor(player)) {
// re-possess canonical player // re-possess canonical player
changePossession(Player.PLAYER_REF_ID) // TODO completely other behaviour? 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) { private fun changePossession(newActor: PlayableActorDelegate) {
@@ -266,7 +272,7 @@ constructor() : BasicGameState() {
} }
playableActorDelegate = newActor playableActorDelegate = newActor
WorldSimulator(world, player, UPDATE_DELTA) WorldSimulator(player, UPDATE_DELTA)
} }
private fun changePossession(refid: Int) { private fun changePossession(refid: Int) {
@@ -280,8 +286,8 @@ constructor() : BasicGameState() {
playableActorDelegate!!.actor.collisionType = HumanoidNPC.DEFAULT_COLLISION_TYPE playableActorDelegate!!.actor.collisionType = HumanoidNPC.DEFAULT_COLLISION_TYPE
// accept new delegate // accept new delegate
playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid) playableActorDelegate = PlayableActorDelegate(getActorByID(refid) as ActorHumanoid)
playableActorDelegate!!.actor.collisionType = ActorWithBody.COLLISION_KINEMATIC playableActorDelegate!!.actor.collisionType = ActorWithSprite.COLLISION_KINEMATIC
WorldSimulator(world, player, UPDATE_DELTA) WorldSimulator(player, UPDATE_DELTA)
} }
private fun setAppTitle() { private fun setAppTitle() {
@@ -325,7 +331,7 @@ constructor() : BasicGameState() {
actorsRenderMidTop.forEach { actor -> actor.drawBody(worldG) } actorsRenderMidTop.forEach { actor -> actor.drawBody(worldG) }
player.drawBody(worldG) player.drawBody(worldG)
actorsRenderFront.forEach { actor -> actor.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) } actorsRenderMidTop.forEach { actor -> actor.drawGlow(worldG) }
player.drawGlow(worldG) player.drawGlow(worldG)
actorsRenderFront.forEach { actor -> actor.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 // draw reference ID if debugWindow is open
if (debugWindow.isVisible) { if (debugWindow.isVisible) {
actorContainer.forEachIndexed { i, actor -> actorContainer.forEachIndexed { i, actor ->
if (actor is ActorWithBody) { if (actor is ActorVisible) {
worldG.color = Color.white worldG.color = Color.white
worldG.font = Terrarum.fontSmallNumbers worldG.font = Terrarum.fontSmallNumbers
worldG.drawString( worldG.drawString(
@@ -401,6 +407,13 @@ constructor() : BasicGameState() {
///////////////// /////////////////
gwin.drawImage(worldDrawFrameBuffer.getScaledCopy(screenZoom), 0f, 0f) gwin.drawImage(worldDrawFrameBuffer.getScaledCopy(screenZoom), 0f, 0f)
gwin.drawImage(uisDrawFrameBuffer, 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) { override fun keyPressed(key: Int, c: Char) {
@@ -484,7 +497,7 @@ constructor() : BasicGameState() {
while (i < actorContainerSize) { // loop through actorContainerInactive while (i < actorContainerSize) { // loop through actorContainerInactive
val actor = actorContainerInactive[i] val actor = actorContainerInactive[i]
val actorIndex = i val actorIndex = i
if (actor is ActorWithBody && actor.inUpdateRange()) { if (actor is ActorVisible && actor.inUpdateRange()) {
addActor(actor) // duplicates are checked here addActor(actor) // duplicates are checked here
actorContainerInactive.removeAt(actorIndex) actorContainerInactive.removeAt(actorIndex)
actorContainerSize -= 1 actorContainerSize -= 1
@@ -507,12 +520,12 @@ constructor() : BasicGameState() {
val actorIndex = i val actorIndex = i
// kill actors flagged to despawn // kill actors flagged to despawn
if (actor.flagDespawn) { if (actor.flagDespawn) {
actorContainer.removeAt(actorIndex) removeActor(actor)
actorContainerSize -= 1 actorContainerSize -= 1
i-- // array removed 1 elem, so we also decrement counter by 1 i-- // array removed 1 elem, so we also decrement counter by 1
} }
// inactivate distant actors // 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. 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 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 } d.forEach { if (it < ret) ret = it }
return ret 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 min(// take min of normal position and wrapped (x < 0) position
(a.hitbox.centeredX - p.hitbox.centeredX).sqr() + (a.hitbox.centeredX - p.hitbox.centeredX).sqr() +
(a.hitbox.centeredY - p.hitbox.centeredY).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.centeredX - p.hitbox.centeredX - world.width * TILE_SIZE).sqr() +
(a.hitbox.centeredY - p.hitbox.centeredY).sqr() (a.hitbox.centeredY - p.hitbox.centeredY).sqr()
) )
private fun distToCameraSqr(a: ActorWithBody) = private fun distToCameraSqr(a: ActorVisible) =
min( min(
(a.hitbox.posX - MapCamera.x).sqr() + (a.hitbox.posX - MapCamera.x).sqr() +
(a.hitbox.posY - MapCamera.y).sqr(), (a.hitbox.posY - MapCamera.y).sqr(),
@@ -579,14 +592,14 @@ constructor() : BasicGameState() {
) )
/** whether the actor is within screen */ /** whether the actor is within screen */
private fun ActorWithBody.inScreen() = private fun ActorVisible.inScreen() =
distToCameraSqr(this) <= distToCameraSqr(this) <=
(Terrarum.WIDTH.plus(this.hitbox.width.div(2)).times(1 / Terrarum.ingame.screenZoom).sqr() + (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()) Terrarum.HEIGHT.plus(this.hitbox.height.div(2)).times(1 / Terrarum.ingame.screenZoom).sqr())
/** whether the actor is within update range */ /** 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 * actorContainer extensions
@@ -596,8 +609,21 @@ constructor() : BasicGameState() {
fun hasActor(ID: Int): Boolean = fun hasActor(ID: Int): Boolean =
if (actorContainer.size == 0) if (actorContainer.size == 0)
false false
else else {
actorContainer.binarySearch(ID) >= 0 // 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)) fun removeActor(ID: Int) = removeActor(getActorByID(ID))
/** /**
@@ -616,7 +642,7 @@ constructor() : BasicGameState() {
// indexToDelete >= 0 means that the actor certainly exists in the game // indexToDelete >= 0 means that the actor certainly exists in the game
// which means we don't need to check if i >= 0 again // which means we don't need to check if i >= 0 again
if (actor is ActorWithBody) { if (actor is ActorVisible) {
when (actor.renderOrder) { when (actor.renderOrder) {
ActorOrder.BEHIND -> { ActorOrder.BEHIND -> {
val i = actorsRenderBehind.binarySearch(actor.referenceID) val i = actorsRenderBehind.binarySearch(actor.referenceID)
@@ -648,12 +674,12 @@ constructor() : BasicGameState() {
actorContainer.add(actor) actorContainer.add(actor)
insertionSortLastElem(actorContainer) // we can do this as we are only adding single 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) { when (actor.renderOrder) {
ActorOrder.BEHIND -> actorsRenderBehind.add(actor) ActorOrder.BEHIND -> { actorsRenderBehind.add(actor); insertionSortLastElemAV(actorsRenderBehind) }
ActorOrder.MIDDLE -> actorsRenderMiddle.add(actor) ActorOrder.MIDDLE -> { actorsRenderMiddle.add(actor); insertionSortLastElemAV(actorsRenderMiddle) }
ActorOrder.MIDTOP -> actorsRenderMidTop.add(actor) ActorOrder.MIDTOP -> { actorsRenderMidTop.add(actor); insertionSortLastElemAV(actorsRenderMidTop) }
ActorOrder.FRONT -> actorsRenderFront.add(actor) ActorOrder.FRONT -> { actorsRenderFront .add(actor); insertionSortLastElemAV(actorsRenderFront ) }
} }
} }
} }
@@ -681,15 +707,26 @@ constructor() : BasicGameState() {
} }
private fun insertionSortLastElem(arr: ArrayList<Actor>) { private fun insertionSortLastElem(arr: ArrayList<Actor>) {
var j: Int lock(ReentrantLock()) {
val index: Int = arr.size - 1 var j = arr.lastIndex - 1
val x = arr[index] val x = arr.last()
j = index - 1 while (j >= 0 && arr[j] > x) {
while (j > 0 && arr[j] > x) { arr[j + 1] = arr[j]
arr[j + 1] = arr[j] j -= 1
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) private fun ArrayList<out Actor>.binarySearch(actor: Actor) = this.binarySearch(actor.referenceID)
@@ -712,6 +749,16 @@ constructor() : BasicGameState() {
} }
return -(low + 1) // key not found 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 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) 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 { private fun noiseBillowFractal(): Joise {
val ridged = ModuleFractal() val ridged = ModuleFractal()
ridged.setType(ModuleFractal.FractalType.BILLOW) ridged.setType(ModuleFractal.FractalType.BILLOW)
@@ -70,19 +87,6 @@ class StateNoiseTexGen : BasicGameState() {
return Joise(ridged_autocorrect) 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 { private fun noiseSimplex(): Joise {
val simplex = ModuleFractal() val simplex = ModuleFractal()
simplex.seed = Random().nextLong() simplex.seed = Random().nextLong()
@@ -114,7 +118,7 @@ class StateNoiseTexGen : BasicGameState() {
} }
fun generateNoiseImage() { fun generateNoiseImage() {
val noiseModule = noiseBrownian() // change noise function here val noiseModule = noiseBrownianGranite() // change noise function here
for (y in 0..imagesize - 1) { for (y in 0..imagesize - 1) {
for (x 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 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 { init {
// just in case
println("[Terrarum] os.arch = $systemArch")
gameConfig = GameConfig() gameConfig = GameConfig()
joypadLabelStart = when (getConfigString("joypadlabelstyle")) { joypadLabelStart = when (getConfigString("joypadlabelstyle")) {
@@ -67,7 +75,7 @@ constructor(gamename: String) : StateBasedGame(gamename) {
else else
gameLocale = gameLocaleFromConfig gameLocale = gameLocaleFromConfig
println("[terrarum] Locale: " + gameLocale) println("[Terrarum] Locale: " + gameLocale)
try { try {
Controllers.getController(0) Controllers.getController(0)
@@ -127,6 +135,12 @@ constructor(gamename: String) : StateBasedGame(gamename) {
ingame = StateInGame() ingame = StateInGame()
addState(ingame) addState(ingame)
// foolproof
if (stateCount < 1) {
throw Error("Please add or un-comment addState statements")
}
} }
companion object { companion object {
@@ -158,16 +172,18 @@ constructor(gamename: String) : StateBasedGame(gamename) {
var HEIGHT = 742 // IMAX ratio var HEIGHT = 742 // IMAX ratio
var VSYNC = true var VSYNC = true
val VSYNC_TRIGGER_THRESHOLD = 56 val VSYNC_TRIGGER_THRESHOLD = 56
val HALFW: Int
get() = WIDTH.ushr(1)
val HALFH: Int
get() = HEIGHT.ushr(1)
var gameStarted = false var gameStarted = false
lateinit var ingame: StateInGame lateinit var ingame: StateInGame
lateinit var gameConfig: GameConfig lateinit var gameConfig: GameConfig
lateinit var OSName: String // System.getProperty("os.name") val OSName = System.getProperty("os.name")
private set val OSVersion = System.getProperty("os.version")
lateinit var OSVersion: String // System.getProperty("os.version")
private set
lateinit var OperationSystem: String // all caps "WINDOWS, "OSX", "LINUX", "SOLARIS", "UNKNOWN" lateinit var OperationSystem: String // all caps "WINDOWS, "OSX", "LINUX", "SOLARIS", "UNKNOWN"
private set private set
val isWin81: Boolean val isWin81: Boolean
@@ -268,7 +284,8 @@ constructor(gamename: String) : StateBasedGame(gamename) {
appgc.setVSync(VSYNC) appgc.setVSync(VSYNC)
appgc.setMaximumLogicUpdateInterval(1000 / TARGET_INTERNAL_FPS) // 10 ms appgc.setMaximumLogicUpdateInterval(1000 / TARGET_INTERNAL_FPS) // 10 ms
appgc.setMinimumLogicUpdateInterval(1000 / TARGET_INTERNAL_FPS - 1) // 9 ms appgc.setMinimumLogicUpdateInterval(1000 / TARGET_INTERNAL_FPS - 1) // 9 ms
appgc.setMultiSample(4)
appgc.setMultiSample(0)
appgc.setShowFPS(false) appgc.setShowFPS(false)
@@ -299,9 +316,6 @@ constructor(gamename: String) : StateBasedGame(gamename) {
} }
private fun getDefaultDirectory() { private fun getDefaultDirectory() {
OSName = System.getProperty("os.name")
OSVersion = System.getProperty("os.version")
val OS = System.getProperty("os.name").toUpperCase() val OS = System.getProperty("os.name").toUpperCase()
if (OS.contains("WIN")) { if (OS.contains("WIN")) {
OperationSystem = "WINDOWS" OperationSystem = "WINDOWS"
@@ -327,8 +341,8 @@ constructor(gamename: String) : StateBasedGame(gamename) {
defaultSaveDir = defaultDir + "/Saves" defaultSaveDir = defaultDir + "/Saves"
configDir = defaultDir + "/config.json" configDir = defaultDir + "/config.json"
println("os.name: '$OSName'") println("[Terrarum] os.name = $OSName")
println("os.version: '$OSVersion'") println("[Terrarum] os.version = $OSVersion")
} }
private fun createDirs() { private fun createDirs() {

View File

@@ -41,6 +41,7 @@ object CommandDict {
Pair("inventory", Inventory), Pair("inventory", Inventory),
Pair("avtracker", AVTracker), Pair("avtracker", AVTracker),
Pair("actorslist", ActorsList), Pair("actorslist", ActorsList),
Pair("setscale", SetScale),
// Test codes // Test codes
Pair("bulletintest", SetBulletin), 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 package net.torvald.terrarum.console
import net.torvald.terrarum.gameactors.Actor 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.gameactors.PhysTestBall
import net.torvald.terrarum.mapdrawer.TilesDrawer import net.torvald.terrarum.mapdrawer.TilesDrawer
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum

View File

@@ -20,6 +20,6 @@ object SpawnTapestry : ConsoleCommand {
} }
override fun printUsage() { 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.StateInGame
import net.torvald.terrarum.mapdrawer.FeaturesDrawer import net.torvald.terrarum.mapdrawer.FeaturesDrawer
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gameactors.ActorWithSprite
/** /**
* Created by minjaesong on 16-01-24. * Created by minjaesong on 16-01-24.
@@ -31,8 +31,8 @@ internal object Teleport : ConsoleCommand {
EchoError("missing 'to' on teleport command") EchoError("missing 'to' on teleport command")
return return
} }
val fromActor: ActorWithBody val fromActor: ActorWithSprite
val targetActor: ActorWithBody val targetActor: ActorWithSprite
try { try {
val fromActorID = args[1].toInt() val fromActorID = args[1].toInt()
val targetActorID = if (args[3].toLowerCase() == "player") val targetActorID = if (args[3].toLowerCase() == "player")
@@ -43,13 +43,13 @@ internal object Teleport : ConsoleCommand {
// if from == target, ignore the action // if from == target, ignore the action
if (fromActorID == targetActorID) return if (fromActorID == targetActorID) return
if (Terrarum.ingame.getActorByID(fromActorID) !is ActorWithBody || if (Terrarum.ingame.getActorByID(fromActorID) !is ActorWithSprite ||
Terrarum.ingame.getActorByID(targetActorID) !is ActorWithBody) { Terrarum.ingame.getActorByID(targetActorID) !is ActorWithSprite) {
throw IllegalArgumentException() throw IllegalArgumentException()
} }
else { else {
fromActor = Terrarum.ingame.getActorByID(fromActorID) as ActorWithBody fromActor = Terrarum.ingame.getActorByID(fromActorID) as ActorWithSprite
targetActor = Terrarum.ingame.getActorByID(targetActorID) as ActorWithBody targetActor = Terrarum.ingame.getActorByID(targetActorID) as ActorWithSprite
} }
} }
catch (e: NumberFormatException) { catch (e: NumberFormatException) {
@@ -72,7 +72,7 @@ internal object Teleport : ConsoleCommand {
return return
} }
val actor: ActorWithBody val actor: ActorWithSprite
val x: Int val x: Int
val y: Int val y: Int
try { try {
@@ -80,11 +80,11 @@ internal object Teleport : ConsoleCommand {
y = args[4].toInt() * FeaturesDrawer.TILE_SIZE + FeaturesDrawer.TILE_SIZE / 2 y = args[4].toInt() * FeaturesDrawer.TILE_SIZE + FeaturesDrawer.TILE_SIZE / 2
val actorID = args[1].toInt() val actorID = args[1].toInt()
if (Terrarum.ingame.getActorByID(actorID) !is ActorWithBody) { if (Terrarum.ingame.getActorByID(actorID) !is ActorWithSprite) {
throw IllegalArgumentException() throw IllegalArgumentException()
} }
else { else {
actor = Terrarum.ingame.getActorByID(actorID) as ActorWithBody actor = Terrarum.ingame.getActorByID(actorID) as ActorWithSprite
} }
} }
catch (e: NumberFormatException) { 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.AVKey
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorValue 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 net.torvald.terrarum.mapdrawer.FeaturesDrawer
import java.awt.BorderLayout import java.awt.BorderLayout
import java.awt.Color import java.awt.Color
@@ -30,7 +30,7 @@ class ActorValueTracker constructor() : JFrame() {
private val avPosArea = JTextArea() private val avPosArea = JTextArea()
private val avPosScroller = JScrollPane(avPosArea) private val avPosScroller = JScrollPane(avPosArea)
private var actor: ActorWithBody? = null private var actor: ActorWithSprite? = null
private var actorValue: ActorValue? = null private var actorValue: ActorValue? = null
private val modavInputKey = JTextField() private val modavInputKey = JTextField()
@@ -101,7 +101,7 @@ class ActorValueTracker constructor() : JFrame() {
actorValue = actor!!.actorValue actorValue = actor!!.actorValue
} }
else if (actorIDField.text.isNotBlank()) { 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 actorValue = actor!!.actorValue
} }
} }
@@ -165,7 +165,7 @@ class ActorValueTracker constructor() : JFrame() {
this.title = "AVTracker — $actor" this.title = "AVTracker — $actor"
if (actor is ActorWithBody) { if (actor is ActorWithSprite) {
this.actor = actor 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 * this code base, ACCELERATION must be changed (in other words, we must deal with JERK) accordingly
* to the FRICTION. * 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. * walkX/Y + velocity, which is stored in variable moveDelta.
* *
* Be warned. * 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.mapdrawer.FeaturesDrawer
import net.torvald.terrarum.tileproperties.TileCodex import net.torvald.terrarum.tileproperties.TileCodex
import net.torvald.spriteanimation.SpriteAnimation 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.mapdrawer.FeaturesDrawer.TILE_SIZE
import net.torvald.terrarum.tileproperties.Tile import net.torvald.terrarum.tileproperties.Tile
import net.torvald.terrarum.tileproperties.TileProp import net.torvald.terrarum.tileproperties.TileProp
import org.dyn4j.Epsilon import org.dyn4j.Epsilon
import org.dyn4j.geometry.Vector2 import org.dyn4j.geometry.Vector2
import org.newdawn.slick.Color
import org.newdawn.slick.GameContainer import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics import org.newdawn.slick.Graphics
import org.newdawn.slick.Image
import java.util.* 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. * 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 !! **/ /** !! 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 hitboxTranslateY: Double = 0.0// relative to spritePosY
protected var baseHitboxW: Int = 0 protected var baseHitboxW: Int = 0
protected var baseHitboxH: Int = 0 protected var baseHitboxH: Int = 0
protected var baseSpriteWidth: Int = 0
protected var baseSpriteHeight: Int = 0
/** /**
* * Position: top-left point * * Position: top-left point
* * Unit: pixel * * Unit: pixel
* !! external class should not hitbox.set(); use setHitboxDimension() and setPosition() * !! 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... @Transient val nextHitbox = Hitbox(0.0, 0.0, 0.0, 0.0) // 52 mantissas ought to be enough for anybody...
val tilewiseHitbox: Hitbox val tilewiseHitbox: Hitbox
@@ -100,7 +106,10 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
get() = (actorValue.getAsDouble(AVKey.SCALE) ?: 1.0) * get() = (actorValue.getAsDouble(AVKey.SCALE) ?: 1.0) *
(actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0) (actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0)
set(value) { set(value) {
val scaleDelta = value - scale
actorValue[AVKey.SCALE] = value / (actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0) actorValue[AVKey.SCALE] = value / (actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0)
// reposition
translatePosition(-baseHitboxW * scaleDelta / 2, -baseHitboxH * scaleDelta)
} }
@Transient val MASS_LOWEST = 0.1 // Kilograms @Transient val MASS_LOWEST = 0.1 // Kilograms
/** Apparent mass. Use "avBaseMass" for base mass */ /** Apparent mass. Use "avBaseMass" for base mass */
@@ -110,7 +119,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
if (value <= 0) if (value <= 0)
throw IllegalArgumentException("mass cannot be less than or equal to zero.") throw IllegalArgumentException("mass cannot be less than or equal to zero.")
else if (value < MASS_LOWEST) { 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 actorValue[AVKey.BASEMASS] = MASS_LOWEST
} }
@@ -123,7 +132,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
if (value < 0) if (value < 0)
throw IllegalArgumentException("invalid elasticity value $value; valid elasticity value is [0, 1].") throw IllegalArgumentException("invalid elasticity value $value; valid elasticity value is [0, 1].")
else if (value >= ELASTICITY_MAX) { else if (value >= ELASTICITY_MAX) {
println("[ActorWithBody] Elasticity were capped to $ELASTICITY_MAX.") println("[ActorWithSprite] Elasticity were capped to $ELASTICITY_MAX.")
field = ELASTICITY_MAX field = ELASTICITY_MAX
} }
else else
@@ -149,7 +158,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
var density = 1000.0 var density = 1000.0
set(value) { set(value) {
if (value < 0) if (value < 0)
throw IllegalArgumentException("[ActorWithBody] $value: density cannot be negative.") throw IllegalArgumentException("[ActorWithSprite] $value: density cannot be negative.")
field = value field = value
} }
@@ -164,7 +173,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
/** Default to 'true' */ /** Default to 'true' */
var isVisible = true var isVisible = true
/** Default to 'true' */ /** Default to 'true' */
var isUpdate = true var isUpdate = physics
var isNoSubjectToGrav = false var isNoSubjectToGrav = false
var isNoCollideWorld = false var isNoCollideWorld = false
var isNoSubjectToFluidResistance = false var isNoSubjectToFluidResistance = false
@@ -177,19 +186,6 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
*/ */
@Volatile var isChronostasis = false @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. * Gravitational Constant G. Load from gameworld.
* [m / s^2] * [m / s^2]
@@ -203,7 +199,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
get() = actorValue.getAsDouble(AVKey.DRAGCOEFF) ?: DRAG_COEFF_DEFAULT get() = actorValue.getAsDouble(AVKey.DRAGCOEFF) ?: DRAG_COEFF_DEFAULT
set(value) { set(value) {
if (value < 0) if (value < 0)
throw IllegalArgumentException("[ActorWithBody] drag coefficient cannot be negative.") throw IllegalArgumentException("[ActorWithSprite] drag coefficient cannot be negative.")
actorValue[AVKey.DRAGCOEFF] = value actorValue[AVKey.DRAGCOEFF] = value
} }
@@ -260,23 +256,33 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
// some initialiser goes here... // some initialiser goes here...
} }
fun makeNewSprite(w: Int, h: Int) { fun makeNewSprite(w: Int, h: Int, image: Image) {
sprite = SpriteAnimation(this) sprite = SpriteAnimation(this, w, h)
sprite!!.setDimension(w, h) sprite!!.setSpriteImage(image)
} }
fun makeNewSpriteGlow(w: Int, h: Int) { fun makeNewSprite(w: Int, h: Int, imageref: String) {
spriteGlow = SpriteAnimation(this) sprite = SpriteAnimation(this, w, h)
spriteGlow!!.setDimension(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 w
* @param h * @param h
* @param tx positive: translate drawn sprite to LEFT. * @param tx positive: translate sprite to LEFT.
* @param ty positive: translate drawn sprite to DOWN. * @param ty positive: translate sprite to DOWN.
* @see ActorWithBody.drawBody * @see ActorWithSprite.drawBody
* @see ActorWithBody.drawGlow * @see ActorWithSprite.drawGlow
*/ */
fun setHitboxDimension(w: Int, h: Int, tx: Int, ty: Int) { fun setHitboxDimension(w: Int, h: Int, tx: Int, ty: Int) {
baseHitboxH = h baseHitboxH = h
@@ -296,18 +302,23 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
*/ */
fun setPosition(x: Double, y: Double) { fun setPosition(x: Double, y: Double) {
hitbox.setFromWidthHeight( hitbox.setFromWidthHeight(
x - (baseHitboxW / 2 - hitboxTranslateX) * (1 - scale), x - (baseHitboxW / 2 - hitboxTranslateX) * scale,
y - (baseHitboxH - hitboxTranslateY) * (1 - scale), y - (baseHitboxH - hitboxTranslateY) * scale,
baseHitboxW * scale, baseHitboxW * scale,
baseHitboxH * scale) baseHitboxH * scale)
nextHitbox.setFromWidthHeight( nextHitbox.setFromWidthHeight(
x - (baseHitboxW / 2 - hitboxTranslateX) * (1 - scale), x - (baseHitboxW / 2 - hitboxTranslateX) * scale,
y - (baseHitboxH - hitboxTranslateY) * (1 - scale), y - (baseHitboxH - hitboxTranslateY) * scale,
baseHitboxW * scale, baseHitboxW * scale,
baseHitboxH * scale) baseHitboxH * scale)
} }
private fun translatePosition(dx: Double, dy: Double) {
hitbox.translate(dx, dy)
nextHitbox.translate(dx, dy)
}
val centrePosVector: Vector2 val centrePosVector: Vector2
get() = Vector2(hitbox.centeredX, hitbox.centeredY) get() = Vector2(hitbox.centeredX, hitbox.centeredY)
val centrePosPoint: Point2d val centrePosPoint: Point2d
@@ -344,12 +355,6 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
isNoSubjectToFluidResistance = isPlayerNoClip 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 * 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) private fun updateHitbox() = hitbox.reassign(nextHitbox)
open fun drawGlow(g: Graphics) { override open fun drawGlow(g: Graphics) {
if (isVisible && spriteGlow != null) { if (isVisible && spriteGlow != null) {
blendLightenOnly() blendLightenOnly()
if (!sprite!!.flippedHorizontal()) { if (!sprite!!.flippedHorizontal()) {
spriteGlow!!.render(g, spriteGlow!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat(), (hitbox.posX - hitboxTranslateX * scale).toFloat(),
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(), (hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat() (scale).toFloat()
) )
// Q&D fix for Roundworld anomaly // Q&D fix for Roundworld anomaly
spriteGlow!!.render(g, spriteGlow!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat() + world.width * TILE_SIZE, (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() (scale).toFloat()
) )
spriteGlow!!.render(g, spriteGlow!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat() - world.width * TILE_SIZE, (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() (scale).toFloat()
) )
} }
else { else {
spriteGlow!!.render(g, spriteGlow!!.render(g,
(hitbox.posX - scale).toFloat(), (hitbox.posX - scale).toFloat(),
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(), (hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat() (scale).toFloat()
) )
// Q&D fix for Roundworld anomaly // Q&D fix for Roundworld anomaly
spriteGlow!!.render(g, spriteGlow!!.render(g,
(hitbox.posX - scale).toFloat() + world.width * TILE_SIZE, (hitbox.posX - scale).toFloat() + world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(), (hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat() (scale).toFloat()
) )
spriteGlow!!.render(g, spriteGlow!!.render(g,
(hitbox.posX - scale).toFloat() - world.width * TILE_SIZE, (hitbox.posX - scale).toFloat() - world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(), (hitbox.posY + hitboxTranslateY * scale).toFloat(),
(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) { if (isVisible && sprite != null) {
@@ -1043,36 +1062,36 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
if (!sprite!!.flippedHorizontal()) { if (!sprite!!.flippedHorizontal()) {
sprite!!.render(g, sprite!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat(), (hitbox.posX - hitboxTranslateX * scale).toFloat(),
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(), (hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat() (scale).toFloat()
) )
// Q&D fix for Roundworld anomaly // Q&D fix for Roundworld anomaly
sprite!!.render(g, sprite!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat() + world.width * TILE_SIZE, (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() (scale).toFloat()
) )
sprite!!.render(g, sprite!!.render(g,
(hitbox.posX - hitboxTranslateX * scale).toFloat() - world.width * TILE_SIZE, (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() (scale).toFloat()
) )
} }
else { else {
sprite!!.render(g, sprite!!.render(g,
(hitbox.posX - scale).toFloat(), (hitbox.posX - scale).toFloat(),
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(), (hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat() (scale).toFloat()
) )
// Q&D fix for Roundworld anomaly // Q&D fix for Roundworld anomaly
sprite!!.render(g, sprite!!.render(g,
(hitbox.posX - scale).toFloat() + world.width * TILE_SIZE, (hitbox.posX - scale).toFloat() + world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(), (hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat() (scale).toFloat()
) )
sprite!!.render(g, sprite!!.render(g,
(hitbox.posX - scale).toFloat() - world.width * TILE_SIZE, (hitbox.posX - scale).toFloat() - world.width * TILE_SIZE,
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(), (hitbox.posY + hitboxTranslateY * scale).toFloat(),
(scale).toFloat() (scale).toFloat()
) )
} }
@@ -1129,9 +1148,9 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
// warnings // warnings
if (sprite == null && isVisible) 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) 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 assertPrinted = true
} }
@@ -1190,13 +1209,30 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
companion object { 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 * Enumerations that exported to JSON
*/ */
@Transient const val COLLISION_NOCOLLIDE = 0 @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) /** 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_KINEMATIC = 1
@Transient const val COLLISION_STATIC = 3 // does not displaced by external forces, target of collision (e.g. nonmoving static obj) /** 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_GIVER = 4 // mobs
@Transient const val COLLISION_KNOCKBACK_TAKER = 5 // benevolent NPCs @Transient const val COLLISION_KNOCKBACK_TAKER = 5 // benevolent NPCs
@Transient const val BLEND_NORMAL = 4 @Transient const val BLEND_NORMAL = 4

View File

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

View File

@@ -9,7 +9,7 @@ import org.newdawn.slick.Graphics
/** /**
* Created by minjaesong on 16-03-15. * 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 { init {
if (item.id >= ItemCodex.ITEM_COUNT_MAX) 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. * 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 * 0: Open
* 1: Blocked * 1: Blocked

View File

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

View File

@@ -11,7 +11,7 @@ import org.newdawn.slick.Input
* *
* Created by minjaesong on 16-10-10. * 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 { init {
this.actorValue["_bornyear"] = born.year 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 private val aiLuaAPI: AILuaAPI
companion object { companion object {
val DEFAULT_COLLISION_TYPE = ActorWithBody.COLLISION_DYNAMIC val DEFAULT_COLLISION_TYPE = ActorWithSprite.COLLISION_DYNAMIC
} }
init { 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. * Created by minjaesong on 16-03-05.
*/ */
class PhysTestBall : ActorWithBody(ActorOrder.MIDDLE) { class PhysTestBall : ActorWithSprite(ActorOrder.MIDDLE) {
private var color = Color.orange private var color = Color.orange

View File

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

View File

@@ -26,13 +26,11 @@ object PlayerBuilderSigrid {
p.referenceID = 0x51621D // the only constant of this procedural universe p.referenceID = 0x51621D // the only constant of this procedural universe
p.makeNewSprite(28, 51) p.makeNewSprite(28, 51, "assets/graphics/sprites/test_player.tga")
p.sprite!!.setSpriteImage("assets/graphics/sprites/test_player.tga")
p.sprite!!.setDelay(200) p.sprite!!.setDelay(200)
p.sprite!!.setRowsAndFrames(1, 1) p.sprite!!.setRowsAndFrames(1, 1)
p.makeNewSpriteGlow(28, 51) p.makeNewSpriteGlow(28, 51, "assets/graphics/sprites/test_player_glow.tga")
p.spriteGlow!!.setSpriteImage("assets/graphics/sprites/test_player_glow.tga")
p.spriteGlow!!.setDelay(200) p.spriteGlow!!.setDelay(200)
p.spriteGlow!!.setRowsAndFrames(1, 1) 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["__selectedtile"] = 147 // test code; replace with <tile_item>.primaryUse(gc, delta)
p.actorValue["__aimhelper"] = true // TODO when you'll gonna implement it? 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) 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.point.Point2d
import net.torvald.spriteanimation.SpriteAnimation import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.tileproperties.Tile
import net.torvald.terrarum.tileproperties.TileCodex
import org.dyn4j.geometry.Vector2 import org.dyn4j.geometry.Vector2
import org.newdawn.slick.Color import org.newdawn.slick.Color
import org.newdawn.slick.GameContainer import org.newdawn.slick.GameContainer
@@ -15,11 +17,13 @@ import java.util.*
* *
* Created by minjaesong on 16-08-29. * Created by minjaesong on 16-08-29.
*/ */
// TODO simplified, lightweight physics (does not call PhysicsSolver)
open class ProjectileSimple( open class ProjectileSimple(
private val type: Int, private val type: Int,
fromPoint: Vector2, // projected coord fromPoint: Vector2, // projected coord
toPoint: Vector2 // arriving coord toPoint: Vector2 // arriving coord
) : ActorWithBody(ActorOrder.MIDTOP), Luminous, Projectile { ) : ActorWithSprite(ActorOrder.MIDTOP), Luminous, Projectile {
val damage: Int val damage: Int
val displayColour: Color val displayColour: Color
@@ -69,7 +73,12 @@ open class ProjectileSimple(
override fun update(gc: GameContainer, delta: Int) { override fun update(gc: GameContainer, delta: Int) {
// hit something and despawn // hit something and despawn
lifetimeCounter += delta 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) posPre.set(centrePosPoint)

View File

@@ -10,13 +10,14 @@ import org.newdawn.slick.Image
/** /**
* Created by SKYHi14 on 2017-01-07. * 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 { init {
makeNewSprite(image.width, image.height) image.filter = Image.FILTER_NEAREST
makeNewSprite(image.width, image.height, image)
setHitboxDimension(image.width, image.height, 0, 0) setHitboxDimension(image.width, image.height, 0, 0)
sprite!!.setSpriteImage(image)
isNoSubjectToGrav = true
setPosition(Terrarum.appgc.mouseX, Terrarum.appgc.mouseY) 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. * 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 // 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.Terrarum
import net.torvald.terrarum.gameactors.AIControlled import net.torvald.terrarum.gameactors.AIControlled
import net.torvald.terrarum.gameactors.AVKey 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.mapdrawer.LightmapRenderer
import net.torvald.terrarum.tileproperties.Tile import net.torvald.terrarum.tileproperties.Tile
import net.torvald.terrarum.tileproperties.TileCodex import net.torvald.terrarum.tileproperties.TileCodex
@@ -14,7 +14,7 @@ import org.luaj.vm2.lib.ZeroArgFunction
/** /**
* Created by minjaesong on 16-10-24. * 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 // 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"]["getNearbyTiles"] = GetNearbyTiles(actor)
g["ai"]["getFloorsHeight"] = GetFloorsHeight(actor) g["ai"]["getFloorsHeight"] = GetFloorsHeight(actor)
g["ai"]["getCeilingsHeight"] = GetCeilingsHeight(actor) g["ai"]["getCeilingsHeight"] = GetCeilingsHeight(actor)
g["ai"]["getLedgesHeight"] = GetLedgesHeight(actor)
g["game"] = LuaValue.tableOf() g["game"] = LuaValue.tableOf()
g["game"]["version"] = GameVersion() g["game"]["version"] = GameVersion()
@@ -50,9 +51,9 @@ internal class AILuaAPI(g: Globals, actor: ActorWithBody) {
companion object { 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() val t: LuaTable = LuaTable()
t["name"] = actor.actorValue.getAsString(AVKey.NAME).toLua() 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() } 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 { override fun call(): LuaValue {
return composeActorObject(actor) 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 { override fun call(): LuaValue {
return LuaValue.valueOf(actor.hitbox.centeredX) return LuaValue.valueOf(actor.hitbox.centeredX)
} }
} }
class GetY(val actor: ActorWithBody) : ZeroArgFunction() { class GetY(val actor: ActorWithSprite) : ZeroArgFunction() {
override fun call(): LuaValue { override fun call(): LuaValue {
return LuaValue.valueOf(actor.hitbox.centeredY) 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 /** @param radius
* *
* 3 will return 7x7 array, 0 will return 1x1, 1 will return 3x3 * 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 /** @param radius
* *
* 3 will return len:7 array, 0 will return len:1, 1 will return len:3 * 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() { class GetCeilingsHeight(val actor: ActorWithSprite) : OneArgFunction() {
/** @param radius /** @param arg radius
* *
* 3 will return 7x7 array, 0 will return 1x1, 1 will return 3x3 * 3 will return 7x7 array, 0 will return 1x1, 1 will return 3x3
* *
* Index: [-3] .. [0] .. [3] for radius * Index: [-3] .. [0] .. [3] for radius
* Return value: floor height * Return value: floor height
* (-1): tile you can stand on
* 0: body tile (legs area) * 0: body tile (legs area)
* 1: body tile (may be vary depend on the size of the actor) * 1: body tile (may be vary depend on the size of the actor)
* 2+: tiles up there * 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 end
function moveToDirection(delta) function moveToDirection(delta)
local tiles = ai.getNearbyTiles(1) local pits = ai.getFloorsHeight(2)
local ledges = ai.getLedgesHeight(1) local ledges = ai.getLedgesHeight(1)
if moveMode == "left" then 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) ai.moveLeft(0.8)
if ledges[-1] <= jumpheight then -- no futile jumps if ledges[-1] <= jumpheight then -- no futile jumps
ai.jump() ai.jump()
@@ -33,7 +33,7 @@ function moveToDirection(delta)
ai.moveLeft(0.5) ai.moveLeft(0.5)
end end
elseif moveMode == "right" then 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) ai.moveRight(0.8)
if ledges[1] <= jumpheight then -- no futile jumps if ledges[1] <= jumpheight then -- no futile jumps
ai.jump() ai.jump()

View File

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

View File

@@ -1,6 +1,6 @@
package net.torvald.terrarum.gameactors.physicssolver 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. * 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 val FLUID_UPDATING_SQUARE_RADIUS = 64 // larger value will have dramatic impact on performance
const private val DOUBLE_RADIUS = FLUID_UPDATING_SQUARE_RADIUS * 2 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) }) private val fluidTypeMap = Array<ByteArray>(DOUBLE_RADIUS, { ByteArray(DOUBLE_RADIUS) })
const val DISPLACE_CAP = 4 const val DISPLACE_CAP = 4
@@ -38,23 +38,28 @@ object WorldSimulator {
val colourNone = Color(0x808080) val colourNone = Color(0x808080)
val colourWater = Color(0x66BBFF) val colourWater = Color(0x66BBFF)
private val world = Terrarum.ingame.world
// TODO future Kotlin feature -- typealias AnyPlayer: HistoricalFigure // 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() 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() updateYFrom = p.hitbox.centeredY.div(FeaturesDrawer.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt()
updateXTo = updateXFrom + DOUBLE_RADIUS updateXTo = updateXFrom + DOUBLE_RADIUS
updateYTo = updateYFrom + DOUBLE_RADIUS updateYTo = updateYFrom + DOUBLE_RADIUS
moveFluids(world, delta) moveFluids(delta)
displaceFallables(world, delta) displaceFallables(delta)
} }
/** /**
* displace fluids. Note that the code assumes the gravity pulls things downward ONLY, * 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 * which means you'll need to modify the code A LOT if you're going to implement zero- or
* reverse-gravity. * 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 // // build fluidmap //
//////////////////// ////////////////////
@@ -74,7 +79,7 @@ object WorldSimulator {
if (tile.isFluid()) { if (tile.isFluid()) {
// move down if not obstructed // move down if not obstructed
if (!tileBottom.isSolid()) { /*if (!tileBottom.isSolid()) {
val drainage = drain(world, x, y, DISPLACE_CAP) val drainage = drain(world, x, y, DISPLACE_CAP)
pour(world, x, y + 1, drainage) pour(world, x, y + 1, drainage)
} }
@@ -106,7 +111,11 @@ object WorldSimulator {
// nowhere open; do default (fill top) // nowhere open; do default (fill top)
else { else {
pour(world, x, y - 1, DISPLACE_CAP) 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 * displace fallable tiles. It is scanned bottom-left first. To achieve the sens ofreal
* falling, each tiles are displaced by ONLY ONE TILE below. * 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 (y in updateYFrom..updateYTo) {
for (x in updateXFrom..updateXTo) { for (x in updateXFrom..updateXTo) {
val tile = world.getTileFromTerrain(x, y) ?: Tile.STONE val tile = world.getTileFromTerrain(x, y) ?: Tile.STONE
@@ -135,7 +144,7 @@ object WorldSimulator {
// remove tileThis to create air pocket // remove tileThis to create air pocket
world.setTileTerrain(x, y, Tile.AIR) 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 // place our tile
world.setTileTerrain(x, y + 1, tile) world.setTileTerrain(x, y + 1, tile)
} }
@@ -156,7 +165,7 @@ object WorldSimulator {
for (x in 0..fluidMap[0].size - 1) { for (x in 0..fluidMap[0].size - 1) {
val data = fluidMap[y][x] val data = fluidMap[y][x]
if (TilesDrawer.tileInCamera(x + updateXFrom, y + updateYFrom)) { if (TilesDrawer.tileInCamera(x + updateXFrom, y + updateYFrom)) {
if (data == 0) if (data == 0.toByte())
g.color = colourNone g.color = colourNone
else else
g.color = colourWater g.color = colourWater
@@ -188,7 +197,7 @@ object WorldSimulator {
for (x in updateXFrom..updateXTo) { for (x in updateXFrom..updateXTo) {
val tile = world.getTileFromTerrain(x, y) ?: Tile.STONE val tile = world.getTileFromTerrain(x, y) ?: Tile.STONE
if (tile.isFluid()) { 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() fluidTypeMap[y - updateYFrom][x - updateXFrom] = tile.fluidType().toByte()
} }
} }
@@ -209,8 +218,8 @@ object WorldSimulator {
fun Int.isFluid() = TileCodex[this].isFluid fun Int.isFluid() = TileCodex[this].isFluid
fun Int.isSolid() = this.fluidLevel() == FLUID_MAX || TileCodex[this].isSolid fun Int.isSolid() = this.fluidLevel() == FLUID_MAX || TileCodex[this].isSolid
//fun Int.viscosity() = TileCodex[this]. //fun Int.viscosity() = TileCodex[this].
fun Int.fluidLevel() = if (!this.isFluid()) 0 else (this % FLUID_MAX) + 1 fun Int.fluidLevel() = if (!this.isFluid()) 0 else (this % FLUID_MAX).plus(1)
fun Int.fluidType() = this / FLUID_MAX fun Int.fluidType() = (this / 16) // 0 - 255, 255 being water, 254 being lava
fun Int.isEven() = (this and 0x01) == 0 fun Int.isEven() = (this and 0x01) == 0
fun Int.isFallable() = TileCodex[this].isFallable 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. * (intended drainage - this) will give you how much fluid is not yet drained.
* TODO add fluidType support * TODO add fluidType support
*/ */
private fun drain(world: GameWorld, x: Int, y: Int, amount: Int): Int { private fun drain(x: Int, y: Int, amount: Int): Int {
val displacement = Math.min(fluidMap[y - updateYFrom][x - updateXFrom], amount) 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 return displacement
} }
@@ -243,7 +253,7 @@ object WorldSimulator {
* @param x and y: world tile coord * @param x and y: world tile coord
* TODO add fluidType support * 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 * @param x and y: world tile coord
* @return spillage * @return spillage
@@ -256,10 +266,10 @@ object WorldSimulator {
val addrY = worldYPos - updateYFrom val addrY = worldYPos - updateYFrom
if (addrX >= 0 && addrY >= 0 && addrX < DOUBLE_RADIUS && addrY < DOUBLE_RADIUS) { 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) { if (fluidMap[addrY][addrX] > FLUID_MAX) {
spil = 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.gameactors.CanBeAnItem
import net.torvald.terrarum.gameitem.InventoryItem import net.torvald.terrarum.gameitem.InventoryItem
import net.torvald.terrarum.Terrarum 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.mouseTileX
import net.torvald.terrarum.gamecontroller.mouseTileY import net.torvald.terrarum.gamecontroller.mouseTileY
import net.torvald.terrarum.gameitem.EquipPosition import net.torvald.terrarum.gameitem.EquipPosition
@@ -50,7 +50,7 @@ object ItemCodex {
val mousePoint = Point2d(gc.mouseTileX.toDouble(), gc.mouseTileY.toDouble()) val mousePoint = Point2d(gc.mouseTileX.toDouble(), gc.mouseTileY.toDouble())
// linear search filter (check for intersection with tilewise mouse point and tilewise hitbox) // linear search filter (check for intersection with tilewise mouse point and tilewise hitbox)
Terrarum.ingame.actorContainer.forEach { Terrarum.ingame.actorContainer.forEach {
if (it is ActorWithBody && it.tilewiseHitbox.intersects(mousePoint)) if (it is ActorWithSprite && it.tilewiseHitbox.intersects(mousePoint))
return return
} }
// filter passed, do the job // 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.RGB
import net.torvald.colourutil.CIELuvUtil.additiveLuv import net.torvald.colourutil.CIELuvUtil.additiveLuv
import net.torvald.terrarum.concurrent.ThreadParallel 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.abs
import net.torvald.terrarum.gameactors.roundInt import net.torvald.terrarum.gameactors.roundInt
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
@@ -217,7 +217,7 @@ object LightmapRenderer {
private fun buildLanternmap() { private fun buildLanternmap() {
lanternMap.clear() lanternMap.clear()
Terrarum.ingame.actorContainer.forEach { it -> 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 // put lanterns to the area the luminantBox is occupying
for (lightBox in it.lightBoxList) { for (lightBox in it.lightBoxList) {
val lightBoxX = it.hitbox.posX + lightBox.posX val lightBoxX = it.hitbox.posX + lightBox.posX
@@ -267,11 +267,6 @@ object LightmapRenderer {
} }
// END MIX TILE // 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) { for (i in 0..lanternMap.size - 1) {
val lmap = lanternMap[i] val lmap = lanternMap[i]
if (lmap.posX == x && lmap.posY == y) 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. * Created by minjaesong on 16-03-31.
*/ */
interface NoiseFilter { 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. * Created by minjaesong on 16-03-31.
*/ */
object NoiseFilterCubic : NoiseFilter { 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 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) * (start - end) / FastMath.pow(WorldGenerator.HEIGHT.toFloat(), 3f) *
FastMath.pow((func_argX - WorldGenerator.HEIGHT).toFloat(), 3f) + end 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. * Created by minjaesong on 16-03-31.
*/ */
object NoiseFilterMinusQuadratic : NoiseFilter { 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 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()) * (start - end) / FastMath.sqr(WorldGenerator.HEIGHT.toFloat()) *
FastMath.sqr((func_argX - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat()) + start 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. * Created by minjaesong on 16-03-31.
*/ */
object NoiseFilterQuadratic : NoiseFilter { 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 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()) * (start - end) / FastMath.sqr(WorldGenerator.HEIGHT.toFloat()) *
FastMath.sqr((func_argX - WorldGenerator.HEIGHT).toFloat()) + end 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. * Created by minjaesong on 16-03-31.
*/ */
object NoiseFilterSqrt : NoiseFilter { 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 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) { 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. * Created by minjaesong on 16-03-31.
*/ */
object NoiseFilterUniform : NoiseFilter { object NoiseFilterUniform : NoiseFilter {
override fun getGrad(func_argX: Int, start: Float, end: Float): Float { override fun getGrad(func_argX: Int, start: Double, end: Double): Double {
return 1f return 1.0
} }
} }

View File

@@ -32,11 +32,11 @@ object WorldGenerator {
var TERRAIN_AVERAGE_HEIGHT: Int = 0 var TERRAIN_AVERAGE_HEIGHT: Int = 0
private var minimumFloatingIsleHeight: Int = 0 private var minimumFloatingIsleHeight: Int = 0
private val NOISE_GRAD_START = 0.67f private val NOISE_GRAD_START = 0.67
private val NOISE_GRAD_END = 0.56f private val NOISE_GRAD_END = 0.56
private val NOISE_SIMPLEX_ORE_START = 1.42f private val NOISE_SIMPLEX_ORE_START = 1.42
private val NOISE_SIMPLEX_ORE_END = 1.28f private val NOISE_SIMPLEX_ORE_END = 1.28
private val HILL_WIDTH = 256 // power of two! private val HILL_WIDTH = 256 // power of two!
//private val MAX_HILL_HEIGHT = 100 //private val MAX_HILL_HEIGHT = 100
@@ -51,8 +51,8 @@ object WorldGenerator {
private var GLACIER_MOUNTAIN_WIDTH = 900 private var GLACIER_MOUNTAIN_WIDTH = 900
private val GLACIER_MOUNTAIN_HEIGHT = 300 private val GLACIER_MOUNTAIN_HEIGHT = 300
private val CAVEGEN_THRE_START = 0.95f private val CAVEGEN_THRE_START = 0.95
private val CAVEGEN_THRE_END = 0.67f private val CAVEGEN_THRE_END = 0.67
private var worldOceanPosition: Int = -1 private var worldOceanPosition: Int = -1
@@ -113,12 +113,12 @@ object WorldGenerator {
*/ */
val noiseArray = arrayOf( 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("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.5f, 0.5f), 0.3f, Tile.AIR, Tile.STONE, Tile.STONE, NoiseFilterUniform) , 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("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.5f, 0.5f), 0.98f, Tile.STONE, Tile.STONE, Tile.DIRT, 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.5f, 0.5f), 0.98f, Tile.STONE, Tile.STONE, Tile.GRAVEL, 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("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) //, 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 */ /* 1. Raise */
private fun noiseRidged(xStretch: Float, yStretch: Float): Joise { private fun noiseRidged(xStretch: Double, yStretch: Double): Joise {
val ridged = ModuleFractal() val ridged = ModuleFractal()
ridged.setType(ModuleFractal.FractalType.RIDGEMULTI) ridged.setType(ModuleFractal.FractalType.RIDGEMULTI)
ridged.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC) ridged.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
@@ -185,18 +185,21 @@ object WorldGenerator {
return Joise(ridged_scale) return Joise(ridged_scale)
} }
private fun noiseBlobs(xStretch: Float, yStretch: Float): Joise { private fun noiseBlobs(frequency: Double): Joise {
val gradval = ModuleBasisFunction() val ridged = ModuleFractal()
gradval.seed = SEED xor random.nextLong() ridged.setType(ModuleFractal.FractalType.FBM)
gradval.setType(ModuleBasisFunction.BasisType.GRADVAL) ridged.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
gradval.setInterpolation(ModuleBasisFunction.InterpolationType.QUINTIC) ridged.setNumOctaves(2)
ridged.setFrequency(frequency)
ridged.seed = Random().nextLong()
val gradval_scale = ModuleScaleDomain() val brownian_select = ModuleSelect()
gradval_scale.setScaleX(1.0 / xStretch) brownian_select.setControlSource(ridged)
gradval_scale.setScaleY(1.0 / yStretch) brownian_select.setThreshold(0.8)
gradval_scale.setSource(gradval) 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, private fun carveByMap(noisemap: Any, scarcity: Float, tile: Int, message: String,
filter: NoiseFilter = NoiseFilterQuadratic, filter: NoiseFilter = NoiseFilterQuadratic,
filterStart: Float = NOISE_GRAD_START, filterStart: Double = NOISE_GRAD_START,
filterEnd: Float = NOISE_GRAD_END) { filterEnd: Double = NOISE_GRAD_END) {
println("[mapgenerator] " + message) println("[mapgenerator] " + message)
for (y in 0..HEIGHT - 1) { 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, private fun fillByMap(noisemap: Any, scarcity: Float, replaceFrom: Int, replaceTo: Int, message: String,
filter: NoiseFilter = NoiseFilterQuadratic, filter: NoiseFilter = NoiseFilterQuadratic,
filterStart: Float = NOISE_GRAD_START, filterStart: Double = NOISE_GRAD_START,
filterEnd: Float = NOISE_GRAD_END) { filterEnd: Double = NOISE_GRAD_END) {
println("[mapgenerator] " + message) println("[mapgenerator] " + message)
for (y in 0..HEIGHT - 1) { 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, private fun fillByMap(noisemap: Any, scarcity: Float, replaceFrom: Int, tile: IntArray, message: String,
filter: NoiseFilter = NoiseFilterQuadratic, filter: NoiseFilter = NoiseFilterQuadratic,
filterStart: Float = NOISE_GRAD_START, filterStart: Double = NOISE_GRAD_START,
filterEnd: Float = NOISE_GRAD_END) { filterEnd: Double = NOISE_GRAD_END) {
println("[mapgenerator] " + message) println("[mapgenerator] " + message)
for (y in 0..HEIGHT - 1) { 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 TaggedSimplexNoise(var noiseModule: SimplexNoise, var xStretch: Float, var yStretch: Float)
data class TaggedJoise(var message: String, 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 replaceFromTerrain: Any, var replaceFromWall: Int,
var replaceTo: Any, var replaceTo: Any,
var filter: NoiseFilter = NoiseFilterQuadratic, var filter: NoiseFilter = NoiseFilterQuadratic,
var filterArg1: Float = NOISE_GRAD_START, var filterArg1: Double = NOISE_GRAD_START,
var filterArg2: Float = NOISE_GRAD_END) var filterArg2: Double = NOISE_GRAD_END)
} }

View File

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

View File

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

View File

@@ -5,137 +5,137 @@ package net.torvald.terrarum.tileproperties
*/ */
object TilePropCSV { object TilePropCSV {
operator fun invoke() = """ operator fun invoke() = """
"id";"dmg";"name" ; "opacity";"strength";"dsty";"mate";"fluid";"solid";"wall"; "lumcolor";"drop";"ddmg";"fall";"dlfn";"vscs";"friction" "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";"4" "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";"16" "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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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"; "4" "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"; "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";"16" "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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"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";"16" "256"; "0";"TILE_NULL" ; "0"; "-1";"2600";"null"; "0"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "N/A"; "0";"16"
## Notes ## ## Notes ##
@@ -155,6 +155,8 @@ object TilePropCSV {
# mate: material, four-letter code # mate: material, four-letter code
# fv: vertical friction (boolean)
## Illuminators ## ## Illuminators ##

View File

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

View File

@@ -7,6 +7,9 @@ import net.torvald.random.HQRNG
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blendMul import net.torvald.terrarum.blendMul
import net.torvald.terrarum.blendNormal 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.gameworld.WorldTime
import net.torvald.terrarum.getPixel import net.torvald.terrarum.getPixel
import org.newdawn.slick.Color import org.newdawn.slick.Color
@@ -76,6 +79,16 @@ object WeatherMixer {
fun update(gc: GameContainer, delta: Int) { fun update(gc: GameContainer, delta: Int) {
currentWeather = weatherList[WEATHER_GENERIC]!![0] 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) { fun render(g: Graphics) {