From e1642c799ca505af44685f4ab53fda19d93128b6 Mon Sep 17 00:00:00 2001 From: Song Minjae Date: Mon, 12 Dec 2016 23:29:13 +0900 Subject: [PATCH] WIP inventory implementation Former-commit-id: ce7d2125209c2c4f49b7d755b068ce72387f5e8f Former-commit-id: f413b2699ee7448f3d3b70775ca7b679ade66475 --- assets/graphics/sprites/test_player.png | Bin 18100 -> 18608 bytes .../torvald/terrarum/console/CodexEdictis.kt | 2 +- .../torvald/terrarum/console/CommandDict.kt | 1 + src/net/torvald/terrarum/console/Inventory.kt | 65 ++++++++++++++++++ .../terrarum/gameactors/ActorInventory.kt | 30 ++++---- .../terrarum/gameactors/HumanoidNPC.kt | 24 +------ .../gameactors/PlayerBuilderSigrid.kt | 10 ++- .../terrarum/gameitem/InventoryItem.kt | 15 ++-- .../terrarum/gameitem/InventoryItemAdapter.kt | 30 ++++++++ .../terrarum/itemproperties/ItemPropCodex.kt | 32 +++++++-- 10 files changed, 157 insertions(+), 52 deletions(-) create mode 100644 src/net/torvald/terrarum/console/Inventory.kt create mode 100644 src/net/torvald/terrarum/gameitem/InventoryItemAdapter.kt diff --git a/assets/graphics/sprites/test_player.png b/assets/graphics/sprites/test_player.png index d9a1c32de9b3d2f24dde387e9603e8393e6fe29b..5801ef5c1d0b36699f8070ddf30f446620a684b6 100644 GIT binary patch delta 3419 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 { + if (args.size == 1) { + printUsage() + } else { + when (args[1]) { + "list" -> listInventory() + "add" -> addItem(args[2].toInt(), args[3].toInt()) + "target" -> setTarget(args[2].toInt()) + "assign" -> assignQuickBar(args[2].toInt(), args[3].toInt()) + else -> printUsage() + } + } + } + + private fun listInventory() { + if (target.getTotalUniqueCount() == 0) { + Echo().execute("(inventory empty)") + } else { + target.forEach { refId, amount -> + if (amount == 0) { + Error().execute("Unexpected zero-amounted item: ID $refId") + } + Echo().execute("ID $refId${if (amount > 1) " ($amount)" else ""}") + } + } + } + + private fun setTarget(actorRefId: Int = Player.PLAYER_REF_ID) { + val actor = Terrarum.ingame.getActorByID(actorRefId) + if (actor !is Pocketed) { + Error().execute("Cannot edit inventory of incompatible actor: $actor") + } else { + target = actor.inventory + } + } + + private fun addItem(refId: Int, amount: Int = 1) { + target.add(ItemPropCodex.getProp(refId), amount) + } + + private fun assignQuickBar(refId: Int, index: Int) { + + } + + override fun printUsage() { + Echo().execute("Usage: inventory command arguments") + Echo().execute("Available commands:") + Echo().execute("list | assign slot | add itemid [amount] | target [actorid]") + } +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameactors/ActorInventory.kt b/src/net/torvald/terrarum/gameactors/ActorInventory.kt index 36b4a5ecc..67314b890 100644 --- a/src/net/torvald/terrarum/gameactors/ActorInventory.kt +++ b/src/net/torvald/terrarum/gameactors/ActorInventory.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum.gameactors +import net.torvald.terrarum.Terrarum import net.torvald.terrarum.gameitem.InventoryItem import net.torvald.terrarum.itemproperties.ItemPropCodex import java.util.* @@ -21,7 +22,7 @@ class ActorInventory() { private var capacityMode: Int /** - * HashMap<ReferenceID, Amounts> + * HashMap */ private val itemList: HashMap = HashMap() @@ -78,6 +79,8 @@ class ActorInventory() { return itemList } + fun forEach(consumer: (Int, Int) -> Unit) = itemList.forEach(consumer) + /** * Get clone of the itemList * @return @@ -97,6 +100,9 @@ class ActorInventory() { return weight } + /** + * Real amount + */ fun getTotalCount(): Int { var count = 0 @@ -107,26 +113,26 @@ class ActorInventory() { return count } + /** + * Unique amount, multiple items are calculated as one + */ fun getTotalUniqueCount(): Int { return itemList.entries.size } - fun appendToPocket(item: InventoryItem) { - appendToPocket(item, 1) + fun add(item: InventoryItem) { + add(item, 1) } - fun appendToPocket(item: InventoryItem, count: Int) { + fun add(item: InventoryItem, count: Int) { val key = item.itemID - // if (key == Player.PLAYER_REF_ID) - // throw new IllegalArgumentException("Attempted to put player into the inventory."); + if (key == Player.PLAYER_REF_ID || key == Terrarum.ingame.player.referenceID) + throw IllegalArgumentException("Attempted to put active player or human player into the inventory.") - if (itemList.containsKey(key)) - // increment amount if it already has specified item - itemList.put(key, itemList[key]!! + count) - else - // add new entry if it does not have specified item - itemList.put(key, count) + // If we already have the item, increment the amount + // If not, add item with specified amount + itemList.put(key, itemList[key] ?: 0 + count) } /** diff --git a/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt b/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt index 85176ca08..10e2b74fd 100644 --- a/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt +++ b/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt @@ -2,6 +2,7 @@ package net.torvald.terrarum.gameactors import net.torvald.terrarum.gameactors.ActorHumanoid import net.torvald.terrarum.gameitem.InventoryItem +import net.torvald.terrarum.gameitem.InventoryItemAdapter import org.luaj.vm2.Globals import org.luaj.vm2.LoadState import org.luaj.vm2.LuaError @@ -39,7 +40,7 @@ open class HumanoidNPC(aiFile: String, born: GameDate) : ActorHumanoid(born), AI } // we're having InventoryItem data so that this class could be somewhat universal - override var itemData: InventoryItem = object : InventoryItem { + override var itemData: InventoryItem = object : InventoryItemAdapter() { override var itemID = referenceID override var mass: Double @@ -54,30 +55,9 @@ open class HumanoidNPC(aiFile: String, born: GameDate) : ActorHumanoid(born), AI actorValue[AVKey.SCALE] = value } - override fun effectWhileInPocket(gc: GameContainer, delta: Int) { - - } - - override fun effectWhenPickedUp(gc: GameContainer, delta: Int) { - - } - - override fun primaryUse(gc: GameContainer, delta: Int) { - // TODO do not allow primary_use - } - override fun secondaryUse(gc: GameContainer, delta: Int) { // TODO place this Actor to the world } - - override fun effectWhenThrown(gc: GameContainer, delta: Int) { - } - - override fun effectWhenTakenOut(gc: GameContainer, delta: Int) { - } - - override fun worldActorEffect(gc: GameContainer, delta: Int) { - } } override fun getItemWeight(): Double { diff --git a/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt b/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt index cd23376fe..f9f55d0c1 100644 --- a/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt +++ b/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt @@ -55,7 +55,7 @@ object PlayerBuilderSigrid { p.actorValue[AVKey.INTELLIGENT] = true - p.actorValue[AVKey.LUMINOSITY] = 0//95487100 + p.actorValue[AVKey.LUMINOSITY] = 95487100 p.actorValue[AVKey.BASEDEFENCE] = 141 @@ -71,6 +71,14 @@ object PlayerBuilderSigrid { p.faction.add(FactionFactory.create("FactionSigrid.json")) + + + // Test fill up inventory + + + + + return p } } diff --git a/src/net/torvald/terrarum/gameitem/InventoryItem.kt b/src/net/torvald/terrarum/gameitem/InventoryItem.kt index 8298ce675..832bee707 100644 --- a/src/net/torvald/terrarum/gameitem/InventoryItem.kt +++ b/src/net/torvald/terrarum/gameitem/InventoryItem.kt @@ -8,20 +8,21 @@ import org.newdawn.slick.GameContainer interface InventoryItem { /** * Internal ID of an Item, Long - * 0-4096: Tiles - * 4097-32767: Static items + * 0-4095: Tiles + * 4096-32767: Static items * 32768-16777215: Dynamic items * >= 16777216: Actor RefID */ val itemID: Int /** - * Weight of the item + * Base mass of the item. Real mass must be calculated from + * mass * scale^3 */ var mass: Double /** - * Scale of the item. Real mass: mass * (scale^3) + * Scale of the item. * * For static item, it must be 1.0. If you tinkered the item to be bigger, * it must be re-assigned as Dynamic Item @@ -57,10 +58,4 @@ interface InventoryItem { * Effects applied (continuously or not) while thrown to the world */ fun effectWhenTakenOut(gc: GameContainer, delta: Int) - - /** - * Effects applied (continuously or not) while thrown to the world, - * called by the proxy Actor - */ - fun worldActorEffect(gc: GameContainer, delta: Int) } \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameitem/InventoryItemAdapter.kt b/src/net/torvald/terrarum/gameitem/InventoryItemAdapter.kt new file mode 100644 index 000000000..57bddbeec --- /dev/null +++ b/src/net/torvald/terrarum/gameitem/InventoryItemAdapter.kt @@ -0,0 +1,30 @@ +package net.torvald.terrarum.gameitem + +import org.newdawn.slick.GameContainer + +/** + * Created by SKYHi14 on 2016-12-12. + */ +abstract class InventoryItemAdapter : InventoryItem { + override abstract val itemID: Int + override abstract var mass: Double + override abstract var scale: Double + + override fun effectWhileInPocket(gc: GameContainer, delta: Int) { + } + + override fun effectWhenPickedUp(gc: GameContainer, delta: Int) { + } + + override fun primaryUse(gc: GameContainer, delta: Int) { + } + + override fun secondaryUse(gc: GameContainer, delta: Int) { + } + + override fun effectWhenThrown(gc: GameContainer, delta: Int) { + } + + override fun effectWhenTakenOut(gc: GameContainer, delta: Int) { + } +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/itemproperties/ItemPropCodex.kt b/src/net/torvald/terrarum/itemproperties/ItemPropCodex.kt index 29ebdc377..2595bdd6d 100644 --- a/src/net/torvald/terrarum/itemproperties/ItemPropCodex.kt +++ b/src/net/torvald/terrarum/itemproperties/ItemPropCodex.kt @@ -5,7 +5,11 @@ import net.torvald.terrarum.KVHashMap import net.torvald.terrarum.gameactors.CanBeAnItem import net.torvald.terrarum.gameitem.InventoryItem import net.torvald.terrarum.Terrarum +import net.torvald.terrarum.gameitem.InventoryItemAdapter import net.torvald.terrarum.gameworld.GameWorld +import net.torvald.terrarum.tileproperties.TileProp +import net.torvald.terrarum.tileproperties.TilePropCodex +import org.apache.commons.csv.CSVRecord import org.newdawn.slick.GameContainer import java.util.* @@ -14,23 +18,39 @@ import java.util.* */ object ItemPropCodex { - val CSV_PATH = "./src/com/torvald/terrarum/itemproperties/itemprop.csv" - /** * * Will return corresponding Actor if ID >= 16777216 */ - private val itemCodex = ArrayList() + private val itemCodex = HashMap() private val dynamicItemDescription = HashMap() - val ITEM_TILE_MAX = GameWorld.TILES_SUPPORTED + val ITEM_TILE_MAX = GameWorld.TILES_SUPPORTED - 1 // 4095 val ITEM_COUNT_MAX = 16777216 val ITEM_DYNAMIC_MAX = ITEM_COUNT_MAX - 1 val ITEM_STATIC_MAX = 32767 val ITEM_DYNAMIC_MIN = ITEM_STATIC_MAX + 1 - val ITEM_STATIC_MIN = ITEM_TILE_MAX + val ITEM_STATIC_MIN = ITEM_TILE_MAX + 1 // 4096 init { + // tile items + for (i in 0..ITEM_TILE_MAX) { + itemCodex[i] = object : InventoryItemAdapter() { + override val itemID: Int = i + override var mass: Double = TilePropCodex.getProp(i).density / 1000.0 + // no need to set setter as scale would not change + override var scale: Double = 1.0 + + override fun primaryUse(gc: GameContainer, delta: Int) { + // TODO base punch attack + } + + override fun secondaryUse(gc: GameContainer, delta: Int) { + // TODO place block to the world + } + } + } + // read prop in csv and fill itemCodex // read from save (if applicable) and fill dynamicItemDescription @@ -38,7 +58,7 @@ object ItemPropCodex { fun getProp(code: Int): InventoryItem { if (code < ITEM_STATIC_MAX) // generic item - return itemCodex[code] // from CSV + return itemCodex[code]!! // from CSV else if (code < ITEM_DYNAMIC_MAX) { TODO("read from dynamicitem description (JSON)") }