From ce08b47423a5f2d1ed103ae58fbb42ccfc3946ed Mon Sep 17 00:00:00 2001 From: Song Minjae Date: Tue, 25 Apr 2017 02:59:59 +0900 Subject: [PATCH] fresh-new dynamic items (e.g. pickaxe) can be stacked --- src/net/torvald/terrarum/AmmoMeterProxy.kt | 4 +- src/net/torvald/terrarum/StateInGame.kt | 5 +- src/net/torvald/terrarum/StateUITest.kt | 4 +- .../torvald/terrarum/UIItemInventoryElem.kt | 2 +- .../terrarum/gameactors/ActorHumanoid.kt | 2 +- .../terrarum/gameactors/ActorInventory.kt | 90 ++++++++++++++----- .../terrarum/gameactors/HumanoidNPC.kt | 2 +- .../torvald/terrarum/gameactors/Pocketed.kt | 5 +- .../terrarum/itemproperties/InventoryItem.kt | 13 ++- .../terrarum/itemproperties/ItemCodex.kt | 14 +-- src/net/torvald/terrarum/langpack/Lang.kt | 4 +- src/net/torvald/terrarum/ui/UIInventory.kt | 4 +- 12 files changed, 102 insertions(+), 47 deletions(-) diff --git a/src/net/torvald/terrarum/AmmoMeterProxy.kt b/src/net/torvald/terrarum/AmmoMeterProxy.kt index 82e43dd3c..2df044fc2 100644 --- a/src/net/torvald/terrarum/AmmoMeterProxy.kt +++ b/src/net/torvald/terrarum/AmmoMeterProxy.kt @@ -19,14 +19,14 @@ object AmmoMeterProxy { } else { meter.vitalGetterVal = { - if (ItemCodex[currentItem.originalID].consumable) + if (ItemCodex[currentItem.originalID].stackable) actor.inventory.getByDynamicID(currentItem.dynamicID)!!.amount.toFloat() else currentItem.durability } meter.vitalGetterMax = { - if (ItemCodex[currentItem.originalID].consumable) + if (ItemCodex[currentItem.originalID].stackable) 500f else currentItem.maxDurability.toFloat() diff --git a/src/net/torvald/terrarum/StateInGame.kt b/src/net/torvald/terrarum/StateInGame.kt index 55bd6f0b4..81db699e9 100644 --- a/src/net/torvald/terrarum/StateInGame.kt +++ b/src/net/torvald/terrarum/StateInGame.kt @@ -73,7 +73,7 @@ class StateInGame : BasicGameState() { get() = playableActorDelegate?.actor var screenZoom = 1.0f - val ZOOM_MAX = 2.0f + val ZOOM_MAX = 4.0f val ZOOM_MIN = 0.5f val worldDrawFrameBuffer = Image(Terrarum.WIDTH.div(ZOOM_MIN).ceilInt(), Terrarum.HEIGHT.div(ZOOM_MIN).ceilInt()) @@ -317,9 +317,6 @@ class StateInGame : BasicGameState() { ///////////////////////// // app-related updates // ///////////////////////// - if (!Terrarum.isWin81) { - Terrarum.appgc.setVSync(Terrarum.appgc.fps >= Terrarum.VSYNC_TRIGGER_THRESHOLD) // windows 10 has some trouble with this... - } // determine if lightmap blending should be done Terrarum.setConfig("smoothlighting", KeyToggler.isOn(KEY_LIGHTMAP_SMOOTH)) diff --git a/src/net/torvald/terrarum/StateUITest.kt b/src/net/torvald/terrarum/StateUITest.kt index 153cb0bdd..b2ea10226 100644 --- a/src/net/torvald/terrarum/StateUITest.kt +++ b/src/net/torvald/terrarum/StateUITest.kt @@ -56,7 +56,7 @@ class StateUITest : BasicGameState() { override var inventoryCategory: String = InventoryItem.Category.TOOL override var maxDurability: Int = 143 override var durability: Float = 64f - override var consumable = false + override var stackable = false override val isDynamic = true }) actor.inventory.getByDynamicID(5656)!!.item.name = "Test tool" @@ -72,7 +72,7 @@ class StateUITest : BasicGameState() { override var baseMass: Double = 1.4 override var baseToolSize: Double? = null override var inventoryCategory: String = InventoryItem.Category.MISC - override var consumable = false + override var stackable = false override val isDynamic = false }) diff --git a/src/net/torvald/terrarum/UIItemInventoryElem.kt b/src/net/torvald/terrarum/UIItemInventoryElem.kt index cd79221ee..c7e7644a1 100644 --- a/src/net/torvald/terrarum/UIItemInventoryElem.kt +++ b/src/net/torvald/terrarum/UIItemInventoryElem.kt @@ -93,7 +93,7 @@ class UIItemInventoryElem( // this one-liner sets color g.color = item!!.nameColour mul if (mouseUp) mouseOverTextCol else inactiveTextCol g.drawString( - "$item" + (if (amount > 0 && !item!!.isUnique) "$fwsp($amount)" else "") + + "$item" + (if (amount > 0 && item!!.stackable) "$fwsp($amount)" else if (amount != 1) "$fwsp!!$amount!!" else "") + //item!!.name + (if (amount > 0 && !item!!.isUnique) "$fwsp($amount)" else "") + (if (equippedSlot != null) " ${0xE081.toChar()}\$$equippedSlot" else ""), posX + textOffsetX, diff --git a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt index 2b065f86e..a084213d4 100644 --- a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt +++ b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt @@ -145,7 +145,7 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) override var baseToolSize: Double? = null override var inventoryCategory = "should_not_be_seen" override val originalName: String = actorValue.getAsString(AVKey.NAME) ?: "(no name)" - override var consumable = false + override var stackable = false override val isDynamic = false } diff --git a/src/net/torvald/terrarum/gameactors/ActorInventory.kt b/src/net/torvald/terrarum/gameactors/ActorInventory.kt index ee8e95729..f40e8c7d8 100644 --- a/src/net/torvald/terrarum/gameactors/ActorInventory.kt +++ b/src/net/torvald/terrarum/gameactors/ActorInventory.kt @@ -3,6 +3,7 @@ package net.torvald.terrarum.gameactors import net.torvald.terrarum.Terrarum import net.torvald.terrarum.itemproperties.InventoryItem import net.torvald.terrarum.itemproperties.ItemCodex +import net.torvald.terrarum.itemproperties.ItemCodex.ITEM_DYNAMIC import net.torvald.terrarum.ui.UIInventory import java.util.* import java.util.concurrent.locks.Lock @@ -36,11 +37,21 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode fun add(itemID: Int, count: Int = 1) = add(ItemCodex[itemID], count) fun add(item: InventoryItem, count: Int = 1) { - if (item.dynamicID == Player.PLAYER_REF_ID || item.dynamicID == 0x51621D) // do not delete this magic + println("[ActorInventory] add $item, $count") + + + if (count == 0) + throw IllegalArgumentException("Item count is zero.") + if (count < 0) + throw IllegalArgumentException("Item count is negative number. If you intended removing items, use remove()" + + "These commands are NOT INTERCHANGEABLE; they handle things differently according to the context.") + if (item.originalID == Player.PLAYER_REF_ID || item.originalID == 0x51621D) // do not delete this magic throw IllegalArgumentException("Attempted to put human player into the inventory.") if (Terrarum.ingame != null && - (item.dynamicID == Terrarum.ingame?.player?.referenceID)) + (item.originalID == Terrarum.ingame?.player?.referenceID)) throw IllegalArgumentException("Attempted to put active player into the inventory.") + if ((!item.stackable || item.dynamicID in ITEM_DYNAMIC) && count > 1) + throw IllegalArgumentException("Attempting to adding stack of item but the item is not stackable; item: $item, count: $count") @@ -56,16 +67,16 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode } // new item else { - if (item.isDynamic) { + /*if (item.isDynamic) { // assign new ID for each repeat(count) { val newItem = item.clone().generateUniqueDynamicID(this) itemList.add(InventoryPair(newItem, 1)) } } - else { + else {*/ itemList.add(InventoryPair(item, count)) - } + //} } insertionSortLastElem(itemList) } @@ -74,6 +85,17 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode /** Will check existence of the item using its Dynamic ID; careful with command order! * e.g. re-assign after this operation */ fun remove(item: InventoryItem, count: Int = 1) { + + println("[ActorInventory] remove $item, $count") + + if (count == 0) + throw IllegalArgumentException("Item count is zero.") + if (count < 0) + throw IllegalArgumentException("Item count is negative number. If you intended adding items, use add()" + + "These commands are NOT INTERCHANGEABLE; they handle things differently according to the context.") + + + val existingItem = getByDynamicID(item.dynamicID) if (existingItem != null) { // if the item already exists val newCount = getByDynamicID(item.dynamicID)!!.amount - count @@ -82,7 +104,9 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode } else if (newCount > 0) { // decrement count - add(item, -count) + val newCount = getByDynamicID(item.dynamicID)!!.amount - count + itemList.remove(existingItem) + itemList.add(InventoryPair(existingItem.item, newCount)) } else { // unequip, if applicable @@ -139,16 +163,30 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode fun consumeItem(actor: Actor, item: InventoryItem) { - if (item.consumable) { + if (item.stackable && !item.isDynamic) { remove(item, 1) } else { + val newItem: InventoryItem + // unpack newly-made dynamic item (e.g. any weapon, floppy disk) - /*if (item.isDynamic && item.originalID == item.dynamicID) { - remove(item.originalID, 1) - item.generateUniqueDynamicID(this) - add(item) - }*/ + if (item.isDynamic && item.originalID == item.dynamicID) { + itemEquipped[item.equipPosition] = null + remove(item, 1) + + + newItem = item.clone() + newItem.generateUniqueDynamicID(this) + + newItem.stackable = false + add(newItem) + itemEquipped[newItem.equipPosition] = getByDynamicID(newItem.dynamicID)!!.item // will test if some sketchy code is written. Test fail: kotlinNullpointerException + + // FIXME now damage meter (vital) is broken + } + else { + newItem = item + } @@ -160,11 +198,11 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode val swingDmgToFrameDmg = Terrarum.delta.toDouble() / actor.actorValue.getAsDouble(AVKey.ACTION_INTERVAL)!! // damage the item - item.durability -= (baseDamagePerSwing * swingDmgToFrameDmg).toFloat() - if (item.durability <= 0) - remove(item, 1) + newItem.durability -= (baseDamagePerSwing * swingDmgToFrameDmg).toFloat() + if (newItem.durability <= 0) + remove(newItem, 1) - println("[ActorInventory] consumed; ${item.durability}") + //println("[ActorInventory] consumed; ${item.durability}") } } @@ -179,12 +217,22 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode if (itemList.size == 0) false else - itemList.binarySearch(id) >= 0 + itemList.binarySearch(id, DYNAMIC_ID) >= 0 fun getByDynamicID(id: Int): InventoryPair? { if (itemList.size == 0) return null - val index = itemList.binarySearch(id) + val index = itemList.binarySearch(id, DYNAMIC_ID) + if (index < 0) + return null + else + return itemList[index] + } + private fun getByStaticID(id: Int): InventoryPair? { + if (itemList.size == 0) + return null + + val index = itemList.binarySearch(id, STATIC_ID) if (index < 0) return null else @@ -201,7 +249,9 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode arr[j + 1] = x } } - private fun ArrayList.binarySearch(ID: Int): Int { + private val STATIC_ID = 41324534 + private val DYNAMIC_ID = 181643953 + private fun ArrayList.binarySearch(ID: Int, searchBy: Int): Int { // code from collections/Collections.kt var low = 0 var high = this.size - 1 @@ -209,7 +259,7 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode while (low <= high) { val mid = (low + high).ushr(1) // safe from overflows - val midVal = get(mid).item.dynamicID + val midVal = if (searchBy == STATIC_ID) this.get(mid).item.originalID else this.get(mid).item.dynamicID if (ID > midVal) low = mid + 1 diff --git a/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt b/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt index 5182f8790..73eacede9 100644 --- a/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt +++ b/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt @@ -57,7 +57,7 @@ open class HumanoidNPC( } override var inventoryCategory = "npc" override val originalName: String = actorValue.getAsString(AVKey.NAME) ?: "NPC" - override var consumable = true + override var stackable = true override val isDynamic = false override fun secondaryUse(gc: GameContainer, delta: Int): Boolean { diff --git a/src/net/torvald/terrarum/gameactors/Pocketed.kt b/src/net/torvald/terrarum/gameactors/Pocketed.kt index c25079f88..c033e9f09 100644 --- a/src/net/torvald/terrarum/gameactors/Pocketed.kt +++ b/src/net/torvald/terrarum/gameactors/Pocketed.kt @@ -32,13 +32,16 @@ interface Pocketed { * Equips an item. If the item is not in the inventory, adds the item first. */ fun equipItem(item: InventoryItem) { - if (!inventory.contains(item)) + if (!inventory.contains(item)) { + println("[Pocketed] Item does not exist; adding one before equipped") inventory.add(item) + } if (item.equipPosition >= 0) { inventory.itemEquipped[item.equipPosition] = item item.effectWhenEquipped(Terrarum.appgc, Terrarum.delta) } + // else do nothing } fun equipped(item: InventoryItem): Boolean { diff --git a/src/net/torvald/terrarum/itemproperties/InventoryItem.kt b/src/net/torvald/terrarum/itemproperties/InventoryItem.kt index 6254bc79f..4faa5c595 100644 --- a/src/net/torvald/terrarum/itemproperties/InventoryItem.kt +++ b/src/net/torvald/terrarum/itemproperties/InventoryItem.kt @@ -16,12 +16,15 @@ import org.newdawn.slick.GameContainer abstract class InventoryItem : Comparable, Cloneable { abstract var dynamicID: Int + /** + * if the ID is a Actor range, it's an actor contained in a pocket. + */ abstract val originalID: Int // WUT?! using init does not work!! /** * - * e.g. Key Items (in a Pokémon sense), floppies + * e.g. Key Items (in a Pokémon sense); only the single instance of the item can exist in the pocket */ abstract val isUnique: Boolean @@ -51,13 +54,15 @@ abstract class InventoryItem : Comparable, Cloneable { var itemProperties = ItemValue() - /** Single-use then destroyed (e.g. Tiles), aka negation of "stackable" */ - abstract var consumable: Boolean + /** Single-use then destroyed (e.g. Tiles), same as "consumable" */ + abstract var stackable: Boolean + /** * DYNAMIC means the item ID should be generated on the fly whenever the item is created. * This is to be used with weapons/armours/etc where multiple instances can exist, and - * each of them should be treated as different item. + * each of them should be treated as different item. Because of this, new + * derivative instances (dynamically created items, e.g. used pickaxe) are not stackable. * * ID Range: 32768..1048575 (ItemCodex.ITEM_DYNAMIC) * diff --git a/src/net/torvald/terrarum/itemproperties/ItemCodex.kt b/src/net/torvald/terrarum/itemproperties/ItemCodex.kt index 702990f0a..b0a819cc1 100644 --- a/src/net/torvald/terrarum/itemproperties/ItemCodex.kt +++ b/src/net/torvald/terrarum/itemproperties/ItemCodex.kt @@ -46,14 +46,14 @@ object ItemCodex { // tile items (blocks and walls are the same thing basically) for (i in ITEM_TILES + ITEM_WALLS) { itemCodex[i] = object : InventoryItem() { - override var dynamicID: Int = i - override val originalID = dynamicID + override val originalID = i + override var dynamicID = i override val isUnique: Boolean = false override var baseMass: Double = TileCodex[i].density / 1000.0 override var baseToolSize: Double? = null override var equipPosition = EquipPosition.HAND_GRIP override val originalName = TileCodex[i % ITEM_WALLS.first].nameKey - override var consumable = true + override var stackable = true override var inventoryCategory = Category.BLOCK override var isDynamic = false @@ -105,14 +105,14 @@ object ItemCodex { // test copper pickaxe itemCodex[ITEM_STATIC.first] = object : InventoryItem() { - override var dynamicID = ITEM_STATIC.first - override val originalID = dynamicID + override val originalID = ITEM_STATIC.first + override var dynamicID = originalID override val isUnique = false override val originalName = "" override var baseMass = 10.0 override var baseToolSize: Double? = 10.0 - override var consumable = false - override var maxDurability = 147//606 // this much tiles before breaking + override var stackable = true + override var maxDurability = 147//606 override var durability = maxDurability.toFloat() override var equipPosition = EquipPosition.HAND_GRIP override var inventoryCategory = Category.TOOL diff --git a/src/net/torvald/terrarum/langpack/Lang.kt b/src/net/torvald/terrarum/langpack/Lang.kt index 84dbe13b3..386ad3859 100644 --- a/src/net/torvald/terrarum/langpack/Lang.kt +++ b/src/net/torvald/terrarum/langpack/Lang.kt @@ -114,9 +114,9 @@ object Lang { // special treatment if (key.startsWith("MENU_LABEL_PRESS_START_SYMBOL")) - return ret2.replace('>', Terrarum.joypadLabelStart) + return ret2.replace('>', Terrarum.joypadLabelStart).capitalize() - return ret2 + return ret2.capitalize() } fun pluraliseLang(key: String, count: Int): String { diff --git a/src/net/torvald/terrarum/ui/UIInventory.kt b/src/net/torvald/terrarum/ui/UIInventory.kt index f373c3602..206bb80f8 100644 --- a/src/net/torvald/terrarum/ui/UIInventory.kt +++ b/src/net/torvald/terrarum/ui/UIInventory.kt @@ -63,8 +63,8 @@ class UIInventory( "MENU_LABEL_ALL", "GAME_INVENTORY_BLOCKS", "GAME_INVENTORY_WALLS", - "GAME_INVENTORY_WEAPONS", // weapons and tools "CONTEXT_ITEM_TOOL_PLURAL", + "GAME_INVENTORY_WEAPONS", "CONTEXT_ITEM_ARMOR", "GAME_INVENTORY_INGREDIENTS", "GAME_INVENTORY_POTIONS", @@ -79,7 +79,7 @@ class UIInventory( textAreaWidth = 100, defaultSelection = 0, iconSpriteSheet = SpriteSheet("./assets/graphics/gui/inventory/category.tga", 20, 20), - iconSpriteSheetIndices = intArrayOf(9,6,7,0,1,2,3,4,5,8), + iconSpriteSheetIndices = intArrayOf(9,6,7,1,0,2,3,4,5,8), iconCol = defaultTextColour, highlightBackCol = Color(0xb8b8b8), highlightBackBlendMode = BlendMode.MULTIPLY,