From 53060fc90c1ab48955d8be88b9d792d45e84f91e Mon Sep 17 00:00:00 2001 From: minjaesong Date: Tue, 12 Sep 2023 13:33:46 +0900 Subject: [PATCH] actor walk and jump power is reduced when encumbered (temp. commented out) --- .../terrarum/gameactors/ActorWithBody.kt | 29 +++++++-- .../modulebasegame/console/Inventory.kt | 2 +- .../gameactors/ActorHumanoid.kt | 10 ++- .../gameactors/FixtureInventory.kt | 64 +++++++++++++++---- .../terrarum/modulebasegame/ui/UICrafting.kt | 14 ++-- .../modulebasegame/ui/UIInventoryCells.kt | 4 +- 6 files changed, 95 insertions(+), 28 deletions(-) diff --git a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt index 549b99063..7c7db2d34 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt @@ -19,6 +19,7 @@ import net.torvald.terrarum.gameworld.BlockAddress import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer +import net.torvald.terrarum.modulebasegame.gameactors.Pocketed import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack @@ -26,6 +27,7 @@ import org.dyn4j.geometry.Vector2 import java.util.* import kotlin.math.absoluteValue import kotlin.math.max +import kotlin.math.pow import kotlin.math.roundToInt @@ -243,6 +245,11 @@ open class ActorWithBody : Actor { val avStrength: Double get() = (actorValue.getAsDouble(AVKey.STRENGTH) ?: 1000.0) * (actorValue.getAsDouble(AVKey.STRENGTHBUFF) ?: 1.0) * scale + /** + * Apparent strength scaled so that 1.0 is default value + */ + val avStrengthNormalised: Double + get() = avStrength / 1000.0 var avBaseStrength: Double? get() = actorValue.getAsDouble(AVKey.STRENGTH) set(value) { @@ -262,11 +269,15 @@ open class ActorWithBody : Actor { accelMultMovement * scale.sqrt() } + val encumberment: Double + get() = if (this is Pocketed) this.inventory.encumberment else 0.0 + val avSpeedCap: Double - get() = actorValue.getAsDouble(AVKey.SPEED)!! * - (actorValue.getAsDouble(AVKey.SPEEDBUFF) ?: 1.0) * - speedMultByTile * - scale.sqrt() + get() = actorValue.getAsDouble(AVKey.SPEED)!! * // base stat + (actorValue.getAsDouble(AVKey.SPEEDBUFF) ?: 1.0) * // buffed stat + speedMultByTile * // tile-specific + scale.sqrt() // taller actors have longer legs but also receives relatively weaker gravity -> pow(0.5) +// ((encumberment / avStrengthNormalised).pow(-2.0/3.0)).coerceIn(0.1, 1.0) // encumbered actors move slower /** * Flags and Properties @@ -1565,6 +1576,16 @@ open class ActorWithBody : Actor { return interpolateLinear(submergedRatio, notSubmergedCap, normalisedViscocity) } + internal inline val jumpMultByTile: Double + get() { + val notSubmergedCap = if (grounded) + feetViscosity.viscosityToMult() + else + bodyViscosity.viscosityToMult() + val normalisedViscocity = bodyViscosity.viscosityToMult() + + return interpolateLinear(submergedRatio, notSubmergedCap, normalisedViscocity) + } /** about get going * for about stopping, see setHorizontalFriction */ internal inline val accelMultMovement: Double diff --git a/src/net/torvald/terrarum/modulebasegame/console/Inventory.kt b/src/net/torvald/terrarum/modulebasegame/console/Inventory.kt index 8809e5445..bd6d85c9b 100644 --- a/src/net/torvald/terrarum/modulebasegame/console/Inventory.kt +++ b/src/net/torvald/terrarum/modulebasegame/console/Inventory.kt @@ -49,7 +49,7 @@ internal object Inventory : ConsoleCommand { private fun getActor() = Terrarum.ingame?.getActorByID(targetID) as? Pocketed private fun listInventory(actor: Pocketed) { - if (actor.inventory.getTotalUniqueCount() == 0L) { + if (actor.inventory.totalUniqueCount == 0L) { Echo("(inventory empty)") } else { diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt index a6f5dafd8..1ad7f0a2e 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt @@ -14,6 +14,7 @@ import net.torvald.terrarum.gameactors.faction.Faction import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.realestate.LandUtil import org.dyn4j.geometry.Vector2 +import kotlin.math.pow /** * Humanoid actor class to provide same controlling function (such as work, jump) @@ -592,7 +593,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L } private fun getJumpAcc(pwr: Double, timedJumpCharge: Double): Double { - return pwr * timedJumpCharge * JUMP_ACCELERATION_MOD * Math.pow(scale, 0.25) // positive value + return pwr * timedJumpCharge * JUMP_ACCELERATION_MOD } @Transient private var oldMAX_JUMP_LENGTH = -1 // init @@ -652,7 +653,11 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L } private val jumpPower: Double - get() = actorValue.getAsDouble(AVKey.JUMPPOWER)!! * (actorValue.getAsDouble(AVKey.JUMPPOWERBUFF) ?: 1.0) + get() = actorValue.getAsDouble(AVKey.JUMPPOWER)!! * // base stat + (actorValue.getAsDouble(AVKey.JUMPPOWERBUFF) ?: 1.0) * // buffed stat + jumpMultByTile * // tile-specific + scale.pow(0.25) +// ((encumberment / avStrengthNormalised).pow(-1.0/3.0)).coerceIn(0.1, 1.0) // encumbered actors move slower private fun jumpFunc(len: Int, counter: Int): Double { // linear time mode @@ -662,6 +667,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L return timedJumpCharge } + /** * See ./work_files/Jump power by pressing time.gcx */ diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt index 5fca12eb4..4ec8b375f 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt @@ -31,11 +31,11 @@ open class FixtureInventory() { /** * Sorted by referenceID. */ - val itemList = SortedArrayList() + protected val itemList = SortedArrayList() var wallet = BigInteger("0") // unified currency for whole civs; Dwarf Fortress approach seems too complicated - fun isEmpty() = getTotalCount() == 0L - fun isNotEmpty() = getTotalCount() > 0 + fun isEmpty() = totalCount == 0L + fun isNotEmpty() = totalCount > 0 open fun add(itemID: ItemID, count: Long = 1) { if (ItemCodex[itemID] == null) @@ -81,6 +81,8 @@ open class FixtureInventory() { itemList.add(InventoryPair(item.dynamicID, count)) } // insertionSortLastElem(itemList) + + updateEncumbrance() } open fun remove(itemID: ItemID, count: Long) = remove(ItemCodex[itemID]!!, count) {} @@ -124,12 +126,26 @@ open class FixtureInventory() { else { // throw InventoryFailedTransactionError("[${this.javaClass.canonicalName}] Tried to remove $item, but the inventory does not have it.") } + + itemList.sumOf { ItemCodex[it.itm]!!.mass * it.qty } + + updateEncumbrance() } /** * HashMap */ - inline fun forEach(consumer: (InventoryPair) -> Unit) = itemList.forEach(consumer) + fun forEach(consumer: (InventoryPair) -> Unit) { + itemList.forEach(consumer) + updateEncumbrance() + } + + fun first(predicate: (InventoryPair) -> Boolean) = itemList.first(predicate) + fun all(predicate: (InventoryPair) -> Boolean) = itemList.all(predicate) + fun any(predicate: (InventoryPair) -> Boolean) = itemList.any(predicate) + fun none(predicate: (InventoryPair) -> Boolean) = itemList.none() + fun filter(predicate: (InventoryPair) -> Boolean) = itemList.filter(predicate) + fun map(transformation: (InventoryPair) -> Any) = itemList.map(transformation) /** * Get capacity of inventory @@ -139,33 +155,52 @@ open class FixtureInventory() { get() = if (capacityMode == CAPACITY_MODE_NO_ENCUMBER) maxCapacity.toDouble() else if (capacityMode == CAPACITY_MODE_WEIGHT) - getTotalWeight() + totalWeight else - getTotalCount().toDouble() + totalCount.toDouble() - fun getTotalWeight(): Double = itemList.sumOf { ItemCodex[it.itm]!!.mass * it.qty } + @Transient private var totalWeight0 = -1.0 + + val totalWeight: Double// = itemList.sumOf { ItemCodex[it.itm]!!.mass * it.qty } + get() { + if (totalWeight0 < 0.0) updateEncumbrance() + return totalWeight0 + } + + @Transient private var totalCount0 = -1L /** * Real amount */ - fun getTotalCount(): Long = itemList.sumOf { it.qty } + val totalCount: Long + get() { + if (totalCount0 < 0) updateEncumbrance() + return totalCount0 + } /** * Unique amount, multiple items are calculated as one */ - fun getTotalUniqueCount(): Long = itemList.size.toLong() + val totalUniqueCount: Long + get() = itemList.size.toLong() /** * Check whether the itemList contains too many items * @return */ val isEncumbered: Boolean + get() = encumberment >= 1.0 + + /** + * How encumbered the actor is. 1.0 if weight of the items are exactly same as the capacity limit, >1.0 if encumbered. + */ + val encumberment: Double get() = if (capacityMode == CAPACITY_MODE_NO_ENCUMBER) - false + 0.0 else if (capacityMode == CAPACITY_MODE_WEIGHT) - maxCapacity < capacity + capacity / maxCapacity else - false + 0.0 fun contains(item: GameItem) = contains(item.dynamicID) fun contains(id: ItemID) = @@ -218,6 +253,11 @@ open class FixtureInventory() { open fun clear() { itemList.clear() } + + fun updateEncumbrance() { + totalWeight0 = itemList.sumOf { ItemCodex[it.itm]!!.mass * it.qty } + totalCount0 = itemList.sumOf { it.qty } + } } class InventoryPair : Comparable { diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt b/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt index f985f4c2a..6792c11a2 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UICrafting.kt @@ -228,7 +228,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory { } targetItemToAlter?.let { - val oldItem = _getItemListIngredients().getInventory().itemList.first { itemPair -> + val oldItem = _getItemListIngredients().getInventory().first { itemPair -> (it.keyMode == CraftingCodex.CraftingItemKeyMode.TAG && ItemCodex[itemPair.itm]!!.hasTag(it.key)) } changeIngredient(oldItem, itemID) @@ -261,7 +261,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory { recipe.ingredients.forEach { ingredient -> val selectedItem: ItemID = if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) { // If the player has the required item, use it; otherwise, will take an item from the ItemCodex - val selectedItem = playerInventory.itemList.filter { (itm, qty) -> + val selectedItem = playerInventory.filter { (itm, qty) -> ItemCodex[itm]?.tags?.contains(ingredient.key) == true && qty >= ingredient.qty }.maxByOrNull { it.qty }?.itm ?: ((ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.hasTag(ingredient.key)) it.key else null }) ?: throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed")) @@ -306,13 +306,13 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory { buttonCraft.clickOnceListener = { _,_ -> getPlayerInventory().let { player -> recipeClicked?.let { recipe -> // check if player has enough amount of ingredients - val itemCraftable = itemListIngredients.getInventory().itemList.all { (itm, qty) -> + val itemCraftable = itemListIngredients.getInventory().all { (itm, qty) -> (player.searchByID(itm)?.qty ?: -1) >= qty * craftMult } if (itemCraftable) { - itemListIngredients.getInventory().itemList.forEach { (itm, qty) -> + itemListIngredients.getInventory().forEach { (itm, qty) -> player.remove(itm, qty * craftMult) } player.add(recipe.product, recipe.moq * craftMult) @@ -365,10 +365,10 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory { * Updates Craft! button so that the button is correctly highlighted */ fun refreshCraftButtonStatus() { - val itemCraftable = if (itemListIngredients.getInventory().itemList.size < 1) false + val itemCraftable = if (itemListIngredients.getInventory().totalUniqueCount < 1) false else getPlayerInventory().let { player -> // check if player has enough amount of ingredients - itemListIngredients.getInventory().itemList.all { (itm, qty) -> + itemListIngredients.getInventory().all { (itm, qty) -> (player.searchByID(itm)?.qty ?: -1) >= qty * craftMult } } @@ -544,7 +544,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory { return recipe.ingredients.map { ingredient -> val selectedItem = if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) { // If the player has the required item, use it; otherwise, will take an item from the ItemCodex - inventory.itemList.filter { (itm, qty) -> + inventory.filter { (itm, qty) -> ItemCodex[itm]?.tags?.contains(ingredient.key) == true && qty >= ingredient.qty }.maxByOrNull { it.qty }?.itm ?: ((ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.hasTag(ingredient.key)) it.key else null }) ?: throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed")) } diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryCells.kt b/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryCells.kt index 65d1e63ca..1575ab54a 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryCells.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryCells.kt @@ -71,7 +71,7 @@ internal class UIInventoryCells( itemList.rebuild(full.catBar.catIconsMeaning[full.catBar.selectedIcon]) equipped.rebuild() - encumbrancePerc = full.actor.inventory.capacity.toFloat() / full.actor.inventory.maxCapacity + encumbrancePerc = full.actor.inventory.encumberment.toFloat() isEncumbered = full.actor.inventory.isEncumbered } @@ -135,7 +135,7 @@ internal class UIInventoryCells( batch.color = Color.LIGHT_GRAY if (App.IS_DEVELOPMENT_BUILD) { App.fontSmallNumbers.draw(batch, - "${full.actor.inventory.capacity}/${full.actor.inventory.maxCapacity}", + "enc: ${full.actor.inventory.encumberment}", encumbBarTextXPos, encumbBarYPos + controlHelpHeight - 4f )