actor walk and jump power is reduced when encumbered (temp. commented out)

This commit is contained in:
minjaesong
2023-09-12 13:33:46 +09:00
parent e6056a79af
commit 53060fc90c
6 changed files with 95 additions and 28 deletions

View File

@@ -19,6 +19,7 @@ import net.torvald.terrarum.gameworld.BlockAddress
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
@@ -26,6 +27,7 @@ import org.dyn4j.geometry.Vector2
import java.util.* import java.util.*
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlin.math.max import kotlin.math.max
import kotlin.math.pow
import kotlin.math.roundToInt import kotlin.math.roundToInt
@@ -243,6 +245,11 @@ open class ActorWithBody : Actor {
val avStrength: Double val avStrength: Double
get() = (actorValue.getAsDouble(AVKey.STRENGTH) ?: 1000.0) * get() = (actorValue.getAsDouble(AVKey.STRENGTH) ?: 1000.0) *
(actorValue.getAsDouble(AVKey.STRENGTHBUFF) ?: 1.0) * scale (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? var avBaseStrength: Double?
get() = actorValue.getAsDouble(AVKey.STRENGTH) get() = actorValue.getAsDouble(AVKey.STRENGTH)
set(value) { set(value) {
@@ -262,11 +269,15 @@ open class ActorWithBody : Actor {
accelMultMovement * accelMultMovement *
scale.sqrt() scale.sqrt()
} }
val encumberment: Double
get() = if (this is Pocketed) this.inventory.encumberment else 0.0
val avSpeedCap: Double val avSpeedCap: Double
get() = actorValue.getAsDouble(AVKey.SPEED)!! * get() = actorValue.getAsDouble(AVKey.SPEED)!! * // base stat
(actorValue.getAsDouble(AVKey.SPEEDBUFF) ?: 1.0) * (actorValue.getAsDouble(AVKey.SPEEDBUFF) ?: 1.0) * // buffed stat
speedMultByTile * speedMultByTile * // tile-specific
scale.sqrt() 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 * Flags and Properties
@@ -1565,6 +1576,16 @@ open class ActorWithBody : Actor {
return interpolateLinear(submergedRatio, notSubmergedCap, normalisedViscocity) 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 /** about get going
* for about stopping, see setHorizontalFriction */ * for about stopping, see setHorizontalFriction */
internal inline val accelMultMovement: Double internal inline val accelMultMovement: Double

View File

@@ -49,7 +49,7 @@ internal object Inventory : ConsoleCommand {
private fun getActor() = Terrarum.ingame?.getActorByID(targetID) as? Pocketed private fun getActor() = Terrarum.ingame?.getActorByID(targetID) as? Pocketed
private fun listInventory(actor: Pocketed) { private fun listInventory(actor: Pocketed) {
if (actor.inventory.getTotalUniqueCount() == 0L) { if (actor.inventory.totalUniqueCount == 0L) {
Echo("(inventory empty)") Echo("(inventory empty)")
} }
else { else {

View File

@@ -14,6 +14,7 @@ import net.torvald.terrarum.gameactors.faction.Faction
import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.realestate.LandUtil
import org.dyn4j.geometry.Vector2 import org.dyn4j.geometry.Vector2
import kotlin.math.pow
/** /**
* Humanoid actor class to provide same controlling function (such as work, jump) * 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 { 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 @Transient private var oldMAX_JUMP_LENGTH = -1 // init
@@ -652,7 +653,11 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
} }
private val jumpPower: Double 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 { private fun jumpFunc(len: Int, counter: Int): Double {
// linear time mode // linear time mode
@@ -662,6 +667,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
return timedJumpCharge return timedJumpCharge
} }
/** /**
* See ./work_files/Jump power by pressing time.gcx * See ./work_files/Jump power by pressing time.gcx
*/ */

View File

@@ -31,11 +31,11 @@ open class FixtureInventory() {
/** /**
* Sorted by referenceID. * Sorted by referenceID.
*/ */
val itemList = SortedArrayList<InventoryPair>() protected val itemList = SortedArrayList<InventoryPair>()
var wallet = BigInteger("0") // unified currency for whole civs; Dwarf Fortress approach seems too complicated var wallet = BigInteger("0") // unified currency for whole civs; Dwarf Fortress approach seems too complicated
fun isEmpty() = getTotalCount() == 0L fun isEmpty() = totalCount == 0L
fun isNotEmpty() = getTotalCount() > 0 fun isNotEmpty() = totalCount > 0
open fun add(itemID: ItemID, count: Long = 1) { open fun add(itemID: ItemID, count: Long = 1) {
if (ItemCodex[itemID] == null) if (ItemCodex[itemID] == null)
@@ -81,6 +81,8 @@ open class FixtureInventory() {
itemList.add(InventoryPair(item.dynamicID, count)) itemList.add(InventoryPair(item.dynamicID, count))
} }
// insertionSortLastElem(itemList) // insertionSortLastElem(itemList)
updateEncumbrance()
} }
open fun remove(itemID: ItemID, count: Long) = remove(ItemCodex[itemID]!!, count) {} open fun remove(itemID: ItemID, count: Long) = remove(ItemCodex[itemID]!!, count) {}
@@ -124,12 +126,26 @@ open class FixtureInventory() {
else { else {
// throw InventoryFailedTransactionError("[${this.javaClass.canonicalName}] Tried to remove $item, but the inventory does not have it.") // 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<GameItem, Amounts> * HashMap<GameItem, Amounts>
*/ */
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 * Get capacity of inventory
@@ -139,33 +155,52 @@ open class FixtureInventory() {
get() = if (capacityMode == CAPACITY_MODE_NO_ENCUMBER) get() = if (capacityMode == CAPACITY_MODE_NO_ENCUMBER)
maxCapacity.toDouble() maxCapacity.toDouble()
else if (capacityMode == CAPACITY_MODE_WEIGHT) else if (capacityMode == CAPACITY_MODE_WEIGHT)
getTotalWeight() totalWeight
else 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 * 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 * 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 * Check whether the itemList contains too many items
* @return * @return
*/ */
val isEncumbered: Boolean 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) get() = if (capacityMode == CAPACITY_MODE_NO_ENCUMBER)
false 0.0
else if (capacityMode == CAPACITY_MODE_WEIGHT) else if (capacityMode == CAPACITY_MODE_WEIGHT)
maxCapacity < capacity capacity / maxCapacity
else else
false 0.0
fun contains(item: GameItem) = contains(item.dynamicID) fun contains(item: GameItem) = contains(item.dynamicID)
fun contains(id: ItemID) = fun contains(id: ItemID) =
@@ -218,6 +253,11 @@ open class FixtureInventory() {
open fun clear() { open fun clear() {
itemList.clear() itemList.clear()
} }
fun updateEncumbrance() {
totalWeight0 = itemList.sumOf { ItemCodex[it.itm]!!.mass * it.qty }
totalCount0 = itemList.sumOf { it.qty }
}
} }
class InventoryPair : Comparable<InventoryPair> { class InventoryPair : Comparable<InventoryPair> {

View File

@@ -228,7 +228,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
} }
targetItemToAlter?.let { 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)) (it.keyMode == CraftingCodex.CraftingItemKeyMode.TAG && ItemCodex[itemPair.itm]!!.hasTag(it.key))
} }
changeIngredient(oldItem, itemID) changeIngredient(oldItem, itemID)
@@ -261,7 +261,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
recipe.ingredients.forEach { ingredient -> recipe.ingredients.forEach { ingredient ->
val selectedItem: ItemID = if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) { 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 // 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 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")) }.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 = { _,_ -> buttonCraft.clickOnceListener = { _,_ ->
getPlayerInventory().let { player -> recipeClicked?.let { recipe -> getPlayerInventory().let { player -> recipeClicked?.let { recipe ->
// check if player has enough amount of ingredients // 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 (player.searchByID(itm)?.qty ?: -1) >= qty * craftMult
} }
if (itemCraftable) { if (itemCraftable) {
itemListIngredients.getInventory().itemList.forEach { (itm, qty) -> itemListIngredients.getInventory().forEach { (itm, qty) ->
player.remove(itm, qty * craftMult) player.remove(itm, qty * craftMult)
} }
player.add(recipe.product, recipe.moq * 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 * Updates Craft! button so that the button is correctly highlighted
*/ */
fun refreshCraftButtonStatus() { fun refreshCraftButtonStatus() {
val itemCraftable = if (itemListIngredients.getInventory().itemList.size < 1) false val itemCraftable = if (itemListIngredients.getInventory().totalUniqueCount < 1) false
else getPlayerInventory().let { player -> else getPlayerInventory().let { player ->
// check if player has enough amount of ingredients // 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 (player.searchByID(itm)?.qty ?: -1) >= qty * craftMult
} }
} }
@@ -544,7 +544,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
return recipe.ingredients.map { ingredient -> return recipe.ingredients.map { ingredient ->
val selectedItem = if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) { 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 // 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 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")) }.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"))
} }

View File

@@ -71,7 +71,7 @@ internal class UIInventoryCells(
itemList.rebuild(full.catBar.catIconsMeaning[full.catBar.selectedIcon]) itemList.rebuild(full.catBar.catIconsMeaning[full.catBar.selectedIcon])
equipped.rebuild() equipped.rebuild()
encumbrancePerc = full.actor.inventory.capacity.toFloat() / full.actor.inventory.maxCapacity encumbrancePerc = full.actor.inventory.encumberment.toFloat()
isEncumbered = full.actor.inventory.isEncumbered isEncumbered = full.actor.inventory.isEncumbered
} }
@@ -135,7 +135,7 @@ internal class UIInventoryCells(
batch.color = Color.LIGHT_GRAY batch.color = Color.LIGHT_GRAY
if (App.IS_DEVELOPMENT_BUILD) { if (App.IS_DEVELOPMENT_BUILD) {
App.fontSmallNumbers.draw(batch, App.fontSmallNumbers.draw(batch,
"${full.actor.inventory.capacity}/${full.actor.inventory.maxCapacity}", "enc: ${full.actor.inventory.encumberment}",
encumbBarTextXPos, encumbBarTextXPos,
encumbBarYPos + controlHelpHeight - 4f encumbBarYPos + controlHelpHeight - 4f
) )