mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
fixed a bug where non-solid blocks would still placed indefinitely
This commit is contained in:
@@ -8,6 +8,7 @@ import net.torvald.terrarum.gameitems.GameItem
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
||||
import net.torvald.terrarum.itemproperties.Material
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
|
||||
import net.torvald.terrarum.modulecomputers.gameactors.FixtureHomeComputer
|
||||
|
||||
@@ -36,7 +37,7 @@ class ItemHomeComputer(originalID: ItemID) : GameItem(originalID) {
|
||||
override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = mouseInInteractableRange(actor) {
|
||||
val item = FixtureHomeComputer()
|
||||
|
||||
if (item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY)) 1L else -1L
|
||||
if (item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY, if (actor is IngamePlayer) actor.uuid else null)) 1L else -1L
|
||||
// return true when placed, false when cannot be placed
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ class SheetSpriteAnimation(parentActor: ActorWithBody) : SpriteAnimation(parentA
|
||||
/**
|
||||
* Sets delays for each rows. Array size must be the same as the rows of the sheet
|
||||
*/
|
||||
var delays: FloatArray = floatArrayOf(0.2f)
|
||||
var delays: FloatArray = FloatArray(64) { 0.2f }
|
||||
set(value) {
|
||||
if (value.filter { it <= 0f }.isNotEmpty()) {
|
||||
throw IllegalArgumentException("Delay array contains zero or negative value: $delays")
|
||||
|
||||
@@ -5,14 +5,13 @@ import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.gameactors.ActorID
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
import net.torvald.terrarum.gameactors.PhysProperties
|
||||
import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import org.dyn4j.geometry.Vector2
|
||||
import java.util.*
|
||||
|
||||
typealias BlockBoxIndex = Int
|
||||
|
||||
@@ -42,6 +41,8 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
@Transient var mainUI: UICanvas? = null
|
||||
var inventory: FixtureInventory? = null
|
||||
|
||||
protected var actorThatInstalledThisFixture: UUID? = null
|
||||
|
||||
private constructor() : super(RenderOrder.BEHIND, PhysProperties.IMMOBILE, null)
|
||||
|
||||
|
||||
@@ -118,7 +119,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
* @param posY0 tile-wise bottem-centre position of the fixture (usually [Terrarum.mouseTileY])
|
||||
* @return true if successfully spawned, false if was not (e.g. space to spawn is occupied by something else)
|
||||
*/
|
||||
open fun spawn(posX0: Int, posY0: Int): Boolean {
|
||||
open fun spawn(posX0: Int, posY0: Int, installersUUID: UUID?): Boolean {
|
||||
// place filler blocks
|
||||
// place the filler blocks where:
|
||||
// origin posX: centre-left if mouseX is on the right-half of the game window,
|
||||
@@ -169,6 +170,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
INGAME.queueActorAddition(this)
|
||||
spawnRequestedTime = System.nanoTime()
|
||||
|
||||
actorThatInstalledThisFixture = installersUUID
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -183,7 +185,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
* @param thbh tile-wise Hitbox height
|
||||
* @return true if successfully spawned, false if was not (e.g. space to spawn is occupied by something else)
|
||||
*/
|
||||
open fun spawn(posX0: Int, posY0: Int, thbw: Int, thbh: Int): Boolean {
|
||||
open fun spawn(posX0: Int, posY0: Int, installersUUID: UUID?, thbw: Int, thbh: Int): Boolean {
|
||||
val posX = (posX0 - thbw.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 - thbh + 1
|
||||
|
||||
@@ -226,6 +228,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
INGAME.queueActorAddition(this)
|
||||
spawnRequestedTime = System.nanoTime()
|
||||
|
||||
actorThatInstalledThisFixture = installersUUID
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@ import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.gameactors.AVKey
|
||||
import net.torvald.terrarum.gameactors.Hitbox
|
||||
import net.torvald.terrarum.gameactors.Lightbox
|
||||
import net.torvald.terrarum.gameactors.Luminous
|
||||
import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import org.dyn4j.geometry.Vector2
|
||||
import java.util.*
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
/**
|
||||
* @param width of hitbox, in tiles, when the door is opened. Default to 2. Closed door always have width of 1. (this limits how big and thick the door can be)
|
||||
@@ -30,6 +30,8 @@ open class FixtureSwingingDoorBase : FixtureBase, Luminous {
|
||||
open val texturePath = "sprites/fixtures/door_test.tga"
|
||||
open val textureIdentifier = "fixtures-door_test.tga"
|
||||
open val customNameFun = { "DOOR_BASE" }
|
||||
open val doorClosedHoldLength: Second = 0.1f
|
||||
open val doorOpenedHoldLength: Second = 0.25f
|
||||
/* END OF CUTOMISABLE PARAMETERS */
|
||||
|
||||
private val tilewiseHitboxWidth = tw * 2 - twClosed
|
||||
@@ -42,6 +44,13 @@ open class FixtureSwingingDoorBase : FixtureBase, Luminous {
|
||||
@Transient override val shadeBoxList: ArrayList<Lightbox> = ArrayList()
|
||||
|
||||
protected var doorState = 0 // -1: open toward left, 0: closed, 1: open toward right
|
||||
protected var doorStateTimer: Second = 0f
|
||||
|
||||
@Transient private val doorHoldLength: HashMap<Int, Second> = hashMapOf(
|
||||
-1 to doorClosedHoldLength,
|
||||
1 to doorClosedHoldLength,
|
||||
0 to doorOpenedHoldLength
|
||||
)
|
||||
|
||||
// @Transient private var placeActorBlockLatch = false
|
||||
|
||||
@@ -49,6 +58,7 @@ open class FixtureSwingingDoorBase : FixtureBase, Luminous {
|
||||
BlockBox(BlockBox.FULL_COLLISION, 1, 1), // temporary value, will be overwritten by spawn()
|
||||
nameFun = { "item not loaded properly, alas!" }
|
||||
) {
|
||||
|
||||
nameFun = customNameFun
|
||||
|
||||
density = 1200.0
|
||||
@@ -75,7 +85,7 @@ open class FixtureSwingingDoorBase : FixtureBase, Luminous {
|
||||
reload()
|
||||
}
|
||||
|
||||
override fun spawn(posX: Int, posY: Int) = spawn(posX, posY, tilewiseHitboxWidth, tilewiseHitboxHeight)
|
||||
override fun spawn(posX: Int, posY: Int, installersUUID: UUID?): Boolean = spawn(posX, posY, installersUUID, tilewiseHitboxWidth, tilewiseHitboxHeight)
|
||||
|
||||
override fun reload() {
|
||||
super.reload()
|
||||
@@ -90,18 +100,27 @@ open class FixtureSwingingDoorBase : FixtureBase, Luminous {
|
||||
}
|
||||
|
||||
open protected fun closeDoor() {
|
||||
if (doorState != 0) {
|
||||
(sprite!! as SheetSpriteAnimation).currentRow = 0
|
||||
doorState = 0
|
||||
placeActorBlocks()
|
||||
}
|
||||
}
|
||||
|
||||
open protected fun openToRight() {
|
||||
if (doorState != 1) {
|
||||
(sprite!! as SheetSpriteAnimation).currentRow = 1
|
||||
doorState = 1
|
||||
placeActorBlocks()
|
||||
}
|
||||
}
|
||||
|
||||
open protected fun openToLeft() {
|
||||
if (doorState != -1) {
|
||||
(sprite!! as SheetSpriteAnimation).currentRow = 2
|
||||
doorState = -1
|
||||
placeActorBlocks()
|
||||
}
|
||||
}
|
||||
|
||||
/*override fun forEachBlockbox(action: (Int, Int, Int, Int) -> Unit) {
|
||||
@@ -142,22 +161,96 @@ open class FixtureSwingingDoorBase : FixtureBase, Luminous {
|
||||
|
||||
}
|
||||
|
||||
override fun update(delta: Float) {
|
||||
/*if (placeActorBlockLatch) {
|
||||
placeActorBlockLatch = false
|
||||
placeActorBlocks()
|
||||
}*/
|
||||
private fun mouseOnLeftSide(): Boolean {
|
||||
val mouseRelX = Terrarum.mouseX - hitbox.hitboxStart.x
|
||||
val mouseRelY = Terrarum.mouseY - hitbox.hitboxStart.y
|
||||
return 0.0 <= mouseRelX && mouseRelX < hitbox.width / 2 && mouseRelY in 0.0..hitbox.height
|
||||
}
|
||||
|
||||
private fun mouseOnRightSide(): Boolean {
|
||||
val mouseRelX = Terrarum.mouseX - hitbox.hitboxStart.x
|
||||
val mouseRelY = Terrarum.mouseY - hitbox.hitboxStart.y
|
||||
return hitbox.width / 2 < mouseRelX && mouseRelX <= hitbox.width && mouseRelY in 0.0..hitbox.height
|
||||
}
|
||||
|
||||
private fun ActorWithBody.ontheLeftSideOfDoor(): Boolean {
|
||||
return this.hitbox.centeredX < this@FixtureSwingingDoorBase.hitbox.centeredX
|
||||
}
|
||||
private fun ActorWithBody.ontheRightSideOfDoor(): Boolean {
|
||||
return this.hitbox.centeredX > this@FixtureSwingingDoorBase.hitbox.centeredX
|
||||
}
|
||||
|
||||
private fun ActorWithBody.movingTowardsRight(): Boolean {
|
||||
return ((this.controllerV ?: Vector2()) + this.externalV).x >= PHYS_EPSILON_VELO
|
||||
}
|
||||
private fun ActorWithBody.movingTowardsLeft(): Boolean {
|
||||
return ((this.controllerV ?: Vector2()) + this.externalV).x <= -PHYS_EPSILON_VELO
|
||||
}
|
||||
private fun ActorWithBody.notMoving(): Boolean {
|
||||
return ((this.controllerV ?: Vector2()) + this.externalV).x.absoluteValue < PHYS_EPSILON_VELO
|
||||
}
|
||||
|
||||
override fun update(delta: Float) {
|
||||
super.update(delta)
|
||||
|
||||
//if (!flagDespawn) placeActorBlocks()
|
||||
|
||||
when (doorState) {
|
||||
0/*CLOSED*/ -> {
|
||||
if (!flagDespawn && worldBlockPos != null) {
|
||||
val actors = INGAME.actorContainerActive.filterIsInstance<ActorWithBody>()
|
||||
|
||||
// auto opening and closing
|
||||
// TODO make this work with "player_alies" faction, not just a player
|
||||
val installer: IngamePlayer? = if (actorThatInstalledThisFixture == null) null else INGAME.actorContainerActive.filterIsInstance<IngamePlayer>().filter { it.uuid == actorThatInstalledThisFixture }.ifEmpty {
|
||||
INGAME.actorContainerInactive.filterIsInstance<IngamePlayer>().filter { it.uuid == actorThatInstalledThisFixture }
|
||||
}.getOrNull(0)
|
||||
|
||||
// if the door is "owned" by someone, restrict access to its "amicable" (defined using Faction subsystem) actors
|
||||
// if the door is owned by null, restrict access to ActorHumanoid and actors with "intelligent" actor value set up
|
||||
if (actorThatInstalledThisFixture == null || installer != null) {
|
||||
val amicableActors: List<ActorWithBody> = ArrayList(
|
||||
if (actorThatInstalledThisFixture == null)
|
||||
actors.filterIsInstance<ActorHumanoid>() union actors.filter { it.actorValue.getAsBoolean("intelligent") == true }
|
||||
else {
|
||||
val goodFactions = installer?.faction?.flatMap { it.factionAmicable }?.toHashSet()
|
||||
if (goodFactions != null)
|
||||
actors.filterIsInstance<Factionable>().filter {
|
||||
(it.faction.map { it.factionName } intersect goodFactions).isNotEmpty()
|
||||
} as List<ActorWithBody>
|
||||
else
|
||||
listOf()
|
||||
}
|
||||
).also {
|
||||
// add the installer of the door to the amicableActors if for some reason it was not added
|
||||
if (installer != null && !it.contains(installer)) it.add(0, installer)
|
||||
}.filter {
|
||||
// filter amicableActors so that ones standing near the door remain
|
||||
it.hitbox.intersects(this.hitbox)
|
||||
}
|
||||
|
||||
// automatic opening/closing
|
||||
if (doorStateTimer > doorHoldLength[doorState]!!) {
|
||||
var nobodyIsThere = true
|
||||
for (actor in amicableActors) {
|
||||
if (actor.ontheLeftSideOfDoor() && actor.movingTowardsRight()) {
|
||||
openToRight()
|
||||
nobodyIsThere = false
|
||||
break
|
||||
}
|
||||
else if (actor.ontheRightSideOfDoor() && actor.movingTowardsLeft()) {
|
||||
openToLeft()
|
||||
nobodyIsThere = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if (nobodyIsThere) {
|
||||
closeDoor()
|
||||
}
|
||||
|
||||
doorStateTimer = 0f
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
doorStateTimer += delta
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import java.util.*
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
/**
|
||||
@@ -44,7 +45,7 @@ internal class FixtureTapestry : FixtureBase {
|
||||
reload()
|
||||
}
|
||||
|
||||
override fun spawn(posX: Int, posY: Int) = spawn(posX, posY, tilewiseHitboxWidth, tilewiseHitboxHeight)
|
||||
override fun spawn(posX: Int, posY: Int, installersUUID: UUID?): Boolean = spawn(posX, posY, installersUUID, tilewiseHitboxWidth, tilewiseHitboxHeight)
|
||||
|
||||
override fun reload() {
|
||||
super.reload()
|
||||
|
||||
@@ -44,8 +44,13 @@ object BlockBase {
|
||||
val terrainUnderCursor = ingame.world.getTileFromTerrain(mouseTile.x, mouseTile.y)
|
||||
val wallUnderCursor = ingame.world.getTileFromWall(mouseTile.x, mouseTile.y)
|
||||
|
||||
// return false if there is a tile already
|
||||
if (isWall && BlockCodex[wallUnderCursor].isSolid || !isWall && (BlockCodex[terrainUnderCursor].isSolid || BlockCodex[terrainUnderCursor].isActorBlock))
|
||||
// return false if there is a same tile already (including non-solid!)
|
||||
if (isWall && wallUnderCursor == itemID || !isWall && terrainUnderCursor == itemID)
|
||||
return@mouseInInteractableRange -1L
|
||||
|
||||
// return false if there is a "solid" tile already
|
||||
if (isWall && BlockCodex[wallUnderCursor].isSolid ||
|
||||
!isWall && (BlockCodex[terrainUnderCursor].isSolid || BlockCodex[terrainUnderCursor].isActorBlock))
|
||||
return@mouseInInteractableRange -1L
|
||||
|
||||
// filter passed, do the job
|
||||
|
||||
@@ -10,6 +10,7 @@ import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
||||
import net.torvald.terrarum.itemproperties.Material
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
@@ -86,7 +87,7 @@ open class FixtureItemBase(originalID: ItemID, val fixtureClassName: String) : G
|
||||
override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = mouseInInteractableRange(actor) {
|
||||
val item = ghostItem.getAndSet(makeFixture()) // renew the "ghost" otherwise you'll be spawning exactly the same fixture again; old ghost will be returned
|
||||
|
||||
if (item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY)) 1 else -1
|
||||
if (item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY, if (actor is IngamePlayer) actor.uuid else null)) 1 else -1
|
||||
// return true when placed, false when cannot be placed
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user