clickable inventory for (un)equip

This commit is contained in:
Song Minjae
2017-04-11 02:30:34 +09:00
parent 68f45ea6ab
commit c20524836d
17 changed files with 214 additions and 71 deletions

View File

@@ -1,30 +1,35 @@
## Format ##
Contain everything on [TEVD](github.com/minjaesong/TerranVirtualDisk)
* Save meta
- GZip'd binary (for more security)
- binary
- Filename : world (with no extension)
|Type |Mnemonic |Description |
|------------|------------|---------------------------------------|
|Byte[4] |TESV |Magic |
|Byte[n] |name |Savegame name, UTF-8 |
|Byte |NULL |String terminator |
|Byte[8] |terraseed |Terrain seed |
|Byte[8] |rogueseed |Randomiser seed |
|Byte[32] |hash1 |SHA-256 hash of worldinfo1 being stored (when not zipped)|
|Byte[32] |hash2 |SHA-256 hash of worldinfo2 being stored (when not zipped)|
|Byte[32] |hash3 |SHA-256 hash of worldinfo3 being stored (when not zipped)|
|Byte[32] |hash4 |SHA-256 hash of worldinfo4 being stored (when not zipped)|
|Type |Mnemonic |Description |
|----------|-----------|-----------------------------|
|Byte[4] |TESV |Magic |
|Byte[n] |name |Savegame name, UTF-8 |
|Byte |NULL |String terminator |
|Byte[8] |terraseed |Terrain seed |
|Byte[8] |rogueseed |Randomiser seed |
|Byte[4] |crc1 |CRC-32 of worldinfo1 entry |
|Byte[4] |crc2 |CRC-32 of worldinfo2 entry |
|Byte[4] |crc3 |CRC-32 of worldinfo3 entry |
|Byte[4] |crc4 |CRC-32 of worldinfo4 entry |
|Byte[32] |hash4321 |SHA-256 of crc4..crc3..crc2..crc1|
Endianness: Big
each entry on the disk contains CRC of its data, we can compare CRC saved in meta && CRC of entry header && CRC of actual content
* Actor/Faction data
- GZip'd GSON
- GSON
- Filename : (refid) (with no extension)
* Prop data
- GZip'd CSV
- CSV
- Filename : (with no extension)
worldinfo2 -- tileprop
worldinfo3 -- itemprop
@@ -43,14 +48,18 @@
Directory:
+--- <save1>
--- 2a93bc5fd...f823 Actor/DynamicItem/Faction/etc. data (JSON)
--- 423bdc838...93bd Actor/DynamicItem/Faction/etc. data (JSON)
+--- <save1.tevd>
--- 2a93bc5f (item ID) Actor/DynamicItem/Faction/etc. data (JSON)
--- 423bdc83 (item ID) Actor/DynamicItem/Faction/etc. data (JSON)
--- Items_list.txt Human-readable
--- Materials_list.txt Human-readable
--- Tiles_list.txt Human-readable
--- world save meta (binary, GZip)
--- worldinfo1 TEMD (binary, GZip)
--- worldinfo2 tileprop (GZip)
--- worldinfo3 itemprop (GZip)
--- worldinfo4 materialprop (GZip)
--- world save meta (binary)
--- worldinfo1 TEMD (binary)
--- worldinfo2 tileprop (CSV)
--- worldinfo3 itemprop (CSV)
--- worldinfo4 materialprop (CSV)
+--- computers
--- (UUID) virtual disk
+--- tapestries
--- (random Int) tapestry

View File

@@ -13,5 +13,7 @@
"GAME_INVENTORY_BLOCKS" : "Blocks",
"GAME_INVENTORY_WALLS" : "Walls",
"CONTEXT_ITEM_TOOL_PLURAL" : "Tools",
"GAME_INVENTORY_FAVORITES" : "Favorites"
"GAME_INVENTORY_FAVORITES" : "Favorites",
"GAME_INVENTORY_REGISTER" : "Register"
}

View File

@@ -50,7 +50,7 @@ class GameFontImpl : GameFontBase() {
GameFontBase.thaiSheet = SpriteSheet(
"./assets/graphics/fonts/thai_wide.tga", GameFontBase.W_LATIN_WIDE, GameFontBase.H)
GameFontBase.keycapSheet = SpriteSheet(
"./assets/graphics/fonts/puae000-e07f.tga", GameFontBase.SIZE_KEYCAP, GameFontBase.SIZE_KEYCAP)
"./assets/graphics/fonts/puae000-e0ff.tga", GameFontBase.SIZE_KEYCAP, GameFontBase.SIZE_KEYCAP)
val shk = arrayOf(
GameFontBase.asciiSheet,

View File

@@ -61,7 +61,7 @@ nopqrstuvwxyz
//g.drawString("Syö salmiakkia perkele", 480f, 10f)
val text = arrayOf(
/*val text = arrayOf(
"The bitmap font for game developers who seek good font that has real multilingual support,",
"for free (as in freedom AND without cost).",
"",
@@ -96,6 +96,11 @@ nopqrstuvwxyz
"Also supports: Unicode „quotation marks“—dashes…「括弧」‼",
"ASCII Latin-1 Latin_Ext-A Latin_Ext-B Greek Cyrillic CJK-Ideo Kana Hangul_Syllables",
""
)*/
val SP = "${0x3000.toChar()}${0x3000.toChar()}"
val text = arrayOf(
"${0xe006.toChar()} ${Lang["GAME_INVENTORY_USE"]}$SP${0xe011.toChar()}..${0xe019.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP${0xe034.toChar()} ${Lang["GAME_INVENTORY_DROP"]}"
)
text.forEachIndexed { i, s ->

View File

@@ -174,7 +174,11 @@ class StateInGame : BasicGameState() {
// >- queue up game UIs that should pause the world -<
// inventory
uiAlasesPausing[UI_INVENTORY_PLAYER] = UIHandler(
UIInventory(player, 800, Terrarum.HEIGHT - 160),
UIInventory(player,
width = 840,
height = Terrarum.HEIGHT - 160,
categoryWidth = 210
),
toggleKey = Terrarum.getConfigInt("keyinventory")
)
uiAlasesPausing[UI_INVENTORY_PLAYER]!!.setPosition(

View File

@@ -31,7 +31,7 @@ class StateUITest : BasicGameState() {
}
init {
ui = UIHandler(UIInventory(actor, 800, Terrarum.HEIGHT - 160))
ui = UIHandler(UIInventory(actor, 900, Terrarum.HEIGHT - 160, 220))
ui.posX = 0
ui.posY = 60

View File

@@ -208,6 +208,9 @@ object Terrarum : StateBasedGame(GAME_NAME) {
private val thirtyTwoBitArchs = arrayOf("i386", "i686", "ppc", "x86", "x86_32") // I know I should Write Once, Run Everywhere; but just in case :)
val is32Bit = thirtyTwoBitArchs.contains(systemArch)
lateinit var textureWhite: Image
lateinit var textureBlack: Image
init {
// just in case
@@ -252,6 +255,10 @@ object Terrarum : StateBasedGame(GAME_NAME) {
@Throws(SlickException::class)
override fun initStatesList(gc: GameContainer) {
textureWhite = Image("./assets/graphics/background_white.png")
textureBlack = Image("./assets/graphics/background_black.png")
fontGame = GameFontImpl()
fontSmallNumbers = TinyAlphNum()
@@ -638,15 +645,13 @@ infix fun Color.screen(other: Color) = Color(
1f - (1f - this.b) * (1f - other.b),
1f - (1f - this.a) * (1f - other.a)
)
operator fun Color.times(other: Color) = Color(
infix fun Color.mul(other: Color) = Color( // don't turn into an operator!
this.r * other.r,
this.g * other.g,
this.b * other.b,
this.a * other.a
)
operator fun Color.minus(other: Color) = Color(
infix fun Color.minus(other: Color) = Color( // don't turn into an operator!
this.r - other.r,
this.g - other.g,
this.b - other.b,
@@ -654,5 +659,11 @@ operator fun Color.minus(other: Color) = Color(
)
fun Int.toHex() = this.toLong().and(0xFFFFFFFF).toString(16).padStart(8, '0').toUpperCase()
fun Long.toHex() = {
val sb = StringBuilder()
(0..16).forEach {
}
}

View File

@@ -3,6 +3,7 @@ package net.torvald.terrarum
import net.torvald.colourutil.CIELabUtil.darkerLab
import net.torvald.terrarum.gameitem.InventoryItem
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIInventory
import net.torvald.terrarum.ui.UIItem
import net.torvald.terrarum.ui.UIItemTextButton
import org.newdawn.slick.Color
@@ -16,7 +17,7 @@ import org.newdawn.slick.Image
* Created by SKYHi14 on 2017-03-16.
*/
class UIItemInventoryElem(
parentUI: UICanvas,
parentUI: UIInventory,
override var posX: Int,
override var posY: Int,
override val width: Int,
@@ -38,6 +39,8 @@ class UIItemInventoryElem(
val UNIQUE_ITEM_HAS_NO_AMOUNT = -1
}
private val inventoryUI = parentUI
override val height = UIItemInventoryElem.height
private val imgOffset: Float
@@ -59,9 +62,9 @@ class UIItemInventoryElem(
}
override fun render(gc: GameContainer, g: Graphics) {
g.font = Terrarum.fontGame
// mouseover background
if (item != null || drawBackOnNull) {
if (mouseUp) {
BlendMode.resolve(mouseoverBackBlendMode)
@@ -78,15 +81,17 @@ class UIItemInventoryElem(
if (item != null && itemImage != null) {
blendNormal()
// item image
g.drawImage(itemImage!!, posX + imgOffset, posY + imgOffset)
// if mouse is over, text lights up
g.color = item!!.nameColour * if (mouseUp) mouseOverTextCol else UIItemTextButton.defaultInactiveCol
// this one-liner sets color
g.color = item!!.nameColour mul if (mouseUp) mouseOverTextCol else UIItemTextButton.defaultInactiveCol
g.drawString(
item!!.name + (if (amount > 0 && !item!!.isUnique) "${0x3000.toChar()}($amount)" else "") +
(if (equippedSlot != null) " <eq $equippedSlot>" else "")
, posX + textOffsetX
, posY + textOffsetY
(if (equippedSlot != null) " ${0xE081.toChar()}\$$equippedSlot" else ""),
posX + textOffsetX,
posY + textOffsetY
)
@@ -126,6 +131,20 @@ 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
if (item != player.itemEquipped[itemEquipSlot]) { // if this item is unequipped, equip it
player.itemEquipped[itemEquipSlot] = item
}
else { // if not, unequip it
player.itemEquipped[itemEquipSlot] = null
}
}
inventoryUI.rebuildList()
}
override fun mouseReleased(button: Int, x: Int, y: Int) {

View File

@@ -14,7 +14,7 @@ import org.newdawn.slick.Input
/**
* Created by minjaesong on 15-12-31.
*/
class ConsoleWindow : UICanvas, KeyboardControlled {
class ConsoleWindow : UICanvas, KeyControlled {
internal var UIColour = Color(0x80404080.toInt())
@@ -206,4 +206,10 @@ class ConsoleWindow : UICanvas, KeyboardControlled {
drawOffY = -height.toFloat()
openingTimeCounter = 0
}
override fun controllerButtonPressed(controller: Int, button: Int) {
}
override fun controllerButtonReleased(controller: Int, button: Int) {
}
}

View File

@@ -1,11 +1,11 @@
package net.torvald.terrarum.ui
/**
* Button pressing only. If you want stick-controls, use processInput()
*
* Created by minjaesong on 16-07-21.
* Created by minjaesong on 16-03-06.
*/
interface GamepadControlled {
interface KeyControlled {
fun keyPressed(key: Int, c: Char)
fun keyReleased(key: Int, c: Char)
fun controllerButtonPressed(controller: Int, button: Int)
fun controllerButtonReleased(controller: Int, button: Int)
}

View File

@@ -1,9 +0,0 @@
package net.torvald.terrarum.ui
/**
* Created by minjaesong on 16-03-06.
*/
interface KeyboardControlled {
fun keyPressed(key: Int, c: Char)
fun keyReleased(key: Int, c: Char)
}

View File

@@ -13,4 +13,10 @@ object Typography {
g.drawString(string, targetW.minus(stringW).ushr(1).toFloat(), screenPosY.toFloat())
}
fun printCentered(g: Graphics, string: String, posX: Int, posY: Int, frameWidth: Int) {
val stringW = g.font.getWidth(string)
g.drawString(string, frameWidth.minus(stringW).ushr(1).toFloat() + posX, posY.toFloat())
}
}

View File

@@ -207,13 +207,13 @@ class UIHandler(val UI: UICanvas,
}
fun keyPressed(key: Int, c: Char) {
if (isVisible && UI is KeyboardControlled) {
if (isVisible && UI is KeyControlled) {
UI.keyPressed(key, c)
}
}
fun keyReleased(key: Int, c: Char) {
if (isVisible && UI is KeyboardControlled) {
if (isVisible && UI is KeyControlled) {
UI.keyReleased(key, c)
}
}
@@ -249,13 +249,13 @@ class UIHandler(val UI: UICanvas,
}
fun controllerButtonPressed(controller: Int, button: Int) {
if (isVisible && UI is GamepadControlled) {
if (isVisible && UI is KeyControlled) {
UI.controllerButtonPressed(controller, button)
}
}
fun controllerButtonReleased(controller: Int, button: Int) {
if (isVisible && UI is GamepadControlled) {
if (isVisible && UI is KeyControlled) {
UI.controllerButtonReleased(controller, button)
}
}

View File

@@ -2,8 +2,11 @@ package net.torvald.terrarum.ui
import net.torvald.terrarum.*
import net.torvald.terrarum.Terrarum.QUICKSLOT_MAX
import net.torvald.terrarum.Terrarum.joypadLabelNinA
import net.torvald.terrarum.Terrarum.joypadLabelNinY
import net.torvald.terrarum.gameactors.*
import net.torvald.terrarum.gameitem.InventoryItem
import net.torvald.terrarum.langpack.Lang
import org.newdawn.slick.*
import java.util.*
@@ -13,8 +16,9 @@ import java.util.*
class UIInventory(
var actor: Pocketed?,
override var width: Int,
override var height: Int
) : UICanvas {
override var height: Int,
var categoryWidth: Int
) : UICanvas, MouseControlled, KeyControlled {
val inventory: ActorInventory?
get() = actor?.inventory
@@ -28,7 +32,7 @@ class UIInventory(
val catButtonsToCatIdent = HashMap<String, String>()
val backgroundColour = Color(0xA0282828.toInt())
val backgroundColour = Color(0xA0242424.toInt())
init {
catButtonsToCatIdent.put("GAME_INVENTORY_WEAPONS", InventoryItem.Category.WEAPON)
@@ -50,39 +54,41 @@ class UIInventory(
val itemStripGutterH = 8
val itemInterColGutter = 8
val controlHelpHeight = Terrarum.fontGame.lineHeight
val catButtons = UIItemTextButtonList(
this,
arrayOf(
"MENU_LABEL_ALL",
"GAME_INVENTORY_BLOCKS",
"GAME_INVENTORY_WALLS",
"GAME_INVENTORY_WEAPONS", // weapons and tools
"CONTEXT_ITEM_TOOL_PLURAL",
"CONTEXT_ITEM_ARMOR",
"GAME_INVENTORY_INGREDIENTS",
"GAME_INVENTORY_POTIONS",
"CONTEXT_ITEM_MAGIC",
"GAME_INVENTORY_BLOCKS",
"GAME_INVENTORY_WALLS",
"GAME_GENRE_MISC"
//"GAME_INVENTORY_FAVORITES",
),
width = (width / 3 / 100) * 100, // chop to hundreds unit (100, 200, 300, ...) with the black magic of integer division
height = height,
width = categoryWidth,
height = height - controlHelpHeight,
verticalGutter = itemStripGutterH,
readFromLang = true,
textAreaWidth = 100,
defaultSelection = 0,
iconSpriteSheet = SpriteSheet("./assets/graphics/gui/inventory/category.tga", 20, 20),
iconSpriteSheetIndices = intArrayOf(9,0,1,2,3,4,5,6,7,8),
highlightBackCol = Color(0x0c0c0c),
highlightBackBlendMode = BlendMode.SCREEN,
backgroundCol = Color(0x383838),
backgroundBlendMode = BlendMode.MULTIPLY,
iconSpriteSheetIndices = intArrayOf(9,6,7,0,1,2,3,4,5,8),
highlightBackCol = Color(0xb8b8b8),
highlightBackBlendMode = BlendMode.MULTIPLY,
backgroundCol = Color(0,0,0,0), // will use custom background colour!
backgroundBlendMode = BlendMode.NORMAL,
kinematic = true
)
val itemsStripWidth = ((width - catButtons.width) - (2 * itemStripGutterH + itemInterColGutter)) / 2
val items = Array(
2 + height / (UIItemInventoryElem.height + itemStripGutterV) * 2, {
2 + height / (UIItemInventoryElem.height + itemStripGutterV - controlHelpHeight) * 2, {
UIItemInventoryElem(
parentUI = this,
posX = catButtons.width + if (it % 2 == 0) itemStripGutterH else (itemStripGutterH + itemsStripWidth + itemInterColGutter),
@@ -98,7 +104,23 @@ class UIInventory(
val itemsScrollOffset = 0
var inventorySortList = ArrayList<InventoryPair>()
var rebuildList = true
private var rebuildList = true
private val SP = "${0x3000.toChar()}${0x3000.toChar()}${0x3000.toChar()}"
val listControlHelp: String
get() = if (Terrarum.environment == RunningEnvironment.PC)
"${0xe006.toChar()} ${Lang["GAME_INVENTORY_USE"]}$SP" +
"${0xe011.toChar()}..${0xe019.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
"${0xe034.toChar()} ${Lang["GAME_INVENTORY_DROP"]}"
else
"$joypadLabelNinY ${Lang["GAME_INVENTORY_USE"]}$SP" +
"${0xe011.toChar()}${0xe019.toChar()} ${Lang["GAME_INVENTORY_REGISTER"]}$SP" +
"$joypadLabelNinA ${Lang["GAME_INVENTORY_DROP"]}"
val listControlClose: String
get() = if (Terrarum.environment == RunningEnvironment.PC)
"${0xe037.toChar()} ${Lang["GAME_ACTION_CLOSE"]}"
else
"${0xe069.toChar()} ${Lang["GAME_ACTION_CLOSE"]}"
private var oldCatSelect = -1
@@ -133,6 +155,7 @@ class UIInventory(
// map sortList to item list
for (k in 0..items.size - 1) {
// we have an item
try {
val sortListItem = inventorySortList[k + itemsScrollOffset]
items[k].item = sortListItem.item
@@ -149,6 +172,7 @@ class UIInventory(
items[k].quickslot = null
}
// set equippedslot number
for (eq in 0..actor!!.itemEquipped.size - 1) {
if (eq < actor!!.itemEquipped.size) {
if (actor!!.itemEquipped[eq] == items[k].item) {
@@ -160,6 +184,7 @@ class UIInventory(
}
}
}
// we do not have an item, empty the slot
catch (e: IndexOutOfBoundsException) {
items[k].item = null
items[k].amount = 0
@@ -175,19 +200,45 @@ class UIInventory(
}
override fun render(gc: GameContainer, g: Graphics) {
//blendMul()
// background
blendNormal()
g.color = backgroundColour
g.fillRect(0f, 0f, width.toFloat(), height.toFloat())
// cat bar background
blendMul()
g.color = Color(0xcccccc)
g.fillRect(0f, 0f, catButtons.width.toFloat(), height.toFloat())
catButtons.render(gc, g)
items.forEach {
it.render(gc, g)
}
// texts
blendNormal()
g.color = Color(0xdddddd)
Typography.printCentered(g, listControlHelp, catButtons.width, height - controlHelpHeight, width - catButtons.width)
Typography.printCentered(g, listControlClose, 0, height - controlHelpHeight, catButtons.width)
}
/** Persuade the UI to rebuild its item list */
fun rebuildList() {
rebuildList = true
}
////////////
// Inputs //
////////////
override fun processInput(gc: GameContainer, delta: Int, input: Input) {
}
@@ -214,4 +265,34 @@ class UIInventory(
override fun endClosing(gc: GameContainer, delta: Int) {
handler!!.posX = -width
}
override fun keyPressed(key: Int, c: Char) {
items.forEach { it.keyPressed(key, c) }
}
override fun mouseMoved(oldx: Int, oldy: Int, newx: Int, newy: Int) {
}
override fun keyReleased(key: Int, c: Char) {
}
override fun mouseDragged(oldx: Int, oldy: Int, newx: Int, newy: Int) {
}
override fun controllerButtonPressed(controller: Int, button: Int) {
}
override fun mousePressed(button: Int, x: Int, y: Int) {
items.forEach { if (it.mouseUp) it.mousePressed(button, x, y) }
}
override fun controllerButtonReleased(controller: Int, button: Int) {
}
override fun mouseReleased(button: Int, x: Int, y: Int) {
items.forEach { if (it.mouseUp) it.mouseReleased(button, x, y) }
}
override fun mouseWheelMoved(change: Int) {
}
}

View File

@@ -23,8 +23,10 @@ abstract class UIItem(var parentUI: UICanvas) { // do not replace parentUI to UI
protected val relativeMouseY: Int
get() = (Terrarum.appgc.mouseScreenY - (parentUI.handler?.posY ?: 0) - this.posY)
/** If mouse is hovering over it */
open val mouseUp: Boolean
get() = relativeMouseX in 0..width - 1 && relativeMouseY in 0..height - 1
/** If mouse is hovering over it and mouse is down */
open val mousePushed: Boolean
get() = mouseUp && Terrarum.appgc.input.isMouseButtonDown(Terrarum.getConfigInt("mouseprimary")!!)

View File

@@ -148,6 +148,7 @@ class UIItemTextButtonList(
g.fillRect(posX.toFloat(), posY.toFloat(), width.toFloat(), height.toFloat())
g.color = highlightBackCol
BlendMode.resolve(highlightBackBlendMode)
g.fillRect(posX.toFloat(), highlightY.toFloat(), width.toFloat(), UIItemTextButton.height.toFloat())
buttons.forEach { it.render(gc, g) }

View File

@@ -12,7 +12,7 @@ import org.newdawn.slick.Input
/**
* Created by minjaesong on 16-09-08.
*/
class UITextTerminal(val terminal: Terminal) : UICanvas, KeyboardControlled, MouseControlled {
class UITextTerminal(val terminal: Terminal) : UICanvas, KeyControlled, MouseControlled {
override fun mouseMoved(oldx: Int, oldy: Int, newx: Int, newy: Int) {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -29,6 +29,12 @@ class UITextTerminal(val terminal: Terminal) : UICanvas, KeyboardControlled, Mou
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun controllerButtonPressed(controller: Int, button: Int) {
}
override fun controllerButtonReleased(controller: Int, button: Int) {
}
override var width: Int = terminal.displayW// + some
override var height: Int = terminal.displayH// + frame
private var terminalDisplay = Image(terminal.displayW, terminal.displayH)