Resolving issues #16 and #20

This commit is contained in:
Song Minjae
2017-04-24 02:23:13 +09:00
parent 41b2b8a694
commit d70cb2524d
21 changed files with 158 additions and 76 deletions

View File

@@ -0,0 +1 @@
println("Hello, script !")

View File

@@ -19,17 +19,17 @@ object AmmoMeterProxy {
}
else {
meter.vitalGetterVal = {
if (ItemCodex[currentItem.id].consumable)
actor.inventory.getByID(currentItem.id)!!.amount.toFloat()
if (ItemCodex[currentItem.originalID].consumable)
actor.inventory.getByDynamicID(currentItem.dynamicID)!!.amount.toFloat()
else
actor.inventory.getByID(currentItem.id)!!.item.durability
actor.inventory.getByDynamicID(currentItem.dynamicID)!!.item.durability
}
meter.vitalGetterMax = {
if (ItemCodex[currentItem.id].consumable)
if (ItemCodex[currentItem.originalID].consumable)
500f
else
actor.inventory.getByID(currentItem.id)!!.item.maxDurability.toFloat()
actor.inventory.getByDynamicID(currentItem.dynamicID)!!.item.maxDurability.toFloat()
}
}
}

View File

@@ -217,17 +217,17 @@ class StateInGame : BasicGameState() {
uiAliases = arrayListOf(
uiPieMenu,
uiQuickBar,
uiInventoryPlayer,
//uiInventoryContainer,
uiVitalPrimary,
uiVitalSecondary,
uiVitalItem
)
uiAlasesPausing = arrayListOf(
uiInventoryPlayer,
//uiInventoryContainer,
consoleHandler
)
uiAlasesPausing.forEach { uiContainer.add(it) } // put them all to the UIContainer
uiAliases.forEach { uiContainer.add(it) } // put them all to the UIContainer
uiAlasesPausing.forEach { addUI(it) } // put them all to the UIContainer
uiAliases.forEach { addUI(it) } // put them all to the UIContainer
@@ -795,6 +795,15 @@ class StateInGame : BasicGameState() {
particlesContainer.add(particle)
}
fun addUI(ui: UIHandler) {
// check for exact duplicates
if (uiContainer.contains(ui)) {
throw IllegalArgumentException("Exact copy of the UI already exists: The instance of ${ui.UI.javaClass.simpleName}")
}
uiContainer.add(ui)
}
fun getActorByID(ID: Int): Actor {
if (actorContainer.size == 0 && actorContainerInactive.size == 0)
throw IllegalArgumentException("Actor with ID $ID does not exist.")

View File

@@ -47,7 +47,8 @@ class StateUITest : BasicGameState() {
init {
itemProperties[IVKey.ITEMTYPE] = IVKey.ItemType.HAMMER
}
override var id: Int = 5656
override var dynamicID: Int = 5656
override val originalID = dynamicID
override val isUnique: Boolean = true
override var originalName: String = "Test tool"
override var baseMass: Double = 12.0
@@ -56,25 +57,28 @@ class StateUITest : BasicGameState() {
override var maxDurability: Int = 143
override var durability: Float = 64f
override var consumable = false
override val isDynamic = true
})
actor.inventory.getByID(5656)!!.item.name = "Test tool"
actor.inventory.getByDynamicID(5656)!!.item.name = "Test tool"
actor.inventory.add(object : InventoryItem() {
init {
itemProperties[IVKey.ITEMTYPE] = IVKey.ItemType.ARTEFACT
}
override var id: Int = 4633
override var dynamicID: Int = 4633
override val originalID = dynamicID
override val isUnique: Boolean = true
override var originalName: String = "CONTEXT_ITEM_QUEST_NOUN"
override var baseMass: Double = 1.4
override var baseToolSize: Double? = null
override var inventoryCategory: String = InventoryItem.Category.MISC
override var consumable = false
override val isDynamic = false
})
actor.inventory.add(ItemCodex[16], 543)
actor.inventory.getByID(Tile.STONE)!!.item equipTo actor
actor.inventory.getByDynamicID(Tile.STONE)!!.item equipTo actor
}
override fun init(container: GameContainer?, game: StateBasedGame?) {

View File

@@ -91,7 +91,8 @@ class UIItemInventoryElem(
// this one-liner sets color
g.color = item!!.nameColour mul if (mouseUp) mouseOverTextCol else inactiveTextCol
g.drawString(
item!!.name + (if (amount > 0 && !item!!.isUnique) "${0x3000.toChar()}($amount)" else "") +
"${item!!.dynamicID}/${item!!.originalID}" + (if (amount > 0 && !item!!.isUnique) "${0x3000.toChar()}($amount)" else "") +
//item!!.name + (if (amount > 0 && !item!!.isUnique) "${0x3000.toChar()}($amount)" else "") +
(if (equippedSlot != null) " ${0xE081.toChar()}\$$equippedSlot" else ""),
posX + textOffsetX,
posY + textOffsetY
@@ -135,6 +136,7 @@ class UIItemInventoryElem(
override fun mousePressed(button: Int, x: Int, y: Int) {
if (item != null && Terrarum.ingame != null) {
// equip da shit
val itemEquipSlot = item!!.equipPosition
val player = Terrarum.ingame!!.player

View File

@@ -37,9 +37,9 @@ internal object Inventory : ConsoleCommand {
else {
target!!.inventory.forEach {
if (it.amount == 0) {
EchoError("Unexpected zero-amounted item: ID ${it.item.id}")
EchoError("Unexpected zero-amounted item: ID ${it.item.dynamicID}")
}
Echo("ID ${it.item.id}${if (it.amount > 1) " ($it.second)" else ""}")
Echo("ID ${it.item.dynamicID}${if (it.amount > 1) " ($it.second)" else ""}")
}
}
}

View File

@@ -6,6 +6,8 @@ import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.itemproperties.ItemCodex
import org.newdawn.slick.GameContainer
typealias ActorID = Int
/**
* @param renderOrder invisible/technical must use "Actor.RenderOrder.MIDDLE"
*
@@ -26,7 +28,7 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable<Actor>, Runnable
* Valid RefID is equal to or greater than 16777216.
* @return Reference ID. (16777216-0x7FFF_FFFF)
*/
open var referenceID: Int = generateUniqueReferenceID()
open var referenceID: ActorID = generateUniqueReferenceID()
var actorValue = ActorValue()
@Volatile var flagDespawn = false
@@ -46,8 +48,8 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable<Actor>, Runnable
*
* override var referenceID: Int = generateUniqueReferenceID()
*/
fun generateUniqueReferenceID(): Int {
fun hasCollision(value: Int) =
fun generateUniqueReferenceID(): ActorID {
fun hasCollision(value: ActorID) =
try {
Terrarum.ingame!!.theGameHasActor(value) ||
value < ItemCodex.ACTOR_ID_MIN ||

View File

@@ -138,13 +138,15 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null)
private val nullItem = object : InventoryItem() {
override var id: Int = 0
override var dynamicID: Int = 0
override val originalID = dynamicID
override val isUnique: Boolean = false
override var baseMass: Double = 0.0
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 val isDynamic = false
}
override fun update(gc: GameContainer, delta: Int) {

View File

@@ -35,26 +35,33 @@ 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.id == Player.PLAYER_REF_ID || item.id == 0x51621D) // do not delete this magic
if (item.dynamicID == Player.PLAYER_REF_ID || item.dynamicID == 0x51621D) // do not delete this magic
throw IllegalArgumentException("Attempted to put human player into the inventory.")
if (Terrarum.ingame != null &&
(item.id == Terrarum.ingame?.player?.referenceID))
(item.dynamicID == 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
val existingItem = getByID(item.id)
val existingItem = getByDynamicID(item.dynamicID)
if (existingItem != null) { // if the item already exists
val newCount = getByID(item.id)!!.amount + count
// if the item already exists
if (existingItem != null) {
val newCount = getByDynamicID(item.dynamicID)!!.amount + count
itemList.remove(existingItem)
itemList.add(InventoryPair(existingItem.item, newCount))
}
else { // new item
// new item
else {
if (item.isDynamic) {
// assign new ID
item.originalID = item.id
item.id = InventoryItem.generateNewDynamicID(this)
println("[ActorInventory] new dynamic item detected: ${item.originalID}")
item.dynamicID = InventoryItem.generateNewDynamicID(this)
}
itemList.add(InventoryPair(item, count))
}
@@ -63,11 +70,11 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode
fun remove(itemID: Int, count: Int = 1) = remove(ItemCodex[itemID], count)
fun remove(item: InventoryItem, count: Int = 1) {
val existingItem = getByID(item.id)
val existingItem = getByDynamicID(item.dynamicID)
if (existingItem != null) { // if the item already exists
val newCount = getByID(item.id)!!.amount - count
val newCount = getByDynamicID(item.dynamicID)!!.amount - count
if (newCount < 0) {
throw Error("Tried to remove $count of $item, but the inventory only contains ${getByID(item.id)!!.amount} of them.")
throw Error("Tried to remove $count of $item, but the inventory only contains ${getByDynamicID(item.dynamicID)!!.amount} of them.")
}
else if (newCount > 0) {
// decrement count
@@ -141,6 +148,8 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode
item.durability -= (baseDamagePerSwing * swingDmgToFrameDmg).toFloat()
if (item.durability <= 0)
remove(item, 1)
println("[ActorInventory] consumed; ${item.durability}")
}
}
@@ -150,13 +159,13 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode
fun contains(item: InventoryItem) = contains(item.id)
fun contains(item: InventoryItem) = contains(item.dynamicID)
fun contains(id: Int) =
if (itemList.size == 0)
false
else
itemList.binarySearch(id) >= 0
fun getByID(id: Int): InventoryPair? {
fun getByDynamicID(id: Int): InventoryPair? {
if (itemList.size == 0)
return null
@@ -187,9 +196,9 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode
val midVal = get(mid).item
if (ID > midVal.id)
if (ID > midVal.dynamicID)
low = mid + 1
else if (ID < midVal.id)
else if (ID < midVal.dynamicID)
high = mid - 1
else
return mid // key found

View File

@@ -12,17 +12,17 @@ import org.newdawn.slick.Graphics
class DroppedItem(private val item: InventoryItem) : ActorWithPhysics(Actor.RenderOrder.MIDTOP) {
init {
if (item.id >= ItemCodex.ACTOR_ID_MIN)
if (item.dynamicID >= ItemCodex.ACTOR_ID_MIN)
throw RuntimeException("Attempted to create DroppedItem actor of a real actor; the real actor must be dropped instead.")
isVisible = true
avBaseMass = if (item.id < TileCodex.TILE_UNIQUE_MAX)
TileCodex[item.id].density / 1000.0
avBaseMass = if (item.dynamicID < TileCodex.TILE_UNIQUE_MAX)
TileCodex[item.dynamicID].density / 1000.0
else
ItemCodex[item.id].mass
ItemCodex[item.dynamicID].mass
scale = ItemCodex[item.id].scale
scale = ItemCodex[item.dynamicID].scale
}
override fun update(gc: GameContainer, delta: Int) {

View File

@@ -43,7 +43,8 @@ open class HumanoidNPC(
// we're having InventoryItem data so that this class could be somewhat universal
override var itemData: InventoryItem = object : InventoryItem() {
override var id = referenceID
override var dynamicID = referenceID
override val originalID = dynamicID
override val isUnique = true
override var baseMass: Double
get() = actorValue.getAsDouble(AVKey.BASEMASS)!!
@@ -57,6 +58,7 @@ open class HumanoidNPC(
override var inventoryCategory = "npc"
override val originalName: String = actorValue.getAsString(AVKey.NAME) ?: "NPC"
override var consumable = true
override val isDynamic = false
override fun secondaryUse(gc: GameContainer, delta: Int): Boolean {
try {

View File

@@ -87,7 +87,7 @@ object PlayerBuilderSigrid {
Tile.SANDSTONE_RED, Tile.STONE, Tile.STONE_BRICKS,
Tile.STONE_QUARRIED, Tile.STONE_TILE_WHITE, Tile.TORCH
)
tiles.forEach { p.inventory.add(it, 999) }
tiles.forEach { p.addItem(it, 999) }
p.inventory.add(ItemCodex.ITEM_STATIC.first)

View File

@@ -50,7 +50,7 @@ interface Pocketed {
fun removeItem(itemID: Int, count: Int = 1) = inventory.remove(ItemCodex[itemID], count)
fun removeItem(item: InventoryItem, count: Int = 1) = inventory.remove(item, count)
fun hasItem(item: InventoryItem) = inventory.contains(item.id)
fun hasItem(item: InventoryItem) = inventory.contains(item.dynamicID)
fun hasItem(id: Int) = inventory.contains(id)

View File

@@ -7,6 +7,9 @@ import java.util.HashSet
/**
* Created by minjaesong on 16-02-15.
*/
typealias FactionID = Int
class Faction(name: String) : Comparable<Faction> {
var factionName: String = name
@@ -14,7 +17,7 @@ class Faction(name: String) : Comparable<Faction> {
lateinit var factionNeutral: HashSet<String>
lateinit var factionHostile: HashSet<String>
lateinit var factionFearful: HashSet<String>
var referenceID: Long = generateUniqueID()
var referenceID: FactionID = generateUniqueID()
init {
factionAmicable = HashSet<String>()
@@ -59,10 +62,11 @@ class Faction(name: String) : Comparable<Faction> {
factionFearful.remove(faction)
}
private fun generateUniqueID(): Long {
var ret: Long
/** Valid range: -2147483648..-1 (all the negative number) */
private fun generateUniqueID(): Int {
var ret: Int
do {
ret = HQRNG().nextLong().or(0x80000000L).and(0xFFFFFFFFL) // guaranteed to be 2147483648..4294967295
ret = HQRNG().nextInt(2147483647).plus(1).unaryMinus()
} while (FactionCodex.hasFaction(ret)) // check for collision
return ret
}

View File

@@ -9,7 +9,7 @@ import java.util.*
object FactionCodex {
val factionContainer = ArrayList<Faction>()
fun hasFaction(ID: Long): Boolean =
fun hasFaction(ID: FactionID): Boolean =
if (factionContainer.size == 0)
false
else
@@ -22,7 +22,7 @@ object FactionCodex {
insertionSortLastElem(factionContainer) // we can do this as we are only adding single actor
}
fun getFactionByID(ID: Long): Faction {
fun getFactionByID(ID: FactionID): Faction {
if (factionContainer.size == 0) throw IllegalArgumentException("Faction with ID $ID does not exist.")
val index = factionContainer.binarySearch(ID)
@@ -45,7 +45,7 @@ object FactionCodex {
arr[j + 1] = x
}
private fun ArrayList<Faction>.binarySearch(ID: Long): Int {
private fun ArrayList<Faction>.binarySearch(ID: FactionID): Int {
// code from collections/Collections.kt
var low = 0
var high = factionContainer.size - 1

View File

@@ -0,0 +1,29 @@
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,
* when all the necessary contents are set and implemented to the production.
*
* Created by SKYHi14 on 2017-04-23.
*/
class GameEconomy {
val transactionHistory = TransanctionHistory()
}
class TransanctionHistory {
private val entries = ArrayList<TransanctionHistory>()
/**
* @param to set 0 to indicate the money was lost to void
*/
data class TransactionEntry(val from: ActorID, val to: ActorID, val amount: Long) {
override fun toString() = "$from -> $to; $amount"
}
}

View File

@@ -34,10 +34,18 @@ class GameWorld(val width: Int, val height: Int) {
var gravitation: Vector2 = Vector2(0.0, 9.8)
/** RGB in Integer */
var globalLight: Int = 0
val time: WorldTime
val economy = GameEconomy()
var generatorSeed: Long = 0
init {
this.spawnX = width / 2
this.spawnY = 200

View File

@@ -14,7 +14,9 @@ import org.newdawn.slick.GameContainer
*/
abstract class InventoryItem : Comparable<InventoryItem>, Cloneable {
abstract var id: Int
abstract var dynamicID: Int
abstract val originalID: Int // WUT?! using init does not work!!
/**
*
@@ -60,7 +62,7 @@ abstract class InventoryItem : Comparable<InventoryItem>, Cloneable {
*
* The opposite of this is called STATIC and their example is a Block.
*/
open val isDynamic = false
abstract val isDynamic: Boolean
/**
* Where to equip the item
@@ -90,7 +92,6 @@ abstract class InventoryItem : Comparable<InventoryItem>, Cloneable {
else
throw NullPointerException("null input; nullify baseToolSize instead :p")
}
var originalID = id
/**
* Scale of the item.
@@ -165,16 +166,16 @@ abstract class InventoryItem : Comparable<InventoryItem>, Cloneable {
override fun toString(): String {
return id.toString()
return dynamicID.toString()
}
override fun hashCode(): Int {
return id
return dynamicID
}
override fun equals(other: Any?): Boolean {
if (other == null) return false
return id == (other as InventoryItem).id
return dynamicID == (other as InventoryItem).dynamicID
}
fun unsetCustomName() {
@@ -183,7 +184,7 @@ abstract class InventoryItem : Comparable<InventoryItem>, Cloneable {
nameColour = Color.white
}
override fun compareTo(other: InventoryItem): Int = (this.id - other.id).sign()
override fun compareTo(other: InventoryItem): Int = (this.dynamicID - other.dynamicID).sign()
fun Int.sign(): Int = if (this > 0) 1 else if (this < 0) -1 else 0

View File

@@ -46,7 +46,8 @@ 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 id: Int = i
override var dynamicID: Int = i
override val originalID = dynamicID
override val isUnique: Boolean = false
override var baseMass: Double = TileCodex[i].density / 1000.0
override var baseToolSize: Double? = null
@@ -54,7 +55,7 @@ object ItemCodex {
override val originalName = TileCodex[i % ITEM_WALLS.first].nameKey
override var consumable = true
override var inventoryCategory = Category.BLOCK
override var isDynamic = true
override var isDynamic = false
init {
itemProperties[IVKey.ITEMTYPE] = if (i in ITEM_TILES)
@@ -77,7 +78,7 @@ object ItemCodex {
}
// return false if the tile is already there
if (this.id == Terrarum.ingame!!.world.getTileFromTerrain(gc.mouseTileX, gc.mouseTileY))
if (this.dynamicID == Terrarum.ingame!!.world.getTileFromTerrain(gc.mouseTileX, gc.mouseTileY))
return false
// filter passed, do the job
@@ -104,16 +105,19 @@ object ItemCodex {
// test copper pickaxe
itemCodex[ITEM_STATIC.first] = object : InventoryItem() {
override var id = ITEM_STATIC.first
override var dynamicID = ITEM_STATIC.first
override val originalID = dynamicID
override val isUnique = false
override val originalName = "Test Pick"
override val originalName = ""
override var baseMass = 10.0
override var baseToolSize: Double? = 10.0
override var consumable = false
override var maxDurability = 64//606 // this much tiles before breaking
override var maxDurability = 147//606 // this much tiles before breaking
override var durability = maxDurability.toFloat()
override var equipPosition = EquipPosition.HAND_GRIP
override var inventoryCategory = Category.TOOL
override val isDynamic = true
private val testmaterial = Material(
0,0,0,0,0,0,0,0,1,0.0 // quick test material Stone
@@ -121,7 +125,7 @@ object ItemCodex {
init {
itemProperties[IVKey.ITEMTYPE] = IVKey.ItemType.PICK
name = "Steel pickaxe"
name = "Stone pickaxe"
}
override fun primaryUse(gc: GameContainer, delta: Int): Boolean {
@@ -184,16 +188,21 @@ object ItemCodex {
}
}
fun getItemImage(code: Int): Image {
if (code <= ITEM_TILES.endInclusive)
return TilesDrawer.tilesTerrain.getSubImage((code % 16) * 16, code / 16)
else if (code <= ITEM_WALLS.endInclusive) {
val img = TilesDrawer.tilesTerrain.getSubImage((code % 16) * 16, code / 16)
fun getItemImage(item: InventoryItem): Image {
// terrain
if (item.originalID in ITEM_TILES) {
return TilesDrawer.tilesTerrain.getSubImage((item.dynamicID % 16) * 16, item.originalID / 16)
}
// wall
else if (item.originalID in ITEM_WALLS) {
val img = TilesDrawer.tilesTerrain.getSubImage((item.originalID % 16) * 16, item.originalID / 16)
img.setImageColor(wallOverlayColour.r, wallOverlayColour.g, wallOverlayColour.b)
return img
}
else if (code <= ITEM_WIRES.endInclusive)
return TilesDrawer.tilesWire.getSubImage((code % 16) * 16, code / 16)
// wire
else if (item.originalID in ITEM_WIRES) {
return TilesDrawer.tilesWire.getSubImage((item.originalID % 16) * 16, item.originalID / 16)
}
else
return itemImagePlaceholder
}

View File

@@ -17,9 +17,9 @@ object LandUtil {
/**
* Get owner ID as an Actor/Faction
*/
fun resolveOwner(id: TileAddress): Any =
if (id < 0x80000000L)
Terrarum.ingame!!.getActorByID(id.toInt())
fun resolveOwner(id: Int): Any =
if (id >= 0)
Terrarum.ingame!!.getActorByID(id)
else
FactionCodex.getFactionByID(id)
}

View File

@@ -175,11 +175,11 @@ class UIInventory(
val sortListItem = inventorySortList[k + itemsScrollOffset]
items[k].item = sortListItem.item
items[k].amount = sortListItem.amount
items[k].itemImage = ItemCodex.getItemImage(sortListItem.item.id)
items[k].itemImage = ItemCodex.getItemImage(sortListItem.item)
// set quickslot number
for (qs in 1..QUICKSLOT_MAX) {
if (-sortListItem.item.id == actorValue.getAsInt(AVKey.__PLAYER_QSPREFIX + qs)) {
if (-sortListItem.item.dynamicID == actorValue.getAsInt(AVKey.__PLAYER_QSPREFIX + qs)) {
items[k].quickslot = qs % 10 // 10 -> 0, 1..9 -> 1..9
break
}