mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 08:38:30 +09:00
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:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@ external_resource_packs.zip
|
|||||||
.idea/workspace.xml
|
.idea/workspace.xml
|
||||||
.tmp*
|
.tmp*
|
||||||
external_resource_packs.zip
|
external_resource_packs.zip
|
||||||
|
tmp_*
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -55,7 +55,7 @@ class TestPick extends GameItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean primaryUse(float delta) {
|
boolean startPrimaryUse(float delta) {
|
||||||
int mouseTileX = Terrarum.getMouseTileX()
|
int mouseTileX = Terrarum.getMouseTileX()
|
||||||
int mouseTileY = Terrarum.getMouseTileY()
|
int mouseTileY = Terrarum.getMouseTileY()
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
214
src/net/torvald/terrarum/IngameInstance.kt
Normal file
214
src/net/torvald/terrarum/IngameInstance.kt
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,11 +18,8 @@ import net.torvald.terrarum.AppLoader.printdbg
|
|||||||
import net.torvald.terrarum.AppLoader.printdbgerr
|
import net.torvald.terrarum.AppLoader.printdbgerr
|
||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
import net.torvald.terrarum.gameactors.ActorID
|
import net.torvald.terrarum.gameactors.ActorID
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
|
||||||
import net.torvald.terrarum.imagefont.TinyAlphNum
|
import net.torvald.terrarum.imagefont.TinyAlphNum
|
||||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
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.JsonFetcher
|
||||||
import net.torvald.terrarum.utils.JsonWriter
|
import net.torvald.terrarum.utils.JsonWriter
|
||||||
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
||||||
@@ -33,10 +30,6 @@ import org.lwjgl.BufferUtils
|
|||||||
import org.lwjgl.input.Controllers
|
import org.lwjgl.input.Controllers
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
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) {
|
inline fun SpriteBatch.inUse(action: (SpriteBatch) -> Unit) {
|
||||||
this.begin()
|
this.begin()
|
||||||
action(this)
|
action(this)
|
||||||
|
|||||||
@@ -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 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
|
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)
|
* 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 }
|
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
|
// two-side collision
|
||||||
if (selfCollisionStatus in listOf(3,6,9,12)) {
|
if (selfCollisionStatus in listOf(3,6,9,12)) {
|
||||||
debug1("twoside collision $selfCollisionStatus")
|
debug1("twoside collision $selfCollisionStatus")
|
||||||
|
|||||||
@@ -115,14 +115,14 @@ class IngameController(val ingame: Ingame) : InputAdapter() {
|
|||||||
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
// don't separate Player from this! Physics will break, esp. airborne manoeuvre
|
// don't separate Player from this! Physics will break, esp. airborne manoeuvre
|
||||||
if (ingame.canPlayerControl) {
|
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")) {
|
if (button == Terrarum.getConfigInt("mouseprimary")) {
|
||||||
itemOnGrip.endPrimaryUse(Terrarum.deltaTime)
|
ingame.worldPrimaryClickEnd(Terrarum.deltaTime)
|
||||||
}
|
}
|
||||||
if (button == Terrarum.getConfigInt("mousesecondary")) {
|
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 {
|
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) }
|
ingame.uiContainer.forEach { it.touchDown(screenX, screenY, pointer, button) }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ abstract class GameItem : Comparable<GameItem>, Cloneable {
|
|||||||
* Consumption function is executed in net.torvald.terrarum.gamecontroller.IngameController,
|
* Consumption function is executed in net.torvald.terrarum.gamecontroller.IngameController,
|
||||||
* in which the function itself is defined in net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
|
* 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
|
* 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!
|
* 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 endPrimaryUse(delta: Float): Boolean = false
|
||||||
open fun endSecondaryUse(delta: Float): Boolean = false
|
open fun endSecondaryUse(delta: Float): Boolean = false
|
||||||
|
|||||||
@@ -61,12 +61,12 @@ object ItemCodex {
|
|||||||
print("$originalID ")
|
print("$originalID ")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun primaryUse(delta: Float): Boolean {
|
override fun startPrimaryUse(delta: Float): Boolean {
|
||||||
return false
|
return false
|
||||||
// TODO base punch attack
|
// 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())
|
val mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble())
|
||||||
|
|
||||||
// check for collision with actors (BLOCK only)
|
// check for collision with actors (BLOCK only)
|
||||||
@@ -130,7 +130,7 @@ object ItemCodex {
|
|||||||
name = "Stone pickaxe"
|
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 mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble())
|
||||||
val actorvalue = ingame.actorNowPlaying.actorValue
|
val actorvalue = ingame.actorNowPlaying.actorValue
|
||||||
|
|
||||||
|
|||||||
@@ -51,12 +51,12 @@ class EntryPoint : ModuleEntryPoint() {
|
|||||||
print("$originalID ")
|
print("$originalID ")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun primaryUse(delta: Float): Boolean {
|
override fun startPrimaryUse(delta: Float): Boolean {
|
||||||
return false
|
return false
|
||||||
// TODO base punch attack
|
// TODO base punch attack
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun secondaryUse(delta: Float): Boolean {
|
override fun startSecondaryUse(delta: Float): Boolean {
|
||||||
val ingame = Terrarum.ingame!! as Ingame
|
val ingame = Terrarum.ingame!! as Ingame
|
||||||
|
|
||||||
val mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble())
|
val mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble())
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import net.torvald.terrarum.modulebasegame.console.AVTracker
|
|||||||
import net.torvald.terrarum.modulebasegame.console.ActorsList
|
import net.torvald.terrarum.modulebasegame.console.ActorsList
|
||||||
import net.torvald.terrarum.console.Authenticator
|
import net.torvald.terrarum.console.Authenticator
|
||||||
import net.torvald.terrarum.console.SetGlobalLightOverride
|
import net.torvald.terrarum.console.SetGlobalLightOverride
|
||||||
|
import net.torvald.terrarum.itemproperties.GameItem
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.*
|
import net.torvald.terrarum.modulebasegame.gameactors.*
|
||||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
||||||
import net.torvald.terrarum.modulebasegame.imagefont.Watch7SegMain
|
import net.torvald.terrarum.modulebasegame.imagefont.Watch7SegMain
|
||||||
@@ -392,6 +393,25 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
}// END enter
|
}// 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 var updateDeltaCounter = 0.0
|
||||||
protected val updateRate = 1.0 / Terrarum.TARGET_INTERNAL_FPS
|
protected val updateRate = 1.0 / Terrarum.TARGET_INTERNAL_FPS
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ open class HumanoidNPC(
|
|||||||
override val isDynamic = false
|
override val isDynamic = false
|
||||||
override val material = Material(0,0,0,0,0,0,0,0,0,0.0)
|
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 {
|
try {
|
||||||
// place the actor to the world
|
// place the actor to the world
|
||||||
this@HumanoidNPC.setPosition(Terrarum.mouseX, Terrarum.mouseY)
|
this@HumanoidNPC.setPosition(Terrarum.mouseX, Terrarum.mouseY)
|
||||||
|
|||||||
@@ -69,13 +69,13 @@ interface Pocketed {
|
|||||||
|
|
||||||
|
|
||||||
fun consumePrimary(item: GameItem) {
|
fun consumePrimary(item: GameItem) {
|
||||||
if (item.primaryUse(Terrarum.deltaTime)) {
|
if (item.startPrimaryUse(Terrarum.deltaTime)) {
|
||||||
inventory.consumeItem(this as Actor, item) // consume on successful
|
inventory.consumeItem(this as Actor, item) // consume on successful
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun consumeSecondary(item: GameItem) {
|
fun consumeSecondary(item: GameItem) {
|
||||||
if (item.secondaryUse(Terrarum.deltaTime))
|
if (item.startSecondaryUse(Terrarum.deltaTime))
|
||||||
inventory.consumeItem(this as Actor, item) // consume on successful
|
inventory.consumeItem(this as Actor, item) // consume on successful
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ class PickaxeGeneric(override val originalID: ItemID) : GameItem() {
|
|||||||
super.name = "Builtin Pickaxe"
|
super.name = "Builtin Pickaxe"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun primaryUse(delta: Float): Boolean {
|
override fun startPrimaryUse(delta: Float): Boolean {
|
||||||
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
|
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
|
||||||
if (player == null) return false
|
if (player == null) return false
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ open class UIRemoCon(treeRepresentation: QNDTreeNode<String>) : UICanvas() {
|
|||||||
return UIRemoConElement(this, dynamicStrArray)
|
return UIRemoConElement(this, dynamicStrArray)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// currently there's no resetter for this!
|
||||||
|
private var startNewGameCalled = false
|
||||||
|
|
||||||
override fun updateUI(delta: Float) {
|
override fun updateUI(delta: Float) {
|
||||||
if (mouseActionAvailable) {
|
if (mouseActionAvailable) {
|
||||||
remoConTray.update(delta)
|
remoConTray.update(delta)
|
||||||
@@ -105,20 +108,24 @@ open class UIRemoCon(treeRepresentation: QNDTreeNode<String>) : UICanvas() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (it.labelText.contains("Start New Random Game")) {
|
else if (it.labelText.contains("Start New Random Game")) {
|
||||||
|
if (!startNewGameCalled) {
|
||||||
|
startNewGameCalled = true
|
||||||
|
|
||||||
printdbg(this, 1)
|
|
||||||
|
|
||||||
val ingame = Ingame(Terrarum.batch)
|
printdbg(this, 1)
|
||||||
ingame.gameLoadInfoPayload = Ingame.NewWorldParameters(2400, 800, HQRNG().nextLong())
|
|
||||||
ingame.gameLoadMode = Ingame.GameLoadMode.CREATE_NEW
|
|
||||||
|
|
||||||
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
|
printdbg(this, 2)
|
||||||
LoadScreen.screenToLoad = ingame
|
|
||||||
Terrarum.setScreen(LoadScreen)
|
|
||||||
|
|
||||||
printdbg(this, 3)
|
Terrarum.ingame = ingame
|
||||||
|
LoadScreen.screenToLoad = ingame
|
||||||
|
Terrarum.setScreen(LoadScreen)
|
||||||
|
|
||||||
|
printdbg(this, 3)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// check if target exists
|
// check if target exists
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ object UITitleRemoConYaml {
|
|||||||
- Development Tools $
|
- Development Tools $
|
||||||
- Building Maker
|
- Building Maker
|
||||||
- Start New Random Game
|
- Start New Random Game
|
||||||
|
- MENU_LABEL_RETURN
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
operator fun invoke() = if (AppLoader.IS_DEVELOPMENT_BUILD)
|
operator fun invoke() = if (AppLoader.IS_DEVELOPMENT_BUILD)
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ abstract class UICanvas(
|
|||||||
val relativeMouseY: Int
|
val relativeMouseY: Int
|
||||||
get() = Terrarum.mouseScreenY - handler.posY
|
get() = Terrarum.mouseScreenY - handler.posY
|
||||||
|
|
||||||
/** If mouse is hovering over it */
|
/** If mouse is hovering over it regardless of its visibility */
|
||||||
val mouseUp: Boolean
|
val mouseUp: Boolean
|
||||||
get() = relativeMouseX in 0..width - 1 && relativeMouseY in 0..height - 1
|
get() = relativeMouseX in 0..width - 1 && relativeMouseY in 0..height - 1
|
||||||
/** If mouse is hovering over it and mouse is down */
|
/** If mouse is hovering over it and mouse is down */
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ Ord Hex Description
|
|||||||
00 54 T
|
00 54 T
|
||||||
01 45 E
|
01 45 E
|
||||||
02 4D M
|
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
|
06 00 Reserved
|
||||||
07 00 Reserved
|
07 00 Reserved
|
||||||
@@ -36,16 +36,30 @@ Ord Hex Description
|
|||||||
17 Default spawn coord Y
|
17 Default spawn coord Y
|
||||||
|
|
||||||
# Layer count 1
|
# 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
|
# 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
|
# Layer count 3
|
||||||
... Terrain tiles data LSB (half size of MSB byte array)
|
... "WIRE"
|
||||||
... Wall tiles data LSB (half size of MSB byte array)
|
... Uncompressed size of DEFLATEd payload
|
||||||
|
... Wire tiles data (MSB only)
|
||||||
|
|
||||||
# Layer count 4
|
<EOF>
|
||||||
... Wire tiles data (0-255)
|
|
||||||
|
|
||||||
<EOF>
|
|
||||||
|
* To read layers: you'll need to search for specific strings, namely ["TERR", "WALL", "WIRE"]
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ A savegame is a single file in the format of TerranVirtualDisk.
|
|||||||
Files contained the TerranVirtualDisk is as follows:
|
Files contained the TerranVirtualDisk is as follows:
|
||||||
|
|
||||||
(root)
|
(root)
|
||||||
worldinfo0 -- Savegame Metadata GZipped (TESV)
|
worldinfo0 -- Savegame Metadata (TESV)
|
||||||
worldinfo1 -- Layer Data GZipped (TEMD)
|
worldinfo1 -- Layer Data (TEMD)
|
||||||
worldinfo2 -- Copy of blocks.csv GZipped -- will use this from the next load
|
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
|
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
|
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)
|
(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)
|
(PLAYER_REF_ID in Hex -- 91A7E2) -- Player Character Information (Serialised Entity Information)
|
||||||
(51621D) -- The Debug Player (Serialised Entity Information)
|
(51621D) -- The Debug Player (Serialised Entity Information)
|
||||||
load_order.txt -- LoadOrder.csv
|
load_order.txt -- LoadOrder.csv (NOT zipped)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Connect two or more tracker head to play the array of trackers play simultaneous
|
|||||||
## Aimhack ##
|
## Aimhack ##
|
||||||
|
|
||||||
- Include a valid way of obtaining Aimhack (possessed weapon shit?)
|
- 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 ##
|
## Particles ##
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user