mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
working proof-of-concept inventory system
Former-commit-id: 1be5d6d10d0a5c93bceaf12f15d2ee50602cb602 Former-commit-id: 44f25a27c3b5d196210f4efcc3fef4dec8e30ff7
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user