Misc fixes regarding NPC behavior tree, but they still dont function properly (except ship pet)
This commit is contained in:
parent
4bd85c0e0e
commit
09f7e8ac70
@ -40,7 +40,7 @@ class ResumeInfo {
|
|||||||
if (resumable instanceof ProtectedResumable) {
|
if (resumable instanceof ProtectedResumable) {
|
||||||
// top is protected, can handle the error
|
// top is protected, can handle the error
|
||||||
ProtectedResumable pr = (ProtectedResumable) resumable;
|
ProtectedResumable pr = (ProtectedResumable) resumable;
|
||||||
pr.resumeError(context, savedState, Conversions.toErrorObject(error));
|
pr.resumeError(context, savedState, error);
|
||||||
Dispatch.evaluateTailCalls(context);
|
Dispatch.evaluateTailCalls(context);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -11,9 +11,8 @@ import ru.dbotthepony.kstarbound.world.entities.behavior.RandomizeNode
|
|||||||
import ru.dbotthepony.kstarbound.world.entities.behavior.SequenceNode
|
import ru.dbotthepony.kstarbound.world.entities.behavior.SequenceNode
|
||||||
|
|
||||||
enum class CompositeNodeType(override val jsonName: String, val factory: (Map<String, NodeParameter>, ImmutableList<AbstractBehaviorNode>) -> AbstractBehaviorNode) : IStringSerializable {
|
enum class CompositeNodeType(override val jsonName: String, val factory: (Map<String, NodeParameter>, ImmutableList<AbstractBehaviorNode>) -> AbstractBehaviorNode) : IStringSerializable {
|
||||||
SEQUENCE("Sequence", { _, c -> SequenceNode(c) }),
|
SEQUENCE("Sequence", { _, c -> SequenceNode(c, isSelector = false) }),
|
||||||
// in original engine, selector and sequence nodes are identical code-wise
|
SELECTOR("Selector", { _, c -> SequenceNode(c, isSelector = true) }),
|
||||||
SELECTOR("Selector", { _, c -> SequenceNode(c) }),
|
|
||||||
PARALLEL("Parallel", { p, c -> ParallelNode(p, c) }),
|
PARALLEL("Parallel", { p, c -> ParallelNode(p, c) }),
|
||||||
DYNAMIC("Dynamic", { _, c -> DynamicNode(c) }),
|
DYNAMIC("Dynamic", { _, c -> DynamicNode(c) }),
|
||||||
RANDOMIZE("Randomize", { _, c -> RandomizeNode(c) });
|
RANDOMIZE("Randomize", { _, c -> RandomizeNode(c) });
|
||||||
|
@ -239,7 +239,7 @@ class ActorMovementController() : MovementController() {
|
|||||||
updateParameters(calculateMovementParameters(actorMovementParameters))
|
updateParameters(calculateMovementParameters(actorMovementParameters))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: run is unsed
|
// TODO: run is unused
|
||||||
fun pathMove(position: Vector2d, run: Boolean, parameters: PathFinder.Parameters? = null): Pair<Vector2d, Boolean>? {
|
fun pathMove(position: Vector2d, run: Boolean, parameters: PathFinder.Parameters? = null): Pair<Vector2d, Boolean>? {
|
||||||
// FIXME: code flow is stupid
|
// FIXME: code flow is stupid
|
||||||
|
|
||||||
@ -281,6 +281,7 @@ class ActorMovementController() : MovementController() {
|
|||||||
controlMove = null
|
controlMove = null
|
||||||
controlRun = false
|
controlRun = false
|
||||||
controlCrouch = false
|
controlCrouch = false
|
||||||
|
controlDown = false
|
||||||
controlJump = false
|
controlJump = false
|
||||||
controlJumpAnyway = false
|
controlJumpAnyway = false
|
||||||
controlFly = null
|
controlFly = null
|
||||||
|
@ -197,9 +197,6 @@ open class MovementController {
|
|||||||
var movementParameters: MovementParameters = Globals.movementParameters
|
var movementParameters: MovementParameters = Globals.movementParameters
|
||||||
protected set
|
protected set
|
||||||
|
|
||||||
var gravityMultiplier = 1.0
|
|
||||||
var isGravityDisabled = false
|
|
||||||
|
|
||||||
open fun isAtWorldLimit(bottomOnly: Boolean = false): Boolean {
|
open fun isAtWorldLimit(bottomOnly: Boolean = false): Boolean {
|
||||||
return false // TODO
|
return false // TODO
|
||||||
}
|
}
|
||||||
@ -212,7 +209,7 @@ open class MovementController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun determineGravity(): Vector2d {
|
fun determineGravity(): Vector2d {
|
||||||
if (isGravityDisabled)
|
if (movementParameters.gravityEnabled == false)
|
||||||
return Vector2d.ZERO
|
return Vector2d.ZERO
|
||||||
|
|
||||||
return world.chunkMap.gravityAt(position)
|
return world.chunkMap.gravityAt(position)
|
||||||
@ -279,7 +276,7 @@ open class MovementController {
|
|||||||
*/
|
*/
|
||||||
// TODO: Ghost collisions occur, where objects trip on edges
|
// TODO: Ghost collisions occur, where objects trip on edges
|
||||||
open fun move(delta: Double) {
|
open fun move(delta: Double) {
|
||||||
isZeroGravity = isGravityDisabled || gravityMultiplier == 0.0 || determineGravity().lengthSquared == 0.0
|
isZeroGravity = movementParameters.gravityEnabled == false || (movementParameters.gravityMultiplier ?: 1.0) == 0.0 || determineGravity().lengthSquared == 0.0
|
||||||
|
|
||||||
val movementParameters = movementParameters
|
val movementParameters = movementParameters
|
||||||
|
|
||||||
|
@ -102,6 +102,9 @@ class PathController(val controller: ActorMovementController, var edgeTimer: Dou
|
|||||||
this.path.addAll(newPath)
|
this.path.addAll(newPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (this.path.isEmpty() && newPath.isNotEmpty()) {
|
||||||
|
merged = true
|
||||||
|
this.path.addAll(newPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!merged && controller.position != this.startPosition) {
|
if (!merged && controller.position != this.startPosition) {
|
||||||
@ -130,7 +133,11 @@ class PathController(val controller: ActorMovementController, var edgeTimer: Dou
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.edgeTimer = newEdgeTimer
|
this.edgeTimer = newEdgeTimer
|
||||||
return this.path.isEmpty()
|
|
||||||
|
if (this.path.isEmpty())
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return null
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -139,7 +146,7 @@ class PathController(val controller: ActorMovementController, var edgeTimer: Dou
|
|||||||
fun findPath(target: Vector2d): Boolean? {
|
fun findPath(target: Vector2d): Boolean? {
|
||||||
// reached the end of the last path and we have a new target position to move toward
|
// reached the end of the last path and we have a new target position to move toward
|
||||||
|
|
||||||
if (path.isEmpty() && controller.world.geometry.diff(this.target!!, target).lengthSquared > 0.1) {
|
if (this.target != null && path.isEmpty() && controller.world.geometry.diff(this.target!!, target).lengthSquared > 0.1) {
|
||||||
reset()
|
reset()
|
||||||
this.target = target
|
this.target = target
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,9 @@ abstract class AbstractBehaviorNode {
|
|||||||
RUNNING(null)
|
RUNNING(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var calls = 0
|
||||||
|
protected set
|
||||||
|
|
||||||
abstract fun run(delta: Double, state: BehaviorState): Status
|
abstract fun run(delta: Double, state: BehaviorState): Status
|
||||||
abstract fun reset()
|
abstract fun reset()
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ class ActionNode(val name: String, val parameters: Map<String, NodeParameter>, v
|
|||||||
private val nodeID = BehaviorState.NODE_GARBAGE_INDEX.getAndIncrement()
|
private val nodeID = BehaviorState.NODE_GARBAGE_INDEX.getAndIncrement()
|
||||||
|
|
||||||
override fun run(delta: Double, state: BehaviorState): Status {
|
override fun run(delta: Double, state: BehaviorState): Status {
|
||||||
|
calls++
|
||||||
var coroutine = coroutine
|
var coroutine = coroutine
|
||||||
var firstTime = false
|
var firstTime = false
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ class ActionNode(val name: String, val parameters: Map<String, NodeParameter>, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "ActionNode[$name, parameters=$parameters, outputs=$outputs, coroutine=$coroutine]"
|
return "ActionNode[$calls / $name, parameters=$parameters, outputs=$outputs, coroutine=$coroutine]"
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -15,6 +15,7 @@ class DecoratorNode(val name: String, val parameters: Map<String, NodeParameter>
|
|||||||
private val nodeID = BehaviorState.NODE_GARBAGE_INDEX.getAndIncrement()
|
private val nodeID = BehaviorState.NODE_GARBAGE_INDEX.getAndIncrement()
|
||||||
|
|
||||||
override fun run(delta: Double, state: BehaviorState): Status {
|
override fun run(delta: Double, state: BehaviorState): Status {
|
||||||
|
calls++
|
||||||
var coroutine = coroutine
|
var coroutine = coroutine
|
||||||
|
|
||||||
if (coroutine == null) {
|
if (coroutine == null) {
|
||||||
@ -100,7 +101,7 @@ class DecoratorNode(val name: String, val parameters: Map<String, NodeParameter>
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "DecoratorNode[$name, coroutine=$coroutine, parameters=$parameters, children=$child]"
|
return "DecoratorNode[$calls / $name, coroutine=$coroutine, parameters=$parameters, children=$child]"
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -8,6 +8,7 @@ class DynamicNode(val children: ImmutableList<AbstractBehaviorNode>) : AbstractB
|
|||||||
private var index = 0
|
private var index = 0
|
||||||
|
|
||||||
override fun run(delta: Double, state: BehaviorState): Status {
|
override fun run(delta: Double, state: BehaviorState): Status {
|
||||||
|
calls++
|
||||||
for ((i, node) in children.withIndex()) {
|
for ((i, node) in children.withIndex()) {
|
||||||
val status = node.runAndReset(delta, state)
|
val status = node.runAndReset(delta, state)
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ class DynamicNode(val children: ImmutableList<AbstractBehaviorNode>) : AbstractB
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "DynamicNode[${children.size}, index=$index, current=${children.getOrNull(index)}]"
|
return "DynamicNode[$calls / ${children.size}, index=$index, current=${children.getOrNull(index)}]"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reset() {
|
override fun reset() {
|
||||||
|
@ -34,6 +34,7 @@ class ParallelNode(parameters: Map<String, NodeParameter>, val children: Immutab
|
|||||||
private var lastSucceeded = -1
|
private var lastSucceeded = -1
|
||||||
|
|
||||||
override fun run(delta: Double, state: BehaviorState): Status {
|
override fun run(delta: Double, state: BehaviorState): Status {
|
||||||
|
calls++
|
||||||
var failed = 0
|
var failed = 0
|
||||||
var succeeded = 0
|
var succeeded = 0
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ class ParallelNode(parameters: Map<String, NodeParameter>, val children: Immutab
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "ParallelNode[children=${children.size}, successLimit=$successLimit, failLimit=$failLimit, lastFailed=$lastFailed, lastSucceeded=$lastSucceeded]"
|
return "ParallelNode[$calls / children=${children.size}, successLimit=$successLimit, failLimit=$failLimit, lastFailed=$lastFailed, lastSucceeded=$lastSucceeded]"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reset() {
|
override fun reset() {
|
||||||
|
@ -8,6 +8,8 @@ class RandomizeNode(val children: ImmutableList<AbstractBehaviorNode>) : Abstrac
|
|||||||
var index = -1
|
var index = -1
|
||||||
|
|
||||||
override fun run(delta: Double, state: BehaviorState): Status {
|
override fun run(delta: Double, state: BehaviorState): Status {
|
||||||
|
calls++
|
||||||
|
|
||||||
if (index == -1 && children.isNotEmpty())
|
if (index == -1 && children.isNotEmpty())
|
||||||
index = state.lua.random.nextInt(children.size)
|
index = state.lua.random.nextInt(children.size)
|
||||||
|
|
||||||
@ -19,9 +21,9 @@ class RandomizeNode(val children: ImmutableList<AbstractBehaviorNode>) : Abstrac
|
|||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
return "RandomizeNode[${children.size}, not chosen]"
|
return "RandomizeNode[$calls / ${children.size}, not chosen]"
|
||||||
else
|
else
|
||||||
return "RandomizeNode[${children.size}, ${children[index]}]"
|
return "RandomizeNode[$calls / ${children.size}, ${children[index]}]"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reset() {
|
override fun reset() {
|
||||||
|
@ -4,25 +4,30 @@ import com.google.common.collect.ImmutableList
|
|||||||
import org.classdump.luna.runtime.ExecutionContext
|
import org.classdump.luna.runtime.ExecutionContext
|
||||||
import ru.dbotthepony.kstarbound.lua.userdata.BehaviorState
|
import ru.dbotthepony.kstarbound.lua.userdata.BehaviorState
|
||||||
|
|
||||||
class SequenceNode(val children: ImmutableList<AbstractBehaviorNode>) : AbstractBehaviorNode() {
|
class SequenceNode(val children: ImmutableList<AbstractBehaviorNode>, val isSelector: Boolean) : AbstractBehaviorNode() {
|
||||||
private var index = 0
|
private var index = 0
|
||||||
|
|
||||||
override fun run(delta: Double, state: BehaviorState): Status {
|
override fun run(delta: Double, state: BehaviorState): Status {
|
||||||
|
calls++
|
||||||
|
|
||||||
while (index < children.size) {
|
while (index < children.size) {
|
||||||
val child = children[index]
|
val child = children[index]
|
||||||
val status = child.runAndReset(delta, state)
|
val status = child.runAndReset(delta, state)
|
||||||
|
|
||||||
if (status == Status.FAILURE || status == Status.RUNNING)
|
if ((isSelector && status == Status.SUCCESS || !isSelector && status == Status.FAILURE) || status == Status.RUNNING)
|
||||||
return status
|
return status
|
||||||
|
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status.SUCCESS
|
return if (isSelector) Status.FAILURE else Status.SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "SequenceNode[${children.size}, index=$index, current=${children.getOrNull(index)}]"
|
if (isSelector)
|
||||||
|
return "SelectorNode[$calls / ${children.size}, index=$index, current=${children.getOrNull(index)}]"
|
||||||
|
else
|
||||||
|
return "SequenceNode[$calls / ${children.size}, index=$index, current=${children.getOrNull(index)}]"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reset() {
|
override fun reset() {
|
||||||
|
Loading…
Reference in New Issue
Block a user