diff --git a/assets/mods/basegame/creatures/CreatureHuman.json b/assets/mods/basegame/creatures/CreatureHuman.json index 24ffb9092..7955756d3 100644 --- a/assets/mods/basegame/creatures/CreatureHuman.json +++ b/assets/mods/basegame/creatures/CreatureHuman.json @@ -29,6 +29,6 @@ "intelligent": true, "barehandactionminheight": 80, - "basebarehanddiggingsize": 0.5 + "basebarehanddiggingsize": 8 } \ No newline at end of file diff --git a/assets/mods/basegame/creatures/CreatureWerebeastBase.json b/assets/mods/basegame/creatures/CreatureWerebeastBase.json index 319b55afd..e98cb08f4 100644 --- a/assets/mods/basegame/creatures/CreatureWerebeastBase.json +++ b/assets/mods/basegame/creatures/CreatureWerebeastBase.json @@ -29,6 +29,6 @@ "intelligent": true, "barehandactionminheight": 40, - "basebarehanddiggingsize": 1.0 + "basebarehanddiggingsize": 16 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/Terrarum.kt b/src/net/torvald/terrarum/Terrarum.kt index c9f6a0c47..9745103db 100644 --- a/src/net/torvald/terrarum/Terrarum.kt +++ b/src/net/torvald/terrarum/Terrarum.kt @@ -251,25 +251,25 @@ object Terrarum : Disposable { return file // TODO TEST CODE } - /** Position of the cursor in the world */ + /** Position of the cursor in the world, rounded */ val mouseX: Double get() = (WorldCamera.zoomedX + Gdx.input.x / (ingame?.screenZoom ?: 1f).toDouble()).fmod(WorldCamera.worldWidth.toDouble()) /** Position of the cursor in the world */ val mouseY: Double get() = (WorldCamera.zoomedY + Gdx.input.y / (ingame?.screenZoom ?: 1f).toDouble()) - /** Position of the cursor in the world */ + /** Position of the cursor in the world, rounded */ val oldMouseX: Double get() = (WorldCamera.zoomedX + (Gdx.input.x - Gdx.input.deltaX) / (ingame?.screenZoom ?: 1f).toDouble()).fmod(WorldCamera.worldWidth.toDouble()) /** Position of the cursor in the world */ val oldMouseY: Double get() = WorldCamera.zoomedY + (Gdx.input.y - Gdx.input.deltaY) / (ingame?.screenZoom ?: 1f).toDouble() - /** Position of the cursor in the world */ + /** Position of the cursor in the world, rounded */ @JvmStatic val mouseTileX: Int get() = (mouseX / TILE_SIZE).floorInt() /** Position of the cursor in the world */ @JvmStatic val mouseTileY: Int get() = (mouseY / TILE_SIZE).floorInt() - /** Position of the cursor in the world */ + /** Position of the cursor in the world, rounded */ @JvmStatic val oldMouseTileX: Int get() = (oldMouseX / TILE_SIZE).floorInt() /** Position of the cursor in the world */ diff --git a/src/net/torvald/terrarum/gameactors/AVKey.kt b/src/net/torvald/terrarum/gameactors/AVKey.kt index 14ec3c724..3413cac5a 100644 --- a/src/net/torvald/terrarum/gameactors/AVKey.kt +++ b/src/net/torvald/terrarum/gameactors/AVKey.kt @@ -133,4 +133,7 @@ object AVKey { const val __HISTORICAL_BORNTIME = "__borntime" // time_t const val __HISTORICAL_DEADTIME = "__deadtime" // time_t, -1 if not dead + + const val BAREHAND_MINHEIGHT = "barehandactionminheight" + const val BAREHAND_BASE_DIGSIZE = "basebarehanddiggingsize" } \ No newline at end of file diff --git a/src/net/torvald/terrarum/itemproperties/Calculate.kt b/src/net/torvald/terrarum/itemproperties/Calculate.kt index 6dfd25419..282cd1967 100644 --- a/src/net/torvald/terrarum/itemproperties/Calculate.kt +++ b/src/net/torvald/terrarum/itemproperties/Calculate.kt @@ -16,8 +16,8 @@ object Calculate { * * TODO Newtons as unit? */ - @JvmStatic fun pickaxePower(actor: ActorWithBody, material: Material): Float { - return (4.0 * material.forceMod.toDouble().sqrt() * (actor.avStrength / 1000.0)).toFloat() + @JvmStatic fun pickaxePower(actor: ActorWithBody, material: Material?): Float { + return (4.0 * (material?.forceMod?.toDouble() ?: 1.0).sqrt() * (actor.avStrength / 1000.0)).toFloat() } diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index ef7288ab6..eb63e4910 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -16,19 +16,18 @@ import net.torvald.terrarum.blockstats.MinimapComposer import net.torvald.terrarum.console.AVTracker import net.torvald.terrarum.console.ActorsList import net.torvald.terrarum.console.Authenticator -import net.torvald.terrarum.gameactors.Actor -import net.torvald.terrarum.gameactors.ActorID -import net.torvald.terrarum.gameactors.ActorWithBody -import net.torvald.terrarum.gameactors.WireActor +import net.torvald.terrarum.gameactors.* import net.torvald.terrarum.gamecontroller.IngameController import net.torvald.terrarum.gamecontroller.KeyToggler import net.torvald.terrarum.gameitem.GameItem +import net.torvald.terrarum.gameitem.inInteractableRange import net.torvald.terrarum.gameparticles.ParticleBase import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.WorldSimulator import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.modulebasegame.gameactors.* import net.torvald.terrarum.modulebasegame.gameactors.physicssolver.CollisionSolver +import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore import net.torvald.terrarum.modulebasegame.gameworld.GameEconomy import net.torvald.terrarum.modulebasegame.ui.* import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser @@ -483,15 +482,24 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { override fun worldPrimaryClickStart(actor: ActorWithBody, delta: Float) { //println("[Ingame] worldPrimaryClickStart $delta") + // prepare some variables + val itemOnGrip = ItemCodex[(actor as Pocketed).inventory.itemEquipped.get(GameItem.EquipPosition.HAND_GRIP)] // bring up the UIs of the fixtures (e.g. crafting menu from a crafting table) var uiOpened = false + val canPerformBarehandAction = actor.scale * actor.baseHitboxH >= actor.actorValue.getAsDouble(AVKey.BAREHAND_MINHEIGHT) ?: 4294967296.0 + // TODO actorsUnderMouse: support ROUNDWORLD val actorsUnderMouse: List = getActorsAt(Terrarum.mouseX, Terrarum.mouseY).filterIsInstance() if (actorsUnderMouse.size > 1) { App.printdbgerr(this, "Multiple fixtures at world coord ${Terrarum.mouseX}, ${Terrarum.mouseY}") } + + //////////////////////////////// + + + // #1. Try to open a UI under the cursor // scan for the one with non-null UI. // what if there's multiple of such fixtures? whatever, you are supposed to DISALLOW such situation. if (itemOnGrip?.inventoryCategory != GameItem.Category.TOOL) { // don't open the UI when player's holding a tool @@ -511,18 +519,30 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { } } - + // #2. If there is no UI under and if I'm holding an item, use it // don't want to open the UI and use the item at the same time, would ya? - if (!uiOpened) { - val consumptionSuccessful = itemOnGrip?.startPrimaryUse(actor, delta) ?: false + if (!uiOpened && itemOnGrip != null) { + val consumptionSuccessful = itemOnGrip.startPrimaryUse(actor, delta) if (consumptionSuccessful) - (actor as Pocketed).inventory.consumeItem(itemOnGrip!!) + (actor as Pocketed).inventory.consumeItem(itemOnGrip) + } + // #3. If I'm not holding any item and I can do barehandaction (size big enough that barehandactionminheight check passes), perform it + else if (itemOnGrip == null && canPerformBarehandAction) { + inInteractableRange(actor) { + performBarehandAction(actor, delta) + true + } } } override fun worldPrimaryClickEnd(actor: ActorWithBody, delta: Float) { + val canPerformBarehandAction = actor.scale * actor.baseHitboxH >= actor.actorValue.getAsDouble(AVKey.BAREHAND_MINHEIGHT) ?: 4294967296.0 val itemOnGrip = (actor as Pocketed).inventory.itemEquipped.get(GameItem.EquipPosition.HAND_GRIP) ItemCodex[itemOnGrip]?.endPrimaryUse(actor, delta) + + if (canPerformBarehandAction) { + actor.actorValue.set(AVKey.__ACTION_TIMER, 0.0) + } } // I have decided that left and right clicks must do the same thing, so no secondary use from now on. --Torvald on 2019-05-26 @@ -1101,6 +1121,32 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { } } + fun performBarehandAction(actor: ActorWithBody, delta: Float) { +// println("whack!") + + fun getActorsAtVicinity(worldX: Double, worldY: Double, radius: Double): List { + val outList = java.util.ArrayList() + try { + actorsRTree.find(worldX - radius, worldY - radius, worldX + radius, worldY + radius, outList) + } + catch (e: NullPointerException) { + } + return outList + } + + + val punchSize = actor.scale * actor.actorValue.getAsDouble(AVKey.BAREHAND_BASE_DIGSIZE)!! + + // if there are attackable actor (todo) on the "actor punch hitbox (todo)", attack them (todo) + val actorsUnderMouse: List = getActorsAtVicinity(Terrarum.mouseX, Terrarum.mouseY, punchSize / 2.0).filter { true } + + // else, punch a block + val punchBlockSize = punchSize.div(TILE_SIZED).floorInt() + if (punchBlockSize > 0) { + PickaxeCore.startPrimaryUse(actor, delta, null, Terrarum.mouseTileX, Terrarum.mouseTileY, 1.0 / punchBlockSize, punchBlockSize, punchBlockSize) + } + } + override fun pause() { paused = true } diff --git a/src/net/torvald/terrarum/modulebasegame/gameitems/PickaxeGeneric.kt b/src/net/torvald/terrarum/modulebasegame/gameitems/PickaxeGeneric.kt index d8fac983a..627f6b29b 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameitems/PickaxeGeneric.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameitems/PickaxeGeneric.kt @@ -3,6 +3,7 @@ package net.torvald.terrarum.modulebasegame.gameitems import com.badlogic.gdx.graphics.g2d.TextureRegion import net.torvald.terrarum.* 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.ActorWithBody @@ -19,43 +20,75 @@ import kotlin.math.roundToInt * Created by minjaesong on 2019-03-10. */ object PickaxeCore { - fun startPrimaryUse(actor: ActorWithBody, delta: Float, item: GameItem) = inInteractableRange(actor) { - val mouseTileX = Terrarum.mouseTileX - val mouseTileY = Terrarum.mouseTileY + /** + * @param mx centre position of the digging + * @param my centre position of the digging + * @param mw width of the digging + * @param mh height of the digging + */ + fun startPrimaryUse(actor: ActorWithBody, delta: Float, item: GameItem?, mx: Int, my: Int, dropProbability: Double = 1.0, mw: Int = 1, mh: Int = 1) = inInteractableRange(actor) { + // un-round the mx + val ww = INGAME.world.width + val apos = actor.centrePosPoint + val mx = if (apos.x < 0.0 && mx >= ww / 2) mx - ww + else if (apos.x > 0.0 && mx < ww / 2) mx + ww + else mx + val wmx = mx * TILE_SIZED + val wmy = my * TILE_SIZED - val mousePoint = Point2d(mouseTileX.toDouble(), mouseTileY.toDouble()) - val actorvalue = actor.actorValue + var xoff = -(mw / 2) // implicit flooring + var yoff = -(mh / 2) // implicit flooring + // if mw or mh is even number, make it closer toward the actor + if (mw % 2 == 0 && apos.x > wmx) xoff += 1 + if (mh % 2 == 0 && apos.y > wmy) yoff += 1 - item.using = true + var usageStatus = false - // linear search filter (check for intersection with tilewise mouse point and tilewise hitbox) - // return false if hitting actors - // ** below is commented out -- don't make actors obstruct the way of digging ** - /*var ret1 = true - INGAME.actorContainerActive.forEach { - if (it is ActorWBMovable && it.hIntTilewiseHitbox.intersects(mousePoint)) - ret1 = false // return is not allowed here - } - if (!ret1) return ret1*/ + for (oy in 0 until mh) for (ox in 0 until mw) { + val x = mx + xoff + ox + val y = my + yoff + oy - // return false if here's no tile - if (Block.AIR == (INGAME.world).getTileFromTerrain(mouseTileX, mouseTileY)) - return@inInteractableRange false + val mousePoint = Point2d(x.toDouble(), y.toDouble()) + val actorvalue = actor.actorValue - // filter passed, do the job - val swingDmgToFrameDmg = delta.toDouble() / actorvalue.getAsDouble(AVKey.ACTION_INTERVAL)!! + item?.using = true - (INGAME.world).inflictTerrainDamage( - mouseTileX, mouseTileY, - Calculate.pickaxePower(actor, item.material) * swingDmgToFrameDmg - )?.let { tileBroken -> - val drop = BlockCodex[tileBroken].drop - if (drop.isNotBlank()) { - INGAME.addNewActor(DroppedItem(drop, mouseTileX * TILE_SIZE, mouseTileY * TILE_SIZE)) + // linear search filter (check for intersection with tilewise mouse point and tilewise hitbox) + // return false if hitting actors + // ** below is commented out -- don't make actors obstruct the way of digging ** + /*var ret1 = true + INGAME.actorContainerActive.forEach { + if (it is ActorWBMovable && it.hIntTilewiseHitbox.intersects(mousePoint)) + ret1 = false // return is not allowed here } + if (!ret1) return ret1*/ + + // return false if here's no tile + if (Block.AIR == (INGAME.world).getTileFromTerrain(x, y)) { + usageStatus = usageStatus or false + continue + } + + // filter passed, do the job + val swingDmgToFrameDmg = delta.toDouble() / actorvalue.getAsDouble(AVKey.ACTION_INTERVAL)!! + + (INGAME.world).inflictTerrainDamage( + x, y, + Calculate.pickaxePower(actor, item?.material) * swingDmgToFrameDmg + )?.let { tileBroken -> + if (Math.random() < dropProbability) { + val drop = BlockCodex[tileBroken].drop + if (drop.isNotBlank()) { + INGAME.addNewActor(DroppedItem(drop, x * TILE_SIZE, y * TILE_SIZE)) + } + } + } + + usageStatus = usageStatus or true } - true + + usageStatus } fun endPrimaryUse(actor: ActorWithBody, delta: Float, item: GameItem): Boolean { @@ -93,7 +126,7 @@ class PickaxeCopper(originalID: ItemID) : GameItem(originalID) { super.name = "Copper Pickaxe" } - override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = PickaxeCore.startPrimaryUse(actor, delta, this) + override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = PickaxeCore.startPrimaryUse(actor, delta, this, Terrarum.mouseTileX, Terrarum.mouseTileY) override fun endPrimaryUse(actor: ActorWithBody, delta: Float) = PickaxeCore.endPrimaryUse(actor, delta, this) } @@ -120,7 +153,7 @@ class PickaxeIron(originalID: ItemID) : GameItem(originalID) { super.name = "Iron Pickaxe" } - override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = PickaxeCore.startPrimaryUse(actor , delta, this) + override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = PickaxeCore.startPrimaryUse(actor , delta, this, Terrarum.mouseTileX, Terrarum.mouseTileY) override fun endPrimaryUse(actor: ActorWithBody, delta: Float) = PickaxeCore.endPrimaryUse(actor, delta, this) } @@ -147,6 +180,6 @@ class PickaxeSteel(originalID: ItemID) : GameItem(originalID) { super.name = "Steel Pickaxe" } - override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = PickaxeCore.startPrimaryUse(actor, delta, this) + override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = PickaxeCore.startPrimaryUse(actor, delta, this, Terrarum.mouseTileX, Terrarum.mouseTileY) override fun endPrimaryUse(actor: ActorWithBody, delta: Float) = PickaxeCore.endPrimaryUse(actor, delta, this) } \ No newline at end of file