mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
saplings
This commit is contained in:
@@ -11,8 +11,8 @@
|
||||
"21";"21";"21";"BLOCK_STONE_MARBLE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.1";"ROCK,NATURAL"
|
||||
|
||||
# dirts
|
||||
"32";"32";"32";"BLOCK_DIRT";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"DIRT";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"DIRT,NATURAL"
|
||||
"33";"32";"32";"BLOCK_GRASS";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
||||
"32";"32";"32";"BLOCK_DIRT";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"DIRT";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"DIRT,NATURAL,CULTIVABLE"
|
||||
"33";"32";"32";"BLOCK_GRASS";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL,CULTIVABLE"
|
||||
"34";"34";"34";"BLOCK_GRASSWALL";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
||||
"35";"item@basegame:25";"item@basegame:25";"BLOCK_CLAY";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1700";"DIRT";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"DIRT,NATURAL"
|
||||
#"35";"35";"35";"BLOCK_FOLIAGE_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 18 and column 2.
|
BIN
assets/mods/basegame/sprites/saplings.tga
LFS
Normal file
BIN
assets/mods/basegame/sprites/saplings.tga
LFS
Normal file
Binary file not shown.
135
src/net/torvald/terrarum/modulebasegame/gameactors/Cultivable.kt
Normal file
135
src/net/torvald/terrarum/modulebasegame/gameactors/Cultivable.kt
Normal file
@@ -0,0 +1,135 @@
|
||||
package net.torvald.terrarum.modulebasegame.gameactors
|
||||
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.spriteanimation.SheetSpriteAnimation
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.modulebasegame.worldgenerator.Treegen
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2024-02-03.
|
||||
*/
|
||||
open class Cultivable: FixtureBase {
|
||||
|
||||
open var currentGrowth = 0f
|
||||
@Transient var maxGrowth: Int = 0; private set
|
||||
@Transient open val growthPerTick = 1f
|
||||
@Transient open val growthRandomness = 0.33333334f
|
||||
open var growthBonusMult = 1f
|
||||
|
||||
override fun canSpawnOnThisFloor(itemID: ItemID) = BlockCodex[itemID].hasTag("CULTIVABLE")
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 1, 2),
|
||||
nameFun = { " " }
|
||||
)
|
||||
|
||||
constructor(maxGrowth: Int) : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 1, 2),
|
||||
nameFun = { " " }
|
||||
) {
|
||||
this.maxGrowth = maxGrowth
|
||||
}
|
||||
|
||||
fun tickGrowthCounter() {
|
||||
val worldTimeDelta = INGAME.world.worldTime.timeDelta
|
||||
val rnd = 1f + (((Math.random() * 2.0) - 1.0) * growthRandomness)
|
||||
currentGrowth += growthPerTick * worldTimeDelta * growthBonusMult * rnd.toFloat()
|
||||
}
|
||||
|
||||
open fun tryToSpawnMaturePlant() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2024-02-03.
|
||||
*/
|
||||
open class SaplingBase(val species: Int) : Cultivable(72000) {
|
||||
private val variant = (0..3).random()
|
||||
init {
|
||||
CommonResourcePool.addToLoadingList("basegame/sprites/saplings.tga") {
|
||||
TextureRegionPack(ModMgr.getGdxFile("basegame", "sprites/saplings.tga"), 16, 32)
|
||||
}
|
||||
CommonResourcePool.loadAll()
|
||||
|
||||
makeNewSprite(CommonResourcePool.getAsTextureRegionPack("basegame/sprites/saplings.tga")).let {
|
||||
it.setRowsAndFrames(4,4)
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(delta: Float) {
|
||||
super.update(delta)
|
||||
|
||||
// these have to run every frame to make the sprite static
|
||||
(sprite as SheetSpriteAnimation).currentRow = species
|
||||
(sprite as SheetSpriteAnimation).currentFrame = variant
|
||||
|
||||
if (!flagDespawn) {
|
||||
tickGrowthCounter()
|
||||
|
||||
// printdbg(this, "growth=$currentGrowth/$maxGrowth")
|
||||
|
||||
if (currentGrowth >= maxGrowth) {
|
||||
tryToSpawnMaturePlant()
|
||||
}
|
||||
}
|
||||
}
|
||||
private var treeHasBeenGrown = false
|
||||
override fun tryToSpawnMaturePlant() {
|
||||
if (INGAME.WORLD_UPDATE_TIMER % 3 == 2) {
|
||||
val size = if (Math.random() < 0.1) 2 else 1
|
||||
val result = Treegen.plantTree(INGAME.world, intTilewiseHitbox.startX.toInt(), intTilewiseHitbox.endY.toInt() + 1, species, size)
|
||||
|
||||
if (result) {
|
||||
treeHasBeenGrown = true
|
||||
flagDespawn()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this function will be called when:
|
||||
* 1. player removes a sapling that has not yet matured
|
||||
* 2. the sapling is matured and the tree is about to be spawned
|
||||
*/
|
||||
|
||||
override fun despawn() {
|
||||
|
||||
if (canBeDespawned) {
|
||||
printdbg(this, "despawn at T${INGAME.WORLD_UPDATE_TIMER}: ${nameFun()}")
|
||||
// printStackTrace(this)
|
||||
|
||||
// remove filler block
|
||||
if (!treeHasBeenGrown) {
|
||||
forEachBlockbox { x, y, _, _ ->
|
||||
world!!.setTileTerrain(x, y, Block.AIR, true)
|
||||
}
|
||||
}
|
||||
|
||||
worldBlockPos = null
|
||||
mainUI?.dispose()
|
||||
|
||||
this.isVisible = false
|
||||
|
||||
despawnHook(this)
|
||||
}
|
||||
else {
|
||||
printdbg(this, "failed to despawn at T${INGAME.WORLD_UPDATE_TIMER}: ${nameFun()}")
|
||||
printdbg(this, "cannot despawn a fixture with non-empty inventory")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SaplingOak : SaplingBase(0)
|
||||
class SaplingEbony : SaplingBase(1)
|
||||
class SaplingBirch : SaplingBase(2)
|
||||
class SaplingRosewood : SaplingBase(3)
|
||||
@@ -245,6 +245,13 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Condition for (if the tile is solid) is always implied regardless of this function. See [canSpawnHere0]
|
||||
*/
|
||||
open fun canSpawnOnThisFloor(itemID: ItemID): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
fun canSpawnHere(posX0: Int, posY0: Int): Boolean {
|
||||
val posX = (posX0 - blockBox.width.minus(1).div(2)) fmod world!!.width // width.minus(1) so that spawning position would be same as the ghost's position
|
||||
val posY = posY0 - blockBox.height + 1
|
||||
@@ -269,7 +276,11 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
if (spawnNeedsFloor) {
|
||||
val y = posY + blockBox.height
|
||||
val xs = posX until posX + blockBox.width
|
||||
cannotSpawn = cannotSpawn or xs.any { x -> !BlockCodex[world!!.getTileFromTerrain(x, y)].isSolid }
|
||||
cannotSpawn = cannotSpawn or xs.any { x ->
|
||||
world!!.getTileFromTerrain(x, y).let {
|
||||
!BlockCodex[it].isSolid || !canSpawnOnThisFloor(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !cannotSpawn
|
||||
@@ -297,7 +308,8 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
val posY = posY0 - blockBox.height + 1
|
||||
|
||||
if (!canSpawnHere(posX0, posY0)) {
|
||||
printdbg(this, "cannot spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
|
||||
printdbg(this, "cannot spawn fixture1 ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
|
||||
printStackTrace(this)
|
||||
return false
|
||||
}
|
||||
printdbg(this, "spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
|
||||
@@ -314,6 +326,12 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
blockBox.width * TILE_SIZED,
|
||||
blockBox.height * TILE_SIZED
|
||||
)
|
||||
this.intTilewiseHitbox.setFromWidthHeight(
|
||||
posX.toDouble(),
|
||||
posY.toDouble(),
|
||||
blockBox.width.toDouble(),
|
||||
blockBox.height.toDouble()
|
||||
)
|
||||
|
||||
// actually add this actor into the world
|
||||
INGAME.queueActorAddition(this)
|
||||
@@ -399,10 +417,16 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
blockBox.width * TILE_SIZED,
|
||||
blockBox.height * TILE_SIZED
|
||||
)
|
||||
this.intTilewiseHitbox.setFromWidthHeight(
|
||||
posX.toDouble(),
|
||||
posY.toDouble(),
|
||||
blockBox.width.toDouble(),
|
||||
blockBox.height.toDouble()
|
||||
)
|
||||
|
||||
// check for existing blocks (and fixtures)
|
||||
if (!canSpawnHere0(posX, posY)) {
|
||||
printdbg(this, "cannot spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
|
||||
printdbg(this, "cannot spawn fixture2 ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
|
||||
return false
|
||||
}
|
||||
printdbg(this, "spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
|
||||
@@ -471,21 +495,10 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
|
||||
protected var dropItem = false
|
||||
|
||||
/**
|
||||
* This function MUST BE super-called for make despawn call to work at all.
|
||||
*/
|
||||
override fun update(delta: Float) {
|
||||
// FIXME retrieving fixture by mining relied on a quirk that mining a actorblock would also drop the fixture.
|
||||
// FIXME since that particular method of operation causes so much problems, it is required to implement the
|
||||
// FIXME said feature "correctly"
|
||||
/*if (!flagDespawn && worldBlockPos != null) {
|
||||
// removal-by-player because player is removing the filler block by pick
|
||||
// no-flagDespawn check is there to prevent item dropping when externally despawned
|
||||
// (e.g. picked the fixture up in which case the fixture must not drop itself to the world; it must go into the actor's inventory)
|
||||
forEachBlockbox { x, y, _, _ ->
|
||||
if (!BlockCodex[world!!.getTileFromTerrain(x, y)].isActorBlock) {
|
||||
flagDespawn = true
|
||||
dropItem = true
|
||||
}
|
||||
}
|
||||
}*/
|
||||
if (!canBeDespawned) flagDespawn = false // actively deny despawning request if cannot be despawned
|
||||
if (canBeDespawned && flagDespawn) despawn()
|
||||
if (canBeDespawned && dropItem) dropSelfAsAnItem()
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package net.torvald.terrarum.modulebasegame.gameitems
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import net.torvald.terrarum.CommonResourcePool
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
|
||||
class ItemSeedOak(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingOak") {
|
||||
override var originalName = "ITEM_SEED_OAK"
|
||||
override var baseMass = 10.0
|
||||
override val materialId = "OOZE"
|
||||
override var inventoryCategory = Category.GENERIC
|
||||
override val itemImage: TextureRegion
|
||||
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(0,11)
|
||||
}
|
||||
class ItemSeedEbony(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingEbony") {
|
||||
override var originalName = "ITEM_SEED_EBONY"
|
||||
override var baseMass = 10.0
|
||||
override val materialId = "OOZE"
|
||||
override var inventoryCategory = Category.GENERIC
|
||||
override val itemImage: TextureRegion
|
||||
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(1,11)
|
||||
}
|
||||
class ItemSeedBirch(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingBirch") {
|
||||
override var originalName = "ITEM_SEED_BIRCH"
|
||||
override var baseMass = 10.0
|
||||
override val materialId = "OOZE"
|
||||
override var inventoryCategory = Category.GENERIC
|
||||
override val itemImage: TextureRegion
|
||||
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(2,11)
|
||||
}
|
||||
class ItemSeedRosewood(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingRosewood") {
|
||||
override var originalName = "ITEM_SEED_ROSEWOOD"
|
||||
override var baseMass = 10.0
|
||||
override val materialId = "OOZE"
|
||||
override var inventoryCategory = Category.GENERIC
|
||||
override val itemImage: TextureRegion
|
||||
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(3,11)
|
||||
}
|
||||
@@ -89,33 +89,6 @@ class ItemLogsRosewood(originalID: ItemID) : OreItemBase(originalID) {
|
||||
|
||||
|
||||
|
||||
class ItemSeedOak(originalID: ItemID) : OreItemBase(originalID) {
|
||||
override var originalName = "ITEM_SEED_OAK"
|
||||
override val materialId = "OOZE"
|
||||
override val itemImage: TextureRegion
|
||||
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(0,11)
|
||||
}
|
||||
class ItemSeedEbony(originalID: ItemID) : OreItemBase(originalID) {
|
||||
override var originalName = "ITEM_SEED_EBONY"
|
||||
override val materialId = "OOZE"
|
||||
override val itemImage: TextureRegion
|
||||
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(1,11)
|
||||
}
|
||||
class ItemSeedBirch(originalID: ItemID) : OreItemBase(originalID) {
|
||||
override var originalName = "ITEM_SEED_BIRCH"
|
||||
override val materialId = "OOZE"
|
||||
override val itemImage: TextureRegion
|
||||
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(2,11)
|
||||
}
|
||||
class ItemSeedRosewood(originalID: ItemID) : OreItemBase(originalID) {
|
||||
override var originalName = "ITEM_SEED_ROSEWOOD"
|
||||
override val materialId = "OOZE"
|
||||
override val itemImage: TextureRegion
|
||||
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(3,11)
|
||||
}
|
||||
|
||||
|
||||
|
||||
class OreStick(originalID: ItemID) : OreItemBase(originalID) {
|
||||
override var originalName = "ITEM_WOOD_STICK"
|
||||
override val materialId = "WOOD"
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package net.torvald.terrarum.modulebasegame.worldgenerator
|
||||
|
||||
import com.sudoplay.joise.Joise
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.random.XXHash32
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameworld.BlockAddress
|
||||
@@ -88,13 +86,7 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
|
||||
val thre = this - ibase
|
||||
return if (nextDouble(x, y, h) < 1.0 - thre) ibase else ibase + 1
|
||||
}
|
||||
|
||||
private fun nextDouble(x: Int, y: Int, h: Int): Double {
|
||||
return ((XXHash32.hashGeoCoord(x, y) * 31 + h) and 0xFFFFFF) / 16777216.0
|
||||
}
|
||||
private fun nextFloat(x: Int, y: Int, h: Int): Float {
|
||||
return ((XXHash32.hashGeoCoord(x, y) * 31 + h) and 0xFFFFFF) / 16777216f
|
||||
}
|
||||
|
||||
|
||||
private fun tryToPlant(xs: IntProgression, ys: Int, grassMap: Array<List<Int>>) {
|
||||
val treeSpecies = 0
|
||||
@@ -147,12 +139,12 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
|
||||
// if there is no grass, grassMap[x] is an empty list
|
||||
if (treeToSpawn[0] != 0) {
|
||||
grassMap[plot1].let { if (it.isEmpty()) null else it.takeRand(xs.first + plot1, ys, 1234) }?.let {
|
||||
plantTree(xs.first + plot1, it, treeSpecies, 1) // TODO use treeSize from the treeToSpawn
|
||||
plantTree(world, xs.first + plot1, it, treeSpecies, 1) // TODO use treeSize from the treeToSpawn
|
||||
}
|
||||
}
|
||||
if (treeToSpawn[1] != 0) {
|
||||
grassMap[plot2].let { if (it.isEmpty()) null else it.takeRand(xs.first + plot2, ys, 2345) }?.let {
|
||||
plantTree(xs.first + plot2, it, treeSpecies, 1) // TODO use treeSize from the treeToSpawn
|
||||
plantTree(world, xs.first + plot2, it, treeSpecies, 1) // TODO use treeSize from the treeToSpawn
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,7 +155,7 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
|
||||
if (treeToSpawn[0] != 0) {
|
||||
val treeSize = arrayOf(null, 0, 1, 2)[treeToSpawn[0]]
|
||||
grassMap[plot1].let { if (it.isEmpty()) null else it.takeRand(xs.first + plot1, ys, 4567) }?.let {
|
||||
plantTree(xs.first + plot1, it, treeSpecies, treeSize!!)
|
||||
plantTree(world, xs.first + plot1, it, treeSpecies, treeSize!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,121 +187,126 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
|
||||
}
|
||||
|
||||
// don't use POI -- generate tiles using code for randomisation
|
||||
/**
|
||||
* @param y where the grass/dirt tile is
|
||||
*/
|
||||
private fun plantTree(x: Int, y: Int, type: Int, size: Int) {
|
||||
val trunk = "basegame:" + ((if (size <= 1) 64 else 72) + type)
|
||||
val foliage = "basegame:" + (112 + type)
|
||||
companion object {
|
||||
/**
|
||||
* If a tree cannot be planted on the specified space, `false` will be returned
|
||||
*
|
||||
* @param y where the grass/dirt tile is
|
||||
* @param species 0: oak, 1: ebony, 2: birch, 3: rose
|
||||
* @param size 0: shrub, 1: normal tree, 2: large tree
|
||||
*/
|
||||
fun plantTree(world: GameWorld, x: Int, y: Int, species: Int, size: Int): Boolean {
|
||||
val trunk = "basegame:" + ((if (size <= 1) 64 else 72) + species)
|
||||
val foliage = "basegame:" + (112 + species)
|
||||
|
||||
var growCnt = 1
|
||||
if (size == 0) {
|
||||
val heightSum = 3
|
||||
var growCnt = 1
|
||||
if (size == 0) {
|
||||
val heightSum = 3
|
||||
|
||||
// check for minimum height
|
||||
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
// check for minimum height
|
||||
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
|
||||
if (chkM1 || chk0 || chkP1) {
|
||||
if (chkM1 || chk0 || chkP1) {
|
||||
// printdbg(this, "Ceiling not tall enough at $x, $y, aborting")
|
||||
return
|
||||
}
|
||||
|
||||
val stem = 1
|
||||
val bulb1 = 3 + fudgeN(x, y, 4095823)
|
||||
|
||||
// trunk
|
||||
for (i in 0 until stem) {
|
||||
for (xi in -1..+1) {
|
||||
if (xi != 0) {
|
||||
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
|
||||
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
|
||||
}
|
||||
else {
|
||||
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
|
||||
}
|
||||
return false
|
||||
}
|
||||
growCnt += 1
|
||||
}
|
||||
// bulb 1
|
||||
growCnt = drawBulb(x, y, 3, bulb1, foliage, growCnt)
|
||||
}
|
||||
else if (size == 1) {
|
||||
val heightSum = 5+3+2+1
|
||||
// check for minimum height
|
||||
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
|
||||
if (chkM1 || chk0 || chkP1) {
|
||||
val stem = 1
|
||||
val bulb1 = 3 + fudgeN(x, y, 4095823)
|
||||
|
||||
// trunk
|
||||
for (i in 0 until stem) {
|
||||
for (xi in -1..+1) {
|
||||
if (xi != 0) {
|
||||
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
|
||||
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
|
||||
}
|
||||
else {
|
||||
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
|
||||
}
|
||||
}
|
||||
growCnt += 1
|
||||
}
|
||||
// bulb 1
|
||||
growCnt = drawBulb(world, x, y, 3, bulb1, foliage, growCnt)
|
||||
}
|
||||
else if (size == 1) {
|
||||
val heightSum = 5 + 3 + 2 + 1
|
||||
// check for minimum height
|
||||
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
|
||||
if (chkM1 || chk0 || chkP1) {
|
||||
// printdbg(this, "Ceiling not tall enough at $x, $y, aborting")
|
||||
return
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// roll for dice until we get a height that fits into the given terrain
|
||||
val stem = 7 + fudgeN(x, y, 7548291, 1530948)
|
||||
val bulb1 = 4 + fudgeN(x, y, 345098)
|
||||
val bulb2 = 3 + fudgeN(x, y, 6093481)
|
||||
val bulb3 = 2 + fudgeN(x, y, 5413879)
|
||||
// roll for dice until we get a height that fits into the given terrain
|
||||
val stem = 7 + fudgeN(x, y, 7548291, 1530948)
|
||||
val bulb1 = 4 + fudgeN(x, y, 345098)
|
||||
val bulb2 = 3 + fudgeN(x, y, 6093481)
|
||||
val bulb3 = 2 + fudgeN(x, y, 5413879)
|
||||
// printdbg(this, "Planting tree at $x, $y; params: $stem, $bulb1, $bulb2, $bulb3")
|
||||
|
||||
// trunk
|
||||
for (i in 0 until stem) {
|
||||
for (xi in -1..+1) {
|
||||
if (xi != 0) {
|
||||
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
|
||||
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
|
||||
}
|
||||
else {
|
||||
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
|
||||
// trunk
|
||||
for (i in 0 until stem) {
|
||||
for (xi in -1..+1) {
|
||||
if (xi != 0) {
|
||||
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
|
||||
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
|
||||
}
|
||||
else {
|
||||
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
|
||||
}
|
||||
}
|
||||
growCnt += 1
|
||||
}
|
||||
// bulb base
|
||||
for (x in x - 2..x + 2) {
|
||||
val tileHere = world.getTileFromTerrain(x, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
|
||||
world.setTileTerrain(x, y - growCnt, foliage, true)
|
||||
}
|
||||
growCnt += 1
|
||||
// bulb 1
|
||||
growCnt = drawBulb(world, x, y, 7, bulb1, foliage, growCnt)
|
||||
// bulb 2
|
||||
growCnt = drawBulb(world, x, y, 5, bulb2, foliage, growCnt)
|
||||
// bulb 3
|
||||
growCnt = drawBulb(world, x, y, 3, bulb3, foliage, growCnt)
|
||||
}
|
||||
// bulb base
|
||||
for (x in x-2..x+2) {
|
||||
val tileHere = world.getTileFromTerrain(x, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
|
||||
world.setTileTerrain(x, y - growCnt, foliage, true)
|
||||
}
|
||||
growCnt += 1
|
||||
// bulb 1
|
||||
growCnt = drawBulb(x, y, 7, bulb1, foliage, growCnt)
|
||||
// bulb 2
|
||||
growCnt = drawBulb(x, y, 5, bulb2, foliage, growCnt)
|
||||
// bulb 3
|
||||
growCnt = drawBulb(x, y, 3, bulb3, foliage, growCnt)
|
||||
}
|
||||
else if (size == 2) {
|
||||
val heightSum = 12+4+3+2+1
|
||||
// check for minimum height
|
||||
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chkP2 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
else if (size == 2) {
|
||||
val heightSum = 12 + 4 + 3 + 2 + 1
|
||||
// check for minimum height
|
||||
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
val chkP2 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
|
||||
|
||||
if (chkM1 || chk0 || chkP1 || chkP2) {
|
||||
if (chkM1 || chk0 || chkP1 || chkP2) {
|
||||
// printdbg(this, "Ceiling not tall enough at $x, $y, aborting")
|
||||
return
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// roll for dice until we get a height that fits into the given terrain
|
||||
val stem = 15 + fudgeN(x, y, 14509, 509348, 412098357)
|
||||
val bulb1 = 5 + fudgeN(x, y, 1254)
|
||||
val bulb2 = 4 + fudgeN(x, y, 98134)
|
||||
val bulb3 = 3 + fudgeN(x, y, 123098)
|
||||
val bulb4 = 2 + fudgeN(x, y, 8712)
|
||||
// roll for dice until we get a height that fits into the given terrain
|
||||
val stem = 15 + fudgeN(x, y, 14509, 509348, 412098357)
|
||||
val bulb1 = 5 + fudgeN(x, y, 1254)
|
||||
val bulb2 = 4 + fudgeN(x, y, 98134)
|
||||
val bulb3 = 3 + fudgeN(x, y, 123098)
|
||||
val bulb4 = 2 + fudgeN(x, y, 8712)
|
||||
// printdbg(this, "Planting tree at $x, $y; params: $stem, $bulb1, $bulb2, $bulb3, $bulb4")
|
||||
|
||||
// soiling
|
||||
val tl1 = world.getTileFromTerrain(x - 1, y)
|
||||
val tl2 = world.getTileFromTerrain(x + 1, y)
|
||||
if (BlockCodex[tl2].hasTag("INCONSEQUENTIAL")) {
|
||||
world.setTileTerrain(x + 1, y, Block.GRASS, true)
|
||||
/*
|
||||
// soiling
|
||||
val tl1 = world.getTileFromTerrain(x - 1, y)
|
||||
val tl2 = world.getTileFromTerrain(x + 1, y)
|
||||
if (BlockCodex[tl2].hasTag("INCONSEQUENTIAL")) {
|
||||
world.setTileTerrain(x + 1, y, Block.GRASS, true)
|
||||
/*
|
||||
Case 1
|
||||
WW WW
|
||||
GG. -> GGG
|
||||
@@ -319,82 +316,94 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
|
||||
xG. -> xGG
|
||||
xG. xDG
|
||||
*/
|
||||
if (tl1 == Block.GRASS) {
|
||||
world.setTileTerrain(x, y + 1, Block.DIRT, true)
|
||||
if (tl1 == Block.GRASS) {
|
||||
world.setTileTerrain(x, y + 1, Block.DIRT, true)
|
||||
|
||||
if (BlockCodex[world.getTileFromTerrain(x + 1, y + 1)].hasTag("INCONSEQUENTIAL"))
|
||||
world.setTileTerrain(x + 1, y + 1, Block.DIRT, true)
|
||||
}
|
||||
/*
|
||||
if (BlockCodex[world.getTileFromTerrain(x + 1, y + 1)].hasTag("INCONSEQUENTIAL"))
|
||||
world.setTileTerrain(x + 1, y + 1, Block.DIRT, true)
|
||||
}
|
||||
/*
|
||||
Case 2
|
||||
WW WW
|
||||
.G. -> .GG
|
||||
xGx xGx
|
||||
*/
|
||||
}
|
||||
// trunk
|
||||
for (i in 0 until stem) {
|
||||
for (xi in -1..+2) {
|
||||
if (xi !in 0..1) {
|
||||
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
|
||||
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
|
||||
}
|
||||
else {
|
||||
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
|
||||
}
|
||||
}
|
||||
growCnt += 1
|
||||
}
|
||||
// bulb base
|
||||
for (x in x - 2..x + 3) {
|
||||
val tileHere = world.getTileFromTerrain(x, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
|
||||
world.setTileTerrain(x, y - growCnt, foliage, true)
|
||||
}
|
||||
growCnt += 1
|
||||
for (x in x - 3..x + 4) {
|
||||
val tileHere = world.getTileFromTerrain(x, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
|
||||
world.setTileTerrain(x, y - growCnt, foliage, true)
|
||||
}
|
||||
growCnt += 1
|
||||
// bulb 1
|
||||
growCnt = drawBulb(world, x, y, 10, bulb1, foliage, growCnt)
|
||||
// bulb 2
|
||||
growCnt = drawBulb(world, x, y, 8, bulb2, foliage, growCnt)
|
||||
// bulb 3
|
||||
growCnt = drawBulb(world, x, y, 6, bulb3, foliage, growCnt)
|
||||
// bulb 4
|
||||
growCnt = drawBulb(world, x, y, 4, bulb4, foliage, growCnt)
|
||||
}
|
||||
// trunk
|
||||
for (i in 0 until stem) {
|
||||
for (xi in -1..+2) {
|
||||
if (xi !in 0..1) {
|
||||
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
|
||||
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
|
||||
}
|
||||
else {
|
||||
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
|
||||
}
|
||||
else throw IllegalArgumentException("Unknown tree size: $size")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun drawBulb(world: GameWorld, x: Int, y: Int, width: Int, height: Int, foliage: ItemID, growCnt0: Int): Int {
|
||||
var growCnt = growCnt0
|
||||
val xStart = x - width / 2 + (1 - (width % 2))
|
||||
val xEnd = xStart + width
|
||||
var xStart2 = xStart
|
||||
var xEnd2 = xEnd
|
||||
|
||||
val r = (XXHash32.hashGeoCoord(x, y) * width * height + growCnt).and(0xffffff) / 16777216f
|
||||
r.let {
|
||||
if (it < 0.25) xStart2 += 1
|
||||
else if (it < 0.5) xEnd2 -= 1
|
||||
}
|
||||
val xs1 = xStart until xEnd
|
||||
val xs2 = xStart2 until xEnd2
|
||||
|
||||
for (i in 0 until height) {
|
||||
for (x in if (i == height - 1 && i > 0) xs2 else xs1) {
|
||||
val tileHere = world.getTileFromTerrain(x, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
|
||||
world.setTileTerrain(x, y - growCnt, foliage, true)
|
||||
}
|
||||
growCnt += 1
|
||||
}
|
||||
// bulb base
|
||||
for (x in x-2..x+3) {
|
||||
val tileHere = world.getTileFromTerrain(x, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
|
||||
world.setTileTerrain(x, y - growCnt, foliage, true)
|
||||
}
|
||||
growCnt += 1
|
||||
for (x in x-3..x+4) {
|
||||
val tileHere = world.getTileFromTerrain(x, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
|
||||
world.setTileTerrain(x, y - growCnt, foliage, true)
|
||||
}
|
||||
growCnt += 1
|
||||
// bulb 1
|
||||
growCnt = drawBulb(x, y, 10, bulb1, foliage, growCnt)
|
||||
// bulb 2
|
||||
growCnt = drawBulb(x, y, 8, bulb2, foliage, growCnt)
|
||||
// bulb 3
|
||||
growCnt = drawBulb(x, y, 6, bulb3, foliage, growCnt)
|
||||
// bulb 4
|
||||
growCnt = drawBulb(x, y, 4, bulb4, foliage, growCnt)
|
||||
return growCnt
|
||||
}
|
||||
else throw IllegalArgumentException("Unknown tree size: $size")
|
||||
}
|
||||
|
||||
private fun drawBulb(x: Int, y: Int, width: Int, height: Int, foliage: ItemID, growCnt0: Int): Int {
|
||||
var growCnt = growCnt0
|
||||
val xStart = x - width / 2 + (1 - (width % 2))
|
||||
val xEnd = xStart + width
|
||||
var xStart2 = xStart
|
||||
var xEnd2 = xEnd
|
||||
/**
|
||||
* @return normally distributed integer, for `maxvar=1`, `[-1, 0, 1]`; for `maxvar=2`, `[-2, -1, 0, 1, 2]`, etc.
|
||||
*/
|
||||
private fun fudgeN(x: Int, y: Int, vararg hs: Int) = hs.sumOf { (nextDouble(x, y, it) * 3).toInt() - 1 }
|
||||
|
||||
val r = (XXHash32.hashGeoCoord(x, y) * width * height + growCnt).and(0xffffff) / 16777216f
|
||||
r.let {
|
||||
if (it < 0.25) xStart2 += 1
|
||||
else if (it < 0.5) xEnd2 -= 1
|
||||
private fun nextDouble(x: Int, y: Int, h: Int): Double {
|
||||
return ((XXHash32.hashGeoCoord(x, y) * 31 + h) and 0xFFFFFF) / 16777216.0
|
||||
}
|
||||
val xs1 = xStart until xEnd
|
||||
val xs2 = xStart2 until xEnd2
|
||||
|
||||
for (i in 0 until height) {
|
||||
for (x in if (i == height - 1 && i > 0) xs2 else xs1) {
|
||||
val tileHere = world.getTileFromTerrain(x, y - growCnt)
|
||||
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
|
||||
world.setTileTerrain(x, y - growCnt, foliage, true)
|
||||
}
|
||||
growCnt += 1
|
||||
}
|
||||
return growCnt
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -418,11 +427,7 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
|
||||
return r
|
||||
}
|
||||
|
||||
/**
|
||||
* @return normally distributed integer, for `maxvar=1`, `[-1, 0, 1]`; for `maxvar=2`, `[-2, -1, 0, 1, 2]`, etc.
|
||||
*/
|
||||
private fun fudgeN(x: Int, y: Int, vararg hs: Int) = hs.sumOf { (nextDouble(x, y, it) * 3).toInt() - 1 }
|
||||
|
||||
|
||||
}
|
||||
|
||||
data class TreegenParams(
|
||||
|
||||
BIN
work_files/graphics/sprites/saplings.kra
LFS
Normal file
BIN
work_files/graphics/sprites/saplings.kra
LFS
Normal file
Binary file not shown.
Reference in New Issue
Block a user