working proof-of-concept inventory system

Former-commit-id: 1be5d6d10d0a5c93bceaf12f15d2ee50602cb602
Former-commit-id: 44f25a27c3b5d196210f4efcc3fef4dec8e30ff7
This commit is contained in:
Song Minjae
2016-12-14 15:41:20 +09:00
parent 7078ecfed4
commit 1d1769a2c3
7 changed files with 153 additions and 80 deletions

View File

@@ -60,9 +60,9 @@ constructor() : BasicGameState() {
lateinit var debugWindow: UIHandler
lateinit var notifier: UIHandler
lateinit internal var playableActorDelegate: PlayableActorDelegate
internal var playableActorDelegate: PlayableActorDelegate? = null
internal val player: ActorHumanoid // currently POSSESSED actor :)
get() = playableActorDelegate.actor
get() = playableActorDelegate!!.actor
//private var GRADIENT_IMAGE: Image? = null
//private var skyBox: Rectangle? = null

View File

@@ -11,27 +11,29 @@ import net.torvald.terrarum.itemproperties.ItemPropCodex
*/
internal object Inventory : ConsoleCommand {
private var target: ActorInventory = Terrarum.ingame.player.inventory
private var target: Pocketed = Terrarum.ingame.player
override fun execute(args: Array<String>) {
if (args.size == 1) {
printUsage()
} else {
}
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())
"hold" -> holdItem(args[2].toInt())
else -> printUsage()
}
}
}
private fun listInventory() {
if (target.getTotalUniqueCount() == 0) {
if (target.inventory.getTotalUniqueCount() == 0) {
Echo("(inventory empty)")
} else {
target.forEach { refId, amount ->
}
else {
target.inventory.forEach { refId, amount ->
if (amount == 0) {
EchoError("Unexpected zero-amounted item: ID $refId")
}
@@ -44,22 +46,29 @@ internal object Inventory : ConsoleCommand {
val actor = Terrarum.ingame.getActorByID(actorRefId)
if (actor !is Pocketed) {
EchoError("Cannot edit inventory of incompatible actor: $actor")
} else {
target = actor.inventory
}
else {
target = actor
}
}
private fun addItem(refId: Int, amount: Int = 1) {
target.add(ItemPropCodex.getProp(refId), amount)
target.inventory.add(ItemPropCodex.getProp(refId), amount)
}
private fun assignQuickBar(refId: Int, index: Int) {
private fun holdItem(refId: Int) {
// if the item does not exist, add it first
if (!target.inventory.contains(refId)) {
target.inventory.add(refId)
}
target.itemHolding = ItemPropCodex.getProp(refId)
}
override fun printUsage() {
Echo("Usage: inventory command arguments")
Echo("Available commands:")
Echo("list | assign slot | add itemid [amount] | target [actorid]")
Echo("list | assign slot | add itemid [amount] | target [actorid] | hold itemid")
Echo("equip itemid")
}
}

View File

@@ -7,6 +7,7 @@ import net.torvald.terrarum.gameactors.faction.Faction
import net.torvald.terrarum.gamecontroller.EnumKeyFunc
import net.torvald.terrarum.gamecontroller.KeyMap
import net.torvald.terrarum.gameitem.InventoryItem
import net.torvald.terrarum.gameitem.InventoryItemAdapter
import net.torvald.terrarum.realestate.RealEstateUtility
import org.dyn4j.geometry.Vector2
import org.lwjgl.input.Controller
@@ -26,11 +27,8 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null)
/** Must be set by PlayerFactory */
override var inventory: ActorInventory = ActorInventory()
override var itemHolding: InventoryItem
get() = throw TODO("itemHolding")
set(value) {
throw TODO("itemHolding")
}
override var itemHolding: InventoryItem? = null
override val itemEquipped = ArrayList<InventoryItem>()
/** Must be set by PlayerFactory */
override var faction: HashSet<Faction> = HashSet()
@@ -136,6 +134,13 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null)
get() = this is Player // FIXME true iff composed by PlayableActorDelegate
private val nullItem = object : InventoryItemAdapter() {
override val itemID: Int = 0
override var mass: Double = 0.0
override var scale: Double = 1.0
}
override fun update(gc: GameContainer, delta: Int) {
super.update(gc, delta)
@@ -206,12 +211,12 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null)
*/
// Left mouse
if (isGamer && input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON)) {
itemHolding.primaryUse(gc, delta)
(itemHolding ?: nullItem).primaryUse(gc, delta)
}
// Right mouse
if (isGamer && input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON)) {
itemHolding.secondaryUse(gc, delta)
(itemHolding ?: nullItem).secondaryUse(gc, delta)
}
/**

View File

@@ -51,6 +51,43 @@ class ActorInventory() {
}
}
fun add(item: InventoryItem, count: Int = 1) = add(item.itemID, count)
fun add(itemID: Int, count: Int = 1) {
if (itemID == Player.PLAYER_REF_ID)
throw IllegalArgumentException("Attempted to put human player into the inventory.")
if (Terrarum.ingame.playableActorDelegate != null &&
itemID == Terrarum.ingame.player.referenceID)
throw IllegalArgumentException("Attempted to put active player into the inventory.")
// If we already have the item, increment the amount
// If not, add item with specified amount
itemList.put(itemID, itemList[itemID] ?: 0 + count)
}
fun remove(item: InventoryItem, count: Int = 1) = remove(item.itemID, count)
fun remove(itemID: Int, count: Int = 1) {
// check if the item does NOT exist
if (itemList[itemID] == null) {
return
}
else {
// remove the existence of the item if count <= 0
if (itemList[itemID]!! - count <= 0) {
itemList.remove(itemID)
}
// else, decrement the item count
else {
itemList.put(itemID, itemList[itemID]!! - count)
}
}
}
fun contains(item: InventoryItem) = itemList.containsKey(item.itemID)
fun contains(itemID: Int) = itemList.containsKey(itemID)
fun forEach(consumer: (Int, Int) -> Unit) = itemList.forEach(consumer)
/**
* Get capacity of inventory
* @return
@@ -79,8 +116,6 @@ class ActorInventory() {
return itemList
}
fun forEach(consumer: (Int, Int) -> Unit) = itemList.forEach(consumer)
/**
* Get clone of the itemList
* @return
@@ -120,21 +155,6 @@ class ActorInventory() {
return itemList.entries.size
}
fun add(item: InventoryItem) {
add(item, 1)
}
fun add(item: InventoryItem, count: Int) {
val key = item.itemID
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 we already have the item, increment the amount
// If not, add item with specified amount
itemList.put(key, itemList[key] ?: 0 + count)
}
/**
* Check whether the itemList contains too many items
* @return

View File

@@ -53,10 +53,14 @@ open class ActorWithBody : Actor() {
internal val velocity = Vector2(0.0, 0.0)
var veloX: Double
get() = velocity.x
protected set(value) { velocity.x = value }
protected set(value) {
velocity.x = value
}
var veloY: Double
get() = velocity.y
protected set(value) { velocity.y = value }
protected set(value) {
velocity.y = value
}
val moveDelta = Vector2(0.0, 0.0)
@Transient private val VELO_HARD_LIMIT = 100.0
@@ -67,10 +71,14 @@ open class ActorWithBody : Actor() {
var controllerVel: Vector2? = if (this is Controllable) Vector2() else null
var walkX: Double
get() = controllerVel!!.x
protected set(value) { controllerVel!!.x = value }
protected set(value) {
controllerVel!!.x = value
}
var walkY: Double
get() = controllerVel!!.y
protected set(value) { controllerVel!!.y = value }
protected set(value) {
controllerVel!!.y = value
}
/**
* Physical properties.
@@ -114,7 +122,9 @@ open class ActorWithBody : Actor() {
* Formula: restitution = 1.0 - elasticity
*/
var restitution: Double
set(value) { elasticity = 1.0 - value }
set(value) {
elasticity = 1.0 - value
}
get() = 1.0 - elasticity
@Transient private val CEILING_HIT_ELASTICITY = 0.3
@@ -363,7 +373,7 @@ open class ActorWithBody : Actor() {
}
// cheap solution for sticking into the wall while Left or Right is held
walledLeft = isTouchingSide(nextHitbox, COLLIDING_LEFT)
walledLeft = isTouchingSide(nextHitbox, COLLIDING_LEFT)
walledRight = isTouchingSide(nextHitbox, COLLIDING_RIGHT)
if (isPlayerNoClip) {
walledLeft = false
@@ -462,7 +472,7 @@ open class ActorWithBody : Actor() {
}
// axis X
if (isTouchingSide(nextHitbox, COLLIDING_LEFT) || isTouchingSide(nextHitbox, COLLIDING_RIGHT)
&& moveDelta.x != 0.0) { // check right and left
&& moveDelta.x != 0.0) { // check right and left
// the actor is hitting the wall
hitAndReflectX()
}
@@ -475,7 +485,7 @@ open class ActorWithBody : Actor() {
private fun displaceByCCD() {
ccdCollided = false
if (!isNoCollideWorld){
if (!isNoCollideWorld) {
if (!isColliding(nextHitbox, COLLIDING_ALLSIDE))
return
@@ -534,7 +544,10 @@ open class ActorWithBody : Actor() {
if (isNoCollideWorld) return false
// offsets will stretch and shrink detection box according to the argument
val x1: Double; val x2: Double; val y1: Double; val y2: Double
val x1: Double;
val x2: Double;
val y1: Double;
val y2: Double
if (option == COLLIDING_LR || option == COLLIDING_UD) {
val offsetX = if (option == COLLIDING_LR) A_PIXEL else 0.0
val offsetY = if (option == COLLIDING_UD) A_PIXEL else 0.0
@@ -578,15 +591,18 @@ open class ActorWithBody : Actor() {
}
val txStart = x1.div(TSIZE).floorInt()
val txEnd = x2.div(TSIZE).floorInt()
val txEnd = x2.div(TSIZE).floorInt()
val tyStart = y1.div(TSIZE).floorInt()
val tyEnd = y2.div(TSIZE).floorInt()
val tyEnd = y2.div(TSIZE).floorInt()
return isCollidingInternal(txStart, tyStart, txEnd, tyEnd)
}
private fun isTouchingSide(hitbox: Hitbox, option: Int): Boolean {
val x1: Double; val x2: Double; val y1: Double; val y2: Double
val x1: Double;
val x2: Double;
val y1: Double;
val y2: Double
if (option == COLLIDING_TOP) {
x1 = hitbox.posX
x2 = hitbox.endPointX
@@ -614,16 +630,19 @@ open class ActorWithBody : Actor() {
else throw IllegalArgumentException()
val txStart = x1.div(TSIZE).floorInt()
val txEnd = x2.div(TSIZE).floorInt()
val txEnd = x2.div(TSIZE).floorInt()
val tyStart = y1.div(TSIZE).floorInt()
val tyEnd = y2.div(TSIZE).floorInt()
val tyEnd = y2.div(TSIZE).floorInt()
return isCollidingInternal(txStart, tyStart, txEnd, tyEnd)
}
private fun isCollidingSide(hitbox: Hitbox, option: Int): Boolean {
val x1: Double; val x2: Double; val y1: Double; val y2: Double
val x1: Double;
val x2: Double;
val y1: Double;
val y2: Double
if (option == COLLIDING_TOP) {
x1 = hitbox.posX
x2 = hitbox.endPointX
@@ -804,8 +823,8 @@ open class ActorWithBody : Actor() {
if (!isWalkingH)
Hitbox(nextHitbox.posX, nextHitbox.posY,
nextHitbox.width + 2.0, nextHitbox.height + 2.0)
// when not walking, enlarge the hitbox for calculation so that
// feet tiles are also counted
// when not walking, enlarge the hitbox for calculation so that
// feet tiles are also counted
else
nextHitbox.clone()
@@ -823,6 +842,7 @@ open class ActorWithBody : Actor() {
return friction
}
fun Int.tileFrictionToMult(): Double = this / 16.0
/**
@@ -908,7 +928,8 @@ open class ActorWithBody : Actor() {
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(scale).toFloat()
)
} else {
}
else {
spriteGlow!!.render(g,
(hitbox.posX - scale).toFloat(),
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
@@ -921,9 +942,9 @@ open class ActorWithBody : Actor() {
open fun drawBody(gc: GameContainer, g: Graphics) {
if (isVisible && sprite != null) {
when (drawMode) {
DrawMode.NORMAL -> blendNormal()
DrawMode.NORMAL -> blendNormal()
DrawMode.MULTIPLY -> blendMul()
DrawMode.SCREEN -> blendScreen()
DrawMode.SCREEN -> blendScreen()
}
if (!sprite!!.flippedHorizontal()) {
@@ -932,7 +953,8 @@ open class ActorWithBody : Actor() {
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
(scale).toFloat()
)
} else {
}
else {
sprite!!.render(g,
(hitbox.posX - scale).toFloat(),
(hitbox.posY + hitboxTranslateY * scale - (baseSpriteHeight - baseHitboxH) * scale + 2).toFloat(),
@@ -951,22 +973,26 @@ open class ActorWithBody : Actor() {
}
private fun clampW(x: Double): Double =
if (x < TSIZE + nextHitbox.width / 2) {
TSIZE + nextHitbox.width / 2
} else if (x >= (world.width * TSIZE).toDouble() - TSIZE.toDouble() - nextHitbox.width / 2) {
(world.width * TSIZE).toDouble() - 1.0 - TSIZE.toDouble() - nextHitbox.width / 2
} else {
x
}
if (x < TSIZE + nextHitbox.width / 2) {
TSIZE + nextHitbox.width / 2
}
else if (x >= (world.width * TSIZE).toDouble() - TSIZE.toDouble() - nextHitbox.width / 2) {
(world.width * TSIZE).toDouble() - 1.0 - TSIZE.toDouble() - nextHitbox.width / 2
}
else {
x
}
private fun clampH(y: Double): Double =
if (y < TSIZE + nextHitbox.height) {
TSIZE + nextHitbox.height
} else if (y >= (world.height * TSIZE).toDouble() - TSIZE.toDouble() - nextHitbox.height) {
(world.height * TSIZE).toDouble() - 1.0 - TSIZE.toDouble() - nextHitbox.height
} else {
y
}
if (y < TSIZE + nextHitbox.height) {
TSIZE + nextHitbox.height
}
else if (y >= (world.height * TSIZE).toDouble() - TSIZE.toDouble() - nextHitbox.height) {
(world.height * TSIZE).toDouble() - 1.0 - TSIZE.toDouble() - nextHitbox.height
}
else {
y
}
private fun clampWtile(x: Int): Int =
if (x < 0) 0 else if (x >= world.width) world.width - 1 else x
@@ -995,7 +1021,9 @@ open class ActorWithBody : Actor() {
assertPrinted = true
}
internal fun flagDespawn() { flagDespawn = true }
internal fun flagDespawn() {
flagDespawn = true
}
companion object {
@@ -1037,23 +1065,25 @@ fun Double.sqr() = this * this
fun Double.sqrt() = Math.sqrt(this)
fun Int.abs() = if (this < 0) -this else this
fun Double.bipolarClamp(limit: Double) =
if (this > 0 && this > limit) limit
if (this > 0 && this > limit) limit
else if (this < 0 && this < -limit) -limit
else this
fun absMax(left: Double, right: Double): Double {
if (left > 0 && right > 0)
if (left > right) return left
else return right
else return right
else if (left < 0 && right < 0)
if (left < right) return left
else return right
else return right
else {
val absL = left.abs()
val absR = right.abs()
if (absL > absR) return left
else return right
else return right
}
}
fun Double.magnSqr() = if (this >= 0.0) this.sqr() else -this.sqr()
fun Double.sign() = if (this > 0.0) 1.0 else if (this < 0.0) -1.0 else 0.0

View File

@@ -6,6 +6,7 @@ import net.torvald.spriteanimation.SpriteAnimation
import com.google.gson.JsonObject
import net.torvald.terrarum.gameactors.ActorHumanoid
import net.torvald.terrarum.gameactors.faction.FactionFactory
import net.torvald.terrarum.itemproperties.ItemPropCodex
import net.torvald.terrarum.mapdrawer.MapDrawer
import org.newdawn.slick.SlickException
import java.io.IOException
@@ -74,7 +75,8 @@ object PlayerBuilderSigrid {
// Test fill up inventory
p.inventory.add(16)
p.itemHolding = ItemPropCodex.getProp(16)

View File

@@ -1,6 +1,7 @@
package net.torvald.terrarum.gameactors
import net.torvald.terrarum.gameitem.InventoryItem
import java.util.*
/**
* Created by minjaesong on 16-01-15.
@@ -9,7 +10,13 @@ interface Pocketed {
var inventory: ActorInventory
/** Item currentry holding, like tools/weapons/scrolls/magic/etc. */
var itemHolding: InventoryItem
/** Item currentry holding, like tools/weapons/scrolls/magic/etc.
* Null if not holding anything
*/
var itemHolding: InventoryItem?
/**
* List of all equipped items (tools, armours, rings, necklaces, etc.)
*/
val itemEquipped: ArrayList<InventoryItem>
}