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.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

View File

@@ -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 {

View File

@@ -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
*/

View File

@@ -31,11 +31,11 @@ open class FixtureInventory() {
/**
* 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
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<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
@@ -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<InventoryPair> {

View File

@@ -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"))
}

View File

@@ -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
)