World Click events

let's hope it works w/o tests as I can't get to the Ingame now
This commit is contained in:
minjaesong
2018-10-01 23:51:04 +09:00
parent d95eaf5be0
commit 76ab620247
25 changed files with 341 additions and 226 deletions

1
.gitignore vendored
View File

@@ -11,3 +11,4 @@ external_resource_packs.zip
.idea/workspace.xml
.tmp*
external_resource_packs.zip
tmp_*

Binary file not shown.

View File

@@ -55,7 +55,7 @@ class TestPick extends GameItem {
}
@Override
boolean primaryUse(float delta) {
boolean startPrimaryUse(float delta) {
int mouseTileX = Terrarum.getMouseTileX()
int mouseTileY = Terrarum.getMouseTileY()

Binary file not shown.

View File

@@ -0,0 +1,214 @@
package net.torvald.terrarum
import com.badlogic.gdx.Screen
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.ui.ConsoleWindow
import java.util.ArrayList
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
import javax.swing.JOptionPane
open class IngameInstance(val batch: SpriteBatch) : Screen {
var screenZoom = 1.0f
val ZOOM_MAXIMUM = 4.0f
val ZOOM_MINIMUM = 0.5f
open lateinit var consoleHandler: ConsoleWindow
open lateinit var world: GameWorld
/** The actor the game is currently allowing you to control.
*
* Most of the time it'd be the "player", but think about the case where you have possessed
* some random actor of the game. Now that actor is now actorNowPlaying, the actual gamer's avatar
* (reference ID of 0x91A7E2) (must) stay in the actorContainer, but it's not a actorNowPlaying.
*
* Nullability of this property is believed to be unavoidable (trust me!). I'm sorry for the inconvenience.
*/
open var actorNowPlaying: ActorHumanoid? = null
val ACTORCONTAINER_INITIAL_SIZE = 64
val actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
override fun hide() {
}
override fun show() {
}
override fun render(delta: Float) {
}
override fun pause() {
}
override fun resume() {
}
override fun resize(width: Int, height: Int) {
}
override fun dispose() {
}
////////////
// EVENTS //
////////////
/**
* Event for triggering held item's `startPrimaryUse(Float)`
*/
open fun worldPrimaryClickStart(delta: Float) {
}
/**
* Event for triggering held item's `endPrimaryUse(Float)`
*/
open fun worldPrimaryClickEnd(delta: Float) {
}
/**
* Event for triggering held item's `startSecondaryUse(Float)`
*/
open fun worldSecondaryClickStart(delta: Float) {
}
/**
* Event for triggering held item's `endSecondaryUse(Float)`
*/
open fun worldSecondaryClickEnd(delta: Float) {
}
///////////////////////
// UTILITY FUNCTIONS //
///////////////////////
fun getActorByID(ID: Int): Actor {
if (actorContainer.size == 0 && actorContainerInactive.size == 0)
throw IllegalArgumentException("Actor with ID $ID does not exist.")
var index = actorContainer.binarySearch(ID)
if (index < 0) {
index = actorContainerInactive.binarySearch(ID)
if (index < 0) {
JOptionPane.showMessageDialog(
null,
"Actor with ID $ID does not exist.",
null, JOptionPane.ERROR_MESSAGE
)
throw IllegalArgumentException("Actor with ID $ID does not exist.")
}
else
return actorContainerInactive[index]
}
else
return actorContainer[index]
}
fun ArrayList<*>.binarySearch(actor: Actor) = this.binarySearch(actor.referenceID!!)
fun ArrayList<*>.binarySearch(ID: Int): Int {
// code from collections/Collections.kt
var low = 0
var high = this.size - 1
while (low <= high) {
val mid = (low + high).ushr(1) // safe from overflows
val midVal = get(mid)!!
if (ID > midVal.hashCode())
low = mid + 1
else if (ID < midVal.hashCode())
high = mid - 1
else
return mid // key found
}
return -(low + 1) // key not found
}
open fun removeActor(ID: Int) = removeActor(getActorByID(ID))
/**
* get index of the actor and delete by the index.
* we can do this as the list is guaranteed to be sorted
* and only contains unique values.
*
* Any values behind the index will be automatically pushed to front.
* This is how remove function of [java.util.ArrayList] is defined.
*/
open fun removeActor(actor: Actor?) {
if (actor == null) return
val indexToDelete = actorContainer.binarySearch(actor.referenceID!!)
if (indexToDelete >= 0) {
actorContainer.removeAt(indexToDelete)
}
}
/**
* Check for duplicates, append actor and sort the list
*/
open fun addNewActor(actor: Actor?) {
if (actor == null) return
if (theGameHasActor(actor.referenceID!!)) {
throw Error("The actor $actor already exists in the game")
}
else {
actorContainer.add(actor)
insertionSortLastElem(actorContainer) // we can do this as we are only adding single actor
}
}
fun isActive(ID: Int): Boolean =
if (actorContainer.size == 0)
false
else
actorContainer.binarySearch(ID) >= 0
fun isInactive(ID: Int): Boolean =
if (actorContainerInactive.size == 0)
false
else
actorContainerInactive.binarySearch(ID) >= 0
/**
* actorContainer extensions
*/
fun theGameHasActor(actor: Actor?) = if (actor == null) false else theGameHasActor(actor.referenceID!!)
fun theGameHasActor(ID: Int): Boolean =
isActive(ID) || isInactive(ID)
fun insertionSortLastElem(arr: ArrayList<Actor>) {
lock(ReentrantLock()) {
var j = arr.lastIndex - 1
val x = arr.last()
while (j >= 0 && arr[j] > x) {
arr[j + 1] = arr[j]
j -= 1
}
arr[j + 1] = x
}
}
inline fun lock(lock: Lock, body: () -> Unit) {
lock.lock()
try {
body()
}
finally {
lock.unlock()
}
}
}

View File

@@ -18,11 +18,8 @@ import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.AppLoader.printdbgerr
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorID
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.imagefont.TinyAlphNum
import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.ui.ConsoleWindow
import net.torvald.terrarum.utils.JsonFetcher
import net.torvald.terrarum.utils.JsonWriter
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
@@ -33,10 +30,6 @@ import org.lwjgl.BufferUtils
import org.lwjgl.input.Controllers
import java.io.File
import java.io.IOException
import java.util.*
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
import javax.swing.JOptionPane
@@ -714,174 +707,6 @@ object Terrarum : Screen {
}
}
open class IngameInstance(val batch: SpriteBatch) : Screen {
var screenZoom = 1.0f
val ZOOM_MAXIMUM = 4.0f
val ZOOM_MINIMUM = 0.5f
open lateinit var consoleHandler: ConsoleWindow
open lateinit var world: GameWorld
/** The actor the game is currently allowing you to control.
*
* Most of the time it'd be the "player", but think about the case where you have possessed
* some random actor of the game. Now that actor is now actorNowPlaying, the actual gamer's avatar
* (reference ID of 0x91A7E2) (must) stay in the actorContainer, but it's not a actorNowPlaying.
*
* Nullability of this property is believed to be unavoidable (trust me!). I'm sorry for the inconvenience.
*/
open var actorNowPlaying: ActorHumanoid? = null
val ACTORCONTAINER_INITIAL_SIZE = 64
val actorContainer = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
override fun hide() {
}
override fun show() {
}
override fun render(delta: Float) {
}
override fun pause() {
}
override fun resume() {
}
override fun resize(width: Int, height: Int) {
}
override fun dispose() {
}
fun getActorByID(ID: Int): Actor {
if (actorContainer.size == 0 && actorContainerInactive.size == 0)
throw IllegalArgumentException("Actor with ID $ID does not exist.")
var index = actorContainer.binarySearch(ID)
if (index < 0) {
index = actorContainerInactive.binarySearch(ID)
if (index < 0) {
JOptionPane.showMessageDialog(
null,
"Actor with ID $ID does not exist.",
null, JOptionPane.ERROR_MESSAGE
)
throw IllegalArgumentException("Actor with ID $ID does not exist.")
}
else
return actorContainerInactive[index]
}
else
return actorContainer[index]
}
fun ArrayList<*>.binarySearch(actor: Actor) = this.binarySearch(actor.referenceID!!)
fun ArrayList<*>.binarySearch(ID: Int): Int {
// code from collections/Collections.kt
var low = 0
var high = this.size - 1
while (low <= high) {
val mid = (low + high).ushr(1) // safe from overflows
val midVal = get(mid)!!
if (ID > midVal.hashCode())
low = mid + 1
else if (ID < midVal.hashCode())
high = mid - 1
else
return mid // key found
}
return -(low + 1) // key not found
}
open fun removeActor(ID: Int) = removeActor(getActorByID(ID))
/**
* get index of the actor and delete by the index.
* we can do this as the list is guaranteed to be sorted
* and only contains unique values.
*
* Any values behind the index will be automatically pushed to front.
* This is how remove function of [java.util.ArrayList] is defined.
*/
open fun removeActor(actor: Actor?) {
if (actor == null) return
val indexToDelete = actorContainer.binarySearch(actor.referenceID!!)
if (indexToDelete >= 0) {
actorContainer.removeAt(indexToDelete)
}
}
/**
* Check for duplicates, append actor and sort the list
*/
open fun addNewActor(actor: Actor?) {
if (actor == null) return
if (theGameHasActor(actor.referenceID!!)) {
throw Error("The actor $actor already exists in the game")
}
else {
actorContainer.add(actor)
insertionSortLastElem(actorContainer) // we can do this as we are only adding single actor
}
}
fun isActive(ID: Int): Boolean =
if (actorContainer.size == 0)
false
else
actorContainer.binarySearch(ID) >= 0
fun isInactive(ID: Int): Boolean =
if (actorContainerInactive.size == 0)
false
else
actorContainerInactive.binarySearch(ID) >= 0
/**
* actorContainer extensions
*/
fun theGameHasActor(actor: Actor?) = if (actor == null) false else theGameHasActor(actor.referenceID!!)
fun theGameHasActor(ID: Int): Boolean =
isActive(ID) || isInactive(ID)
fun insertionSortLastElem(arr: ArrayList<Actor>) {
lock(ReentrantLock()) {
var j = arr.lastIndex - 1
val x = arr.last()
while (j >= 0 && arr[j] > x) {
arr[j + 1] = arr[j]
j -= 1
}
arr[j + 1] = x
}
}
inline fun lock(lock: Lock, body: () -> Unit) {
lock.lock()
try {
body()
}
finally {
lock.unlock()
}
}
}
inline fun SpriteBatch.inUse(action: (SpriteBatch) -> Unit) {
this.begin()
action(this)

View File

@@ -507,11 +507,21 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
*/
val D: Vector2 = Vector2(externalForce.x.magnSqr(), externalForce.y.magnSqr()) * dragCoefficient * 0.5 * A// * tileDensityFluid.toDouble()
val V: Vector2 = (W - D) / Terrarum.TARGET_FPS.toDouble() * SI_TO_GAME_ACC
val V: Vector2 = (W - D) / Terrarum.TARGET_FPS * SI_TO_GAME_ACC
return V
}
/**
* Event for collision (event gets fired when it collided with the world or other actors)
*
* This event may fired two or more times per update.
*/
open fun collided(other: Array<CollisionMessage>) {
}
data class CollisionMessage(val targetID: Int, val AkspfisWorld: Boolean)
/**
* Apply gravitation to the every falling body (unless not levitating)
*
@@ -663,6 +673,14 @@ open class ActorWBMovable(val world: GameWorld, renderOrder: RenderOrder, val im
2, 7 -> { newHitbox.translatePosY( - newHitbox.endY.modTileDelta()) ; bounceY = true }
}
// fire Collision Event with one/two/three-side collision
// for the ease of writing, this jumptable is separated from above.
when (selfCollisionStatus) {
// TODO compose CollisionInfo and fire collided()
}
// two-side collision
if (selfCollisionStatus in listOf(3,6,9,12)) {
debug1("twoside collision $selfCollisionStatus")

View File

@@ -115,14 +115,14 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
// don't separate Player from this! Physics will break, esp. airborne manoeuvre
if (ingame.canPlayerControl) {
val itemOnGrip = ingame.actorNowPlaying?.inventory?.itemEquipped?.get(GameItem.EquipPosition.HAND_GRIP) ?: null
// fire world click events; the event is defined as Ingame's (or any others') WorldClick event
if (ingame.uiContainer.map { if ((it.isOpening || it.isOpened) && it.mouseUp) 1 else 0 }.sum() == 0) { // no UI on the mouse, right?
if (itemOnGrip != null) {
if (button == Terrarum.getConfigInt("mouseprimary")) {
itemOnGrip.endPrimaryUse(Terrarum.deltaTime)
ingame.worldPrimaryClickEnd(Terrarum.deltaTime)
}
if (button == Terrarum.getConfigInt("mousesecondary")) {
itemOnGrip.endSecondaryUse(Terrarum.deltaTime)
ingame.worldSecondaryClickEnd(Terrarum.deltaTime)
}
}
}
@@ -144,6 +144,21 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
// don't separate Player from this! Physics will break, esp. airborne manoeuvre
if (ingame.canPlayerControl) {
// fire world click events; the event is defined as Ingame's (or any others') WorldClick event
if (ingame.uiContainer.map { if ((it.isOpening || it.isOpened) && it.mouseUp) 1 else 0 }.sum() == 0) { // no UI on the mouse, right?
if (button == Terrarum.getConfigInt("mouseprimary")) {
ingame.worldPrimaryClickStart(Terrarum.deltaTime)
}
if (button == Terrarum.getConfigInt("mousesecondary")) {
ingame.worldSecondaryClickStart(Terrarum.deltaTime)
}
}
}
ingame.uiContainer.forEach { it.touchDown(screenX, screenY, pointer, button) }
return true
}

View File

@@ -142,7 +142,7 @@ abstract class GameItem : Comparable<GameItem>, Cloneable {
* Consumption function is executed in net.torvald.terrarum.gamecontroller.IngameController,
* in which the function itself is defined in net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
*/
open fun primaryUse(delta: Float): Boolean = false
open fun startPrimaryUse(delta: Float): Boolean = false
/**
* Apply effects (continuously or not) while secondary button (usually right mouse button) is down
@@ -152,7 +152,7 @@ abstract class GameItem : Comparable<GameItem>, Cloneable {
*
* note: DO NOT super() this!
*/
open fun secondaryUse(delta: Float): Boolean = false
open fun startSecondaryUse(delta: Float): Boolean = false
open fun endPrimaryUse(delta: Float): Boolean = false
open fun endSecondaryUse(delta: Float): Boolean = false

View File

@@ -61,12 +61,12 @@ object ItemCodex {
print("$originalID ")
}
override fun primaryUse(delta: Float): Boolean {
override fun startPrimaryUse(delta: Float): Boolean {
return false
// TODO base punch attack
}
override fun secondaryUse(delta: Float): Boolean {
override fun startSecondaryUse(delta: Float): Boolean {
val mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble())
// check for collision with actors (BLOCK only)
@@ -130,7 +130,7 @@ object ItemCodex {
name = "Stone pickaxe"
}
override fun primaryUse(delta: Float): Boolean {
override fun startPrimaryUse(delta: Float): Boolean {
val mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble())
val actorvalue = ingame.actorNowPlaying.actorValue

View File

@@ -51,12 +51,12 @@ class EntryPoint : ModuleEntryPoint() {
print("$originalID ")
}
override fun primaryUse(delta: Float): Boolean {
override fun startPrimaryUse(delta: Float): Boolean {
return false
// TODO base punch attack
}
override fun secondaryUse(delta: Float): Boolean {
override fun startSecondaryUse(delta: Float): Boolean {
val ingame = Terrarum.ingame!! as Ingame
val mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble())

View File

@@ -29,6 +29,7 @@ import net.torvald.terrarum.modulebasegame.console.AVTracker
import net.torvald.terrarum.modulebasegame.console.ActorsList
import net.torvald.terrarum.console.Authenticator
import net.torvald.terrarum.console.SetGlobalLightOverride
import net.torvald.terrarum.itemproperties.GameItem
import net.torvald.terrarum.modulebasegame.gameactors.*
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.modulebasegame.imagefont.Watch7SegMain
@@ -392,6 +393,25 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
}// END enter
override fun worldPrimaryClickStart(delta: Float) {
val itemOnGrip = actorNowPlaying?.inventory?.itemEquipped?.get(GameItem.EquipPosition.HAND_GRIP)
itemOnGrip?.startPrimaryUse(delta)
}
override fun worldPrimaryClickEnd(delta: Float) {
val itemOnGrip = actorNowPlaying?.inventory?.itemEquipped?.get(GameItem.EquipPosition.HAND_GRIP)
itemOnGrip?.endPrimaryUse(delta)
}
override fun worldSecondaryClickStart(delta: Float) {
val itemOnGrip = actorNowPlaying?.inventory?.itemEquipped?.get(GameItem.EquipPosition.HAND_GRIP)
itemOnGrip?.startSecondaryUse(delta)
}
override fun worldSecondaryClickEnd(delta: Float) {
val itemOnGrip = actorNowPlaying?.inventory?.itemEquipped?.get(GameItem.EquipPosition.HAND_GRIP)
itemOnGrip?.endSecondaryUse(delta)
}
protected var updateDeltaCounter = 0.0
protected val updateRate = 1.0 / Terrarum.TARGET_INTERNAL_FPS

View File

@@ -50,7 +50,7 @@ open class HumanoidNPC(
override val isDynamic = false
override val material = Material(0,0,0,0,0,0,0,0,0,0.0)
override fun secondaryUse(delta: Float): Boolean {
override fun startSecondaryUse(delta: Float): Boolean {
try {
// place the actor to the world
this@HumanoidNPC.setPosition(Terrarum.mouseX, Terrarum.mouseY)

View File

@@ -69,13 +69,13 @@ interface Pocketed {
fun consumePrimary(item: GameItem) {
if (item.primaryUse(Terrarum.deltaTime)) {
if (item.startPrimaryUse(Terrarum.deltaTime)) {
inventory.consumeItem(this as Actor, item) // consume on successful
}
}
fun consumeSecondary(item: GameItem) {
if (item.secondaryUse(Terrarum.deltaTime))
if (item.startSecondaryUse(Terrarum.deltaTime))
inventory.consumeItem(this as Actor, item) // consume on successful
}
}

View File

@@ -33,7 +33,7 @@ class PickaxeGeneric(override val originalID: ItemID) : GameItem() {
super.name = "Builtin Pickaxe"
}
override fun primaryUse(delta: Float): Boolean {
override fun startPrimaryUse(delta: Float): Boolean {
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
if (player == null) return false

View File

@@ -77,6 +77,9 @@ open class UIRemoCon(treeRepresentation: QNDTreeNode<String>) : UICanvas() {
return UIRemoConElement(this, dynamicStrArray)
}
// currently there's no resetter for this!
private var startNewGameCalled = false
override fun updateUI(delta: Float) {
if (mouseActionAvailable) {
remoConTray.update(delta)
@@ -105,20 +108,24 @@ open class UIRemoCon(treeRepresentation: QNDTreeNode<String>) : UICanvas() {
}
}
else if (it.labelText.contains("Start New Random Game")) {
if (!startNewGameCalled) {
startNewGameCalled = true
printdbg(this, 1)
val ingame = Ingame(Terrarum.batch)
ingame.gameLoadInfoPayload = Ingame.NewWorldParameters(2400, 800, HQRNG().nextLong())
ingame.gameLoadMode = Ingame.GameLoadMode.CREATE_NEW
printdbg(this, 1)
printdbg(this, 2)
val ingame = Ingame(Terrarum.batch)
ingame.gameLoadInfoPayload = Ingame.NewWorldParameters(2400, 800, HQRNG().nextLong())
ingame.gameLoadMode = Ingame.GameLoadMode.CREATE_NEW
Terrarum.ingame = ingame
LoadScreen.screenToLoad = ingame
Terrarum.setScreen(LoadScreen)
printdbg(this, 2)
printdbg(this, 3)
Terrarum.ingame = ingame
LoadScreen.screenToLoad = ingame
Terrarum.setScreen(LoadScreen)
printdbg(this, 3)
}
}
else {
// check if target exists

View File

@@ -36,6 +36,7 @@ object UITitleRemoConYaml {
- Development Tools $
- Building Maker
- Start New Random Game
- MENU_LABEL_RETURN
""".trimIndent()
operator fun invoke() = if (AppLoader.IS_DEVELOPMENT_BUILD)

View File

@@ -57,7 +57,7 @@ abstract class UICanvas(
val relativeMouseY: Int
get() = Terrarum.mouseScreenY - handler.posY
/** If mouse is hovering over it */
/** If mouse is hovering over it regardless of its visibility */
val mouseUp: Boolean
get() = relativeMouseX in 0..width - 1 && relativeMouseY in 0..height - 1
/** If mouse is hovering over it and mouse is down */

View File

@@ -6,11 +6,11 @@ Ord Hex Description
00 54 T
01 45 E
02 4D M
03 44 D
03 7A z # 'z' because it's compressed
04 01 Number of bytes per tile; only 1 is supported
04 01 Version revision number
05 Number of layers
05 03 Number of layers
06 00 Reserved
07 00 Reserved
@@ -36,16 +36,30 @@ Ord Hex Description
17 Default spawn coord Y
# Layer count 1
18 Terrain tiles data MSB
18 54 T
19 45 E
20 52 R
21 52 R
22 Uncompressed size of DEFLATEd payload
23 Uncompressed size of DEFLATEd payload
24 Uncompressed size of DEFLATEd payload
25 Uncompressed size of DEFLATEd payload
26... DEFLATEd payload for the terrain (MSB ++ LSB; uncompressed size must be 1.5x of MSB) # ++ is a list concat sign in Haskell
# Layer count 2
... Wall tiles data MSB
... "WALL"
... Uncompressed size of DEFLATEd payload
... DEFLATEd payload for the wall (MSB ++ LSB; uncompressed size must be 1.5x of MSB)
# Layer count 3
... Terrain tiles data LSB (half size of MSB byte array)
... Wall tiles data LSB (half size of MSB byte array)
... "WIRE"
... Uncompressed size of DEFLATEd payload
... Wire tiles data (MSB only)
# Layer count 4
... Wire tiles data (0-255)
<EOF>
<EOF>
* To read layers: you'll need to search for specific strings, namely ["TERR", "WALL", "WIRE"]

View File

@@ -4,15 +4,15 @@ A savegame is a single file in the format of TerranVirtualDisk.
Files contained the TerranVirtualDisk is as follows:
(root)
worldinfo0 -- Savegame Metadata GZipped (TESV)
worldinfo1 -- Layer Data GZipped (TEMD)
worldinfo0 -- Savegame Metadata (TESV)
worldinfo1 -- Layer Data (TEMD)
worldinfo2 -- Copy of blocks.csv GZipped -- will use this from the next load
worldinfo3 -- Copy of items.csv GZipped -- will use this from the next load
worldinfo4 -- Copy of materials.csv GZipped -- will use this from the next load
(any random number in Hex ACTORID_MIN..FFFFFFFF) -- Serialised Entity Information (including Player)
(PLAYER_REF_ID in Hex -- 91A7E2) -- Player Character Information (Serialised Entity Information)
(51621D) -- The Debug Player (Serialised Entity Information)
load_order.txt -- LoadOrder.csv
load_order.txt -- LoadOrder.csv (NOT zipped)

View File

@@ -38,7 +38,7 @@ Connect two or more tracker head to play the array of trackers play simultaneous
## Aimhack ##
- Include a valid way of obtaining Aimhack (possessed weapon shit?)
- Implement it on ```<item>.primaryUse(gc, delta)```
- Implement it on ```<item>.startPrimaryUse(gc, delta)```
## Particles ##

Binary file not shown.

Binary file not shown.