mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
new ID for dynamic item work flawlessly with adding multiple at once
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
|4096..8191|Walls|
|
||||
|8192..8447|Wires|
|
||||
|8448..32767|Items (static)|
|
||||
|32768..1048575|Items (dynamic\*)|
|
||||
|1048576..0x7FFF_FFFF|Actors|
|
||||
|0x8000_0000..0xFFFF_FFFF (all negative numbers)|Faction|
|
||||
|32768..0x0FFF_FFFF|Items (dynamic\*)|
|
||||
|0x1000_0000..0x7FFF_FFFF|Actors|
|
||||
|-2147483648..-1 (all negative numbers)|Faction|
|
||||
|
||||
* dynamic items can have their own properties that will persist through savegame.
|
||||
|
||||
@@ -14,7 +14,7 @@ Actors range in-depth
|
||||
|
||||
|Range|Description|
|
||||
|-----|-----------|
|
||||
|1048576..0x0FFF_FFFF|Rendered behind (e.g. tapestries)
|
||||
|0x1000_0000..0x5FFF_FFFF|Regular actors (e.g. almost all of them)
|
||||
|0x1000_0000..0x1FFF_FFFF|Rendered behind (e.g. tapestries)
|
||||
|0x2000_0000..0x5FFF_FFFF|Regular actors (e.g. almost all of them)
|
||||
|0x6000_0000..0x6FFF_FFFF|Special (e.g. weapon swung, bullets, dropped item, particles)
|
||||
|0x7000_0000..0x7FFF_FFFF|Rendered front (e.g. fake tile)
|
||||
@@ -20,16 +20,16 @@ object AmmoMeterProxy {
|
||||
else {
|
||||
meter.vitalGetterVal = {
|
||||
if (ItemCodex[currentItem.originalID].consumable)
|
||||
actor.inventory.getByDynamicID(currentItem.dynamicID)!!.amount.toFloat()
|
||||
else
|
||||
actor.inventory.getByDynamicID(currentItem.dynamicID)!!.item.durability
|
||||
actor.inventory.getByDynamicID(currentItem.dynamicID)!!.amount.toFloat()
|
||||
else
|
||||
currentItem.durability
|
||||
}
|
||||
|
||||
meter.vitalGetterMax = {
|
||||
if (ItemCodex[currentItem.originalID].consumable)
|
||||
500f
|
||||
else
|
||||
actor.inventory.getByDynamicID(currentItem.dynamicID)!!.item.maxDurability.toFloat()
|
||||
currentItem.maxDurability.toFloat()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ class UIItemInventoryElem(
|
||||
}
|
||||
}
|
||||
|
||||
private val fwsp = 0x3000.toChar()
|
||||
|
||||
override fun render(gc: GameContainer, g: Graphics) {
|
||||
g.font = Terrarum.fontGame
|
||||
|
||||
@@ -91,8 +93,8 @@ class UIItemInventoryElem(
|
||||
// this one-liner sets color
|
||||
g.color = item!!.nameColour mul if (mouseUp) mouseOverTextCol else inactiveTextCol
|
||||
g.drawString(
|
||||
"${item!!.dynamicID}/${item!!.originalID}" + (if (amount > 0 && !item!!.isUnique) "${0x3000.toChar()}($amount)" else "") +
|
||||
//item!!.name + (if (amount > 0 && !item!!.isUnique) "${0x3000.toChar()}($amount)" else "") +
|
||||
"$item" + (if (amount > 0 && !item!!.isUnique) "$fwsp($amount)" else "") +
|
||||
//item!!.name + (if (amount > 0 && !item!!.isUnique) "$fwsp($amount)" else "") +
|
||||
(if (equippedSlot != null) " ${0xE081.toChar()}\$$equippedSlot" else ""),
|
||||
posX + textOffsetX,
|
||||
posY + textOffsetY
|
||||
|
||||
@@ -39,7 +39,7 @@ internal object Inventory : ConsoleCommand {
|
||||
if (it.amount == 0) {
|
||||
EchoError("Unexpected zero-amounted item: ID ${it.item.dynamicID}")
|
||||
}
|
||||
Echo("ID ${it.item.dynamicID}${if (it.amount > 1) " ($it.second)" else ""}")
|
||||
Echo("ID ${it.item}${if (it.amount > 1) " (${it.amount})" else ""}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.ActorValue
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex.ACTORID_MIN
|
||||
import org.newdawn.slick.GameContainer
|
||||
|
||||
typealias ActorID = Int
|
||||
@@ -22,6 +23,13 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable<Actor>, Runnable
|
||||
FRONT // fake tiles
|
||||
}
|
||||
|
||||
companion object {
|
||||
val RANGE_BEHIND = ACTORID_MIN..0x1FFF_FFFF
|
||||
val RANGE_MIDDLE = 0x2000_0000..0x5FFF_FFFF
|
||||
val RANGE_MIDTOP = 0x6000_0000..0x6FFF_FFFF
|
||||
val RANGE_FRONT = 0x7000_0000..0x7FFF_FFFF
|
||||
}
|
||||
|
||||
abstract fun update(gc: GameContainer, delta: Int)
|
||||
|
||||
/**
|
||||
@@ -52,18 +60,12 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable<Actor>, Runnable
|
||||
fun hasCollision(value: ActorID) =
|
||||
try {
|
||||
Terrarum.ingame!!.theGameHasActor(value) ||
|
||||
value < ItemCodex.ACTOR_ID_MIN ||
|
||||
value < when (renderOrder) {
|
||||
RenderOrder.BEHIND -> ItemCodex.ACTOR_ID_MIN
|
||||
RenderOrder.MIDDLE -> 0x10000000
|
||||
RenderOrder.MIDTOP -> 0x60000000
|
||||
RenderOrder.FRONT -> 0x70000000
|
||||
} ||
|
||||
value > when (renderOrder) {
|
||||
RenderOrder.BEHIND -> 0x0FFFFFFF
|
||||
RenderOrder.MIDDLE -> 0x5FFFFFFF
|
||||
RenderOrder.MIDTOP -> 0x6FFFFFFF
|
||||
RenderOrder.FRONT -> 0x7FFFFFFF
|
||||
value < ItemCodex.ACTORID_MIN ||
|
||||
value !in when (renderOrder) {
|
||||
RenderOrder.BEHIND -> RANGE_BEHIND
|
||||
RenderOrder.MIDDLE -> RANGE_MIDDLE
|
||||
RenderOrder.MIDTOP -> RANGE_MIDTOP
|
||||
RenderOrder.FRONT -> RANGE_FRONT
|
||||
}
|
||||
}
|
||||
catch (gameNotInitialisedException: KotlinNullPointerException) {
|
||||
|
||||
@@ -57,18 +57,22 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode
|
||||
// new item
|
||||
else {
|
||||
if (item.isDynamic) {
|
||||
// assign new ID
|
||||
|
||||
println("[ActorInventory] new dynamic item detected: ${item.originalID}")
|
||||
|
||||
item.dynamicID = InventoryItem.generateNewDynamicID(this)
|
||||
// assign new ID for each
|
||||
repeat(count) {
|
||||
val newItem = item.clone().generateUniqueDynamicID(this)
|
||||
itemList.add(InventoryPair(newItem, 1))
|
||||
}
|
||||
}
|
||||
else {
|
||||
itemList.add(InventoryPair(item, count))
|
||||
}
|
||||
itemList.add(InventoryPair(item, count))
|
||||
}
|
||||
insertionSortLastElem(itemList)
|
||||
}
|
||||
|
||||
fun remove(itemID: Int, count: Int = 1) = remove(ItemCodex[itemID], count)
|
||||
fun remove(itemID: Int, count: Int) = remove(ItemCodex[itemID], count)
|
||||
/** 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) {
|
||||
val existingItem = getByDynamicID(item.dynamicID)
|
||||
if (existingItem != null) { // if the item already exists
|
||||
@@ -139,12 +143,23 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode
|
||||
remove(item, 1)
|
||||
}
|
||||
else {
|
||||
// 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)
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
// calculate damage value
|
||||
val baseDamagePerSwing = if (actor is ActorHumanoid)
|
||||
actor.avStrength / 1000.0
|
||||
else
|
||||
1.0 // TODO variable: scale, strength
|
||||
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)
|
||||
@@ -194,11 +209,11 @@ 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
|
||||
val midVal = get(mid).item.dynamicID
|
||||
|
||||
if (ID > midVal.dynamicID)
|
||||
if (ID > midVal)
|
||||
low = mid + 1
|
||||
else if (ID < midVal.dynamicID)
|
||||
else if (ID < midVal)
|
||||
high = mid - 1
|
||||
else
|
||||
return mid // key found
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.newdawn.slick.Graphics
|
||||
class DroppedItem(private val item: InventoryItem) : ActorWithPhysics(Actor.RenderOrder.MIDTOP) {
|
||||
|
||||
init {
|
||||
if (item.dynamicID >= ItemCodex.ACTOR_ID_MIN)
|
||||
if (item.dynamicID >= ItemCodex.ACTORID_MIN)
|
||||
throw RuntimeException("Attempted to create DroppedItem actor of a real actor; the real actor must be dropped instead.")
|
||||
|
||||
isVisible = true
|
||||
|
||||
@@ -3,9 +3,12 @@ package net.torvald.terrarum.gameworld
|
||||
import net.torvald.terrarum.gameactors.ActorID
|
||||
|
||||
/**
|
||||
* This world is economically isolated system. Economy will be important to make player keep playing,
|
||||
* The whole world is economically isolated system. Economy will be important to make player keep playing,
|
||||
* when all the necessary contents are set and implemented to the production.
|
||||
*
|
||||
* Design goal: keep the inflation rate low, but not negative (Single market)
|
||||
* OR, give each faction (establishment) its own economy and watch them prosper/doomed (DF style)
|
||||
*
|
||||
* Created by SKYHi14 on 2017-04-23.
|
||||
*/
|
||||
class GameEconomy {
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.ItemValue
|
||||
import net.torvald.terrarum.gameactors.ActorInventory
|
||||
import net.torvald.terrarum.gameactors.Pocketed
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex.ITEM_DYNAMIC
|
||||
import net.torvald.terrarum.itemproperties.Material
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import org.newdawn.slick.Color
|
||||
@@ -111,7 +112,7 @@ abstract class InventoryItem : Comparable<InventoryItem>, Cloneable {
|
||||
*/
|
||||
open var durability: Float = 0f
|
||||
|
||||
var using = false
|
||||
@Transient var using = false // Always false when loaded from savegame
|
||||
|
||||
/**
|
||||
* Effects applied continuously while in pocket
|
||||
@@ -166,7 +167,7 @@ abstract class InventoryItem : Comparable<InventoryItem>, Cloneable {
|
||||
|
||||
|
||||
override fun toString(): String {
|
||||
return dynamicID.toString()
|
||||
return "$dynamicID/$originalID"
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
@@ -242,13 +243,23 @@ abstract class InventoryItem : Comparable<InventoryItem>, Cloneable {
|
||||
return clonedItem
|
||||
}
|
||||
|
||||
|
||||
fun generateUniqueDynamicID(inventory: ActorInventory): InventoryItem {
|
||||
dynamicID = InventoryItem.generateUniqueDynamicID(inventory)
|
||||
return this
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun generateNewDynamicID(inventory: ActorInventory): Int {
|
||||
fun generateUniqueDynamicID(inventory: ActorInventory): Int {
|
||||
var ret: Int
|
||||
do {
|
||||
ret = HQRNG().nextInt(ItemCodex.ITEM_DYNAMIC.endInclusive + 1 - ItemCodex.ITEM_DYNAMIC.first) + ItemCodex.ITEM_DYNAMIC.first
|
||||
ret = ITEM_DYNAMIC.pickRandom()
|
||||
} while (inventory.contains(ret))
|
||||
return ret
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun IntRange.pickRandom() = HQRNG().nextInt(this.endInclusive - this.start + 1) + this.start // count() on 200 million entries? Se on vitun hyvää idea
|
||||
fun IntArray.pickRandom(): Int = this[HQRNG().nextInt(this.size)]
|
||||
fun DoubleArray.pickRandom(): Double = this[HQRNG().nextInt(this.size)]
|
||||
|
||||
@@ -26,7 +26,7 @@ object ItemCodex {
|
||||
|
||||
/**
|
||||
* <ItemID or RefID for Actor, TheItem>
|
||||
* Will return corresponding Actor if ID >= 16777216
|
||||
* Will return corresponding Actor if ID >= ACTORID_MIN
|
||||
*/
|
||||
private val itemCodex = HashMap<Int, InventoryItem>()
|
||||
private val dynamicItemDescription = HashMap<Int, KVHashMap>()
|
||||
@@ -35,8 +35,8 @@ object ItemCodex {
|
||||
val ITEM_WALLS = GameWorld.TILES_SUPPORTED..GameWorld.TILES_SUPPORTED * 2 - 1
|
||||
val ITEM_WIRES = GameWorld.TILES_SUPPORTED * 2..GameWorld.TILES_SUPPORTED * 2 + 255
|
||||
val ITEM_STATIC = ITEM_WIRES.endInclusive + 1..32767
|
||||
val ITEM_DYNAMIC = 32768..1048575
|
||||
val ACTOR_ID_MIN = ITEM_DYNAMIC.endInclusive + 1
|
||||
val ITEM_DYNAMIC = 32768..0x0FFF_FFFF
|
||||
val ACTORID_MIN = ITEM_DYNAMIC.endInclusive + 1
|
||||
|
||||
|
||||
private val itemImagePlaceholder = Image("./assets/item_kari_24.tga")
|
||||
|
||||
Reference in New Issue
Block a user