recoil on attack block
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

Fix wrong branch commit
This commit is contained in:
railgun 2024-09-09 17:11:12 -04:00
commit 79688e8575
18 changed files with 345 additions and 68 deletions

View File

@ -477,6 +477,14 @@
"audioData" : { "audioData" : {
"audioPath" : "Audio/weapons/swoosh-03.ogg" "audioPath" : "Audio/weapons/swoosh-03.ogg"
} }
},
"blockRecoilState" : {
"animation" : {
"nameFirstPerson" : "SwordR2HSlash1Recoil",
"nameThirdPerson" : "SwordR2HSlash1Recoil",
"priorityCategory" : "MOVEMENT_MODIFIER",
"boneGroups" : ["armLeft", "armRight", "handLeft", "handRight"]
}
} }
}, },
{ {

View File

@ -703,6 +703,10 @@ par_shapes integration
Directed graph datastructure Directed graph datastructure
Framebuffer + RenderingEngine tests Framebuffer + RenderingEngine tests
(09/09/2024)
Fix obnoxious opengl state caching bug w/ framebuffers in junit context
Recoil on attack block
# TODO # TODO

View File

@ -1,6 +1,5 @@
package electrosphere.engine; package electrosphere.engine;
import static org.lwjgl.glfw.GLFW.glfwTerminate;
import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose; import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -16,7 +15,6 @@ import electrosphere.controls.ControlHandler.ControlsState;
import electrosphere.engine.cli.CLIParser; import electrosphere.engine.cli.CLIParser;
import electrosphere.engine.loadingthreads.LoadingThread; import electrosphere.engine.loadingthreads.LoadingThread;
import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType; import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType;
import electrosphere.engine.threads.LabeledThread.ThreadLabel;
import electrosphere.engine.time.Timekeeper; import electrosphere.engine.time.Timekeeper;
import electrosphere.game.server.world.MacroData; import electrosphere.game.server.world.MacroData;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;

View File

@ -29,28 +29,29 @@ import java.util.List;
import org.joml.Vector3d; import org.joml.Vector3d;
@SynchronizedBehaviorTree(name = "clientAttackTree", isServer = false, correspondingTree="serverAttackTree")
/** /**
* Client basic attack tree * Client basic attack tree
*/ */
@SynchronizedBehaviorTree(name = "clientAttackTree", isServer = false, correspondingTree="serverAttackTree")
public class ClientAttackTree implements BehaviorTree { public class ClientAttackTree implements BehaviorTree {
@SynchronizableEnum
/** /**
* States available to the attack tree * States available to the attack tree
*/ */
@SynchronizableEnum
public static enum AttackTreeState { public static enum AttackTreeState {
WINDUP, WINDUP,
HOLD, HOLD,
ATTACK, ATTACK,
BLOCK_RECOIL,
COOLDOWN, COOLDOWN,
IDLE, IDLE,
} }
@SynchronizableEnum
/** /**
* The state of drifting forward during the attack * The state of drifting forward during the attack
*/ */
@SynchronizableEnum
public static enum AttackTreeDriftState { public static enum AttackTreeDriftState {
DRIFT, DRIFT,
NO_DRIFT, NO_DRIFT,
@ -177,6 +178,32 @@ public class ClientAttackTree implements BehaviorTree {
}, },
false false
), ),
StateTransitionUtilItem.create(
AttackTreeState.BLOCK_RECOIL,
() -> {
TreeDataState state = null;
if(currentMove != null){
state = currentMove.getBlockRecoilState();
}
if(state == null){
return null;
} else {
return state.getAnimation();
}
},
() -> {
TreeDataState state = null;
if(currentMove != null){
state = currentMove.getBlockRecoilState();
}
if(state == null){
return null;
} else {
return state.getAudioData();
}
},
false
),
StateTransitionUtilItem.create( StateTransitionUtilItem.create(
AttackTreeState.COOLDOWN, AttackTreeState.COOLDOWN,
() -> { () -> {
@ -320,6 +347,19 @@ public class ClientAttackTree implements BehaviorTree {
} }
} }
} break; } break;
case BLOCK_RECOIL: {
this.stateTransitionUtil.simulate(AttackTreeState.BLOCK_RECOIL);
//activate hitboxes
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
if(attachedEntities != null){
for(Entity currentAttached : attachedEntities){
if(HitboxCollectionState.hasHitboxState(currentAttached)){
HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached);
currentState.setActive(false);
}
}
}
} break;
case COOLDOWN: { case COOLDOWN: {
this.stateTransitionUtil.simulate(AttackTreeState.COOLDOWN); this.stateTransitionUtil.simulate(AttackTreeState.COOLDOWN);
//deactive hitboxes //deactive hitboxes
@ -535,10 +575,12 @@ public class ClientAttackTree implements BehaviorTree {
return 1; return 1;
case ATTACK: case ATTACK:
return 2; return 2;
case COOLDOWN: case BLOCK_RECOIL:
return 3; return 3;
case IDLE: case COOLDOWN:
return 4; return 4;
case IDLE:
return 5;
default: default:
return 0; return 0;
} }
@ -560,8 +602,10 @@ public class ClientAttackTree implements BehaviorTree {
case 2: case 2:
return AttackTreeState.ATTACK; return AttackTreeState.ATTACK;
case 3: case 3:
return AttackTreeState.COOLDOWN; return AttackTreeState.BLOCK_RECOIL;
case 4: case 4:
return AttackTreeState.COOLDOWN;
case 5:
return AttackTreeState.IDLE; return AttackTreeState.IDLE;
default: default:
return AttackTreeState.WINDUP; return AttackTreeState.WINDUP;
@ -632,6 +676,9 @@ public class ClientAttackTree implements BehaviorTree {
*/ */
public void transitionState(AttackTreeState newState){ public void transitionState(AttackTreeState newState){
this.stateTransitionUtil.reset(); this.stateTransitionUtil.reset();
if(newState == AttackTreeState.BLOCK_RECOIL){
this.stateTransitionUtil.interrupt(AttackTreeState.ATTACK);
}
this.setState(newState); this.setState(newState);
} }

View File

@ -45,18 +45,18 @@ import org.joml.Quaterniond;
import org.joml.Vector3d; import org.joml.Vector3d;
import org.joml.Vector3f; import org.joml.Vector3f;
@SynchronizedBehaviorTree(name = "serverAttackTree", isServer = true, correspondingTree="clientAttackTree")
/** /**
* Server basic attack tree * Server basic attack tree
*/ */
@SynchronizedBehaviorTree(name = "serverAttackTree", isServer = true, correspondingTree="clientAttackTree")
public class ServerAttackTree implements BehaviorTree { public class ServerAttackTree implements BehaviorTree {
@SyncedField(serverSendTransitionPacket = true)
//the state of the attack tree //the state of the attack tree
@SyncedField(serverSendTransitionPacket = true)
AttackTreeState state; AttackTreeState state;
@SyncedField
//the state of drifting caused by the attack animation //the state of drifting caused by the attack animation
@SyncedField
AttackTreeDriftState driftState; AttackTreeDriftState driftState;
Entity parent; Entity parent;
@ -91,6 +91,11 @@ public class ServerAttackTree implements BehaviorTree {
//The state transition util //The state transition util
StateTransitionUtil stateTransitionUtil; StateTransitionUtil stateTransitionUtil;
/**
* Private constructor
* @param e The parent entity
* @param params The data to construct the tree with
*/
private ServerAttackTree(Entity e, Object ... params){ private ServerAttackTree(Entity e, Object ... params){
state = AttackTreeState.IDLE; state = AttackTreeState.IDLE;
driftState = AttackTreeDriftState.NO_DRIFT; driftState = AttackTreeDriftState.NO_DRIFT;
@ -126,11 +131,10 @@ public class ServerAttackTree implements BehaviorTree {
StateTransitionUtilItem.create( StateTransitionUtilItem.create(
AttackTreeState.HOLD, AttackTreeState.HOLD,
() -> { () -> {
TreeDataState state = currentMove.getHoldState(); if(currentMove != null && currentMove.getHoldState() == null){
if(state == null){
return null; return null;
} else { } else {
return state.getAnimation(); return currentMove.getHoldState().getAnimation();
} }
}, },
() -> { () -> {
@ -159,6 +163,21 @@ public class ServerAttackTree implements BehaviorTree {
this.setState(AttackTreeState.COOLDOWN); this.setState(AttackTreeState.COOLDOWN);
} }
), ),
StateTransitionUtilItem.create(
AttackTreeState.BLOCK_RECOIL,
() -> {
if(currentMove != null && currentMove.getBlockRecoilState() != null){
return currentMove.getBlockRecoilState().getAnimation();
} else {
return null;
}
},
null,
() -> {
this.stateTransitionUtil.interrupt(AttackTreeState.BLOCK_RECOIL);
this.setState(AttackTreeState.COOLDOWN);
}
),
StateTransitionUtilItem.create( StateTransitionUtilItem.create(
AttackTreeState.COOLDOWN, AttackTreeState.COOLDOWN,
() -> { () -> {
@ -188,6 +207,9 @@ public class ServerAttackTree implements BehaviorTree {
return state; return state;
} }
/**
* Starts an attack
*/
public void start(){ public void start(){
currentMoveCanHold = false; currentMoveCanHold = false;
currentMoveHasWindup = false; currentMoveHasWindup = false;
@ -260,6 +282,23 @@ public class ServerAttackTree implements BehaviorTree {
} }
} }
/**
* Causes the attack tree to instead enter recoil state
*/
public void recoilFromBlock(){
if(currentMove != null){
setState(AttackTreeState.BLOCK_RECOIL);
//deactivate hitboxes
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
for(Entity currentAttached : attachedEntities){
if(HitboxCollectionState.hasHitboxState(currentAttached)){
HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached);
currentState.setActive(false);
}
}
}
}
@Override @Override
public void simulate(float deltaTime){ public void simulate(float deltaTime){
frameCurrent = frameCurrent + (float)Globals.timekeeper.getDeltaFrames(); frameCurrent = frameCurrent + (float)Globals.timekeeper.getDeltaFrames();
@ -365,6 +404,17 @@ public class ServerAttackTree implements BehaviorTree {
projectileToFire = null; projectileToFire = null;
} }
} break; } break;
case BLOCK_RECOIL: {
this.stateTransitionUtil.simulate(AttackTreeState.BLOCK_RECOIL);
//activate hitboxes
List<Entity> attachedEntities = AttachUtils.getChildrenList(parent);
for(Entity currentAttached : attachedEntities){
if(HitboxCollectionState.hasHitboxState(currentAttached)){
HitboxCollectionState currentState = HitboxCollectionState.getHitboxState(currentAttached);
currentState.setActive(false);
}
}
} break;
case COOLDOWN: { case COOLDOWN: {
this.stateTransitionUtil.simulate(AttackTreeState.COOLDOWN); this.stateTransitionUtil.simulate(AttackTreeState.COOLDOWN);
//deactive hitboxes //deactive hitboxes

View File

@ -19,6 +19,7 @@ public class AttackMove {
TreeDataState windupState; TreeDataState windupState;
TreeDataState holdState; TreeDataState holdState;
TreeDataState attackState; TreeDataState attackState;
TreeDataState blockRecoilState;
TreeDataState cooldownState; TreeDataState cooldownState;
/* /*
@ -85,6 +86,14 @@ public class AttackMove {
return attackState; return attackState;
} }
/**
* Gets the state to play for the recoil
* @return the state data
*/
public TreeDataState getBlockRecoilState() {
return blockRecoilState;
}
/** /**
* Gets the state to play for the cooldown * Gets the state to play for the cooldown
* @return the state data * @return the state data

View File

@ -39,7 +39,6 @@ import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL45; import org.lwjgl.opengl.GL45;
import org.lwjgl.opengl.GLCapabilities;
import org.lwjgl.opengl.GLDebugMessageCallback; import org.lwjgl.opengl.GLDebugMessageCallback;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryStack;
@ -271,7 +270,7 @@ public class RenderingEngine {
// setTitleBarDimensions(); // setTitleBarDimensions();
//Creates the OpenGL capabilities for the program.) //Creates the OpenGL capabilities for the program.)
GLCapabilities glCapabilities = GL.createCapabilities(); GL.createCapabilities();
GL45.glEnable(GL45.GL_DEBUG_OUTPUT); GL45.glEnable(GL45.GL_DEBUG_OUTPUT);
//register error callback //register error callback

View File

@ -77,12 +77,24 @@ public class Actor {
//Controls whether the actor should obey frustum culling //Controls whether the actor should obey frustum culling
boolean frustumCull = true; boolean frustumCull = true;
/**
* Used for caching animation masks that should be removed
*/
List<ActorAnimationMask> toRemoveMasks = new LinkedList<ActorAnimationMask>();
/**
* Creates an achor
* @param modelPath The path of the model associated with the actor
*/
public Actor(String modelPath){ public Actor(String modelPath){
this.modelPath = modelPath; this.modelPath = modelPath;
} }
List<ActorAnimationMask> toRemoveMasks = new LinkedList<ActorAnimationMask>(); /**
* Increments the animation time of the actor
* @param deltaTime The amount of time to increment by
*/
public void incrementAnimationTime(double deltaTime){ public void incrementAnimationTime(double deltaTime){
toRemoveMasks.clear(); toRemoveMasks.clear();
for(ActorAnimationMask mask : animationQueue){ for(ActorAnimationMask mask : animationQueue){

View File

@ -15,22 +15,57 @@ import electrosphere.logger.LoggerInterface;
*/ */
public class AnimChannel { public class AnimChannel {
/**
* The current time of the channel
*/
double timeCurrent = 0; double timeCurrent = 0;
/**
* The total time of the channel
*/
double timeTotal; double timeTotal;
/**
* The ticks per second of the channel
*/
double ticksPerSecond; double ticksPerSecond;
/**
* The bone id associated with the channel
*/
String nodeID; String nodeID;
/**
* The starting position of the bone
*/
Vector3f startingPosition; Vector3f startingPosition;
/**
* All position frames
*/
TreeMap<Double,Keyframe> positionFrameTree; TreeMap<Double,Keyframe> positionFrameTree;
/**
* The starting rotation of the bone
*/
Quaterniond startingRotation; Quaterniond startingRotation;
/**
* All rotation frames
*/
TreeMap<Double,Keyframe> rotationFrameTree; TreeMap<Double,Keyframe> rotationFrameTree;
/**
* All scale frames
*/
TreeMap<Double,Keyframe> scaleFrameTree; TreeMap<Double,Keyframe> scaleFrameTree;
/**
* Creates an anim channel
* @param maxTime The max time of the channel
* @param ticksPerSecond The ticks per second
*/
public AnimChannel(double maxTime, double ticksPerSecond){ public AnimChannel(double maxTime, double ticksPerSecond){
timeTotal = maxTime; timeTotal = maxTime;
this.ticksPerSecond = ticksPerSecond; this.ticksPerSecond = ticksPerSecond;
@ -269,43 +304,60 @@ public class AnimChannel {
return rVal; return rVal;
} }
/**
* Increments time on the channel
* @param incrementValue The amount to increment by
*/
public void incrementTime(double incrementValue){ public void incrementTime(double incrementValue){
timeCurrent = timeCurrent + incrementValue; timeCurrent = timeCurrent + incrementValue;
} }
/**
* Sets the current time of the channel
* @param time The time
*/
public void setTime(double time){ public void setTime(double time){
this.timeCurrent = time; this.timeCurrent = time;
} }
/**
* Rewinds the channel
*/
public void rewind(){ public void rewind(){
timeCurrent = 0; timeCurrent = 0;
} }
/**
* Describes the channel at a high level
*/
public void describeChannel(){ public void describeChannel(){
System.out.println("Target object: " + nodeID); LoggerInterface.loggerEngine.INFO("Target object: " + nodeID);
System.out.println("Time: " + timeCurrent + "/" + timeTotal); LoggerInterface.loggerEngine.INFO("Time: " + timeCurrent + "/" + timeTotal);
System.out.println(positionFrameTree.size() + " position Frames"); LoggerInterface.loggerEngine.INFO(positionFrameTree.size() + " position Frames");
System.out.println(rotationFrameTree.size() + " rotation Frames"); LoggerInterface.loggerEngine.INFO(rotationFrameTree.size() + " rotation Frames");
System.out.println(scaleFrameTree.size() + " scale Frames"); LoggerInterface.loggerEngine.INFO(scaleFrameTree.size() + " scale Frames");
} }
/**
* Fully describes the channel
*/
public void fullDescribeChannel(){ public void fullDescribeChannel(){
System.out.println("Target object: " + nodeID); LoggerInterface.loggerEngine.INFO("Target object: " + nodeID);
System.out.println("Time: " + timeCurrent + "/" + timeTotal); LoggerInterface.loggerEngine.INFO("Time: " + timeCurrent + "/" + timeTotal);
System.out.println(positionFrameTree.size() + " position Frames"); LoggerInterface.loggerEngine.INFO(positionFrameTree.size() + " position Frames");
Iterator<Map.Entry<Double,Keyframe>> frameIterator = positionFrameTree.entrySet().iterator(); Iterator<Map.Entry<Double,Keyframe>> frameIterator = positionFrameTree.entrySet().iterator();
while(frameIterator.hasNext()){ while(frameIterator.hasNext()){
System.out.println(frameIterator.next()); LoggerInterface.loggerEngine.INFO(frameIterator.next() + "");
} }
System.out.println(rotationFrameTree.size() + " rotation Frames"); LoggerInterface.loggerEngine.INFO(rotationFrameTree.size() + " rotation Frames");
frameIterator = rotationFrameTree.entrySet().iterator(); frameIterator = rotationFrameTree.entrySet().iterator();
while(frameIterator.hasNext()){ while(frameIterator.hasNext()){
System.out.println(frameIterator.next()); LoggerInterface.loggerEngine.INFO(frameIterator.next() + "");
} }
System.out.println(scaleFrameTree.size() + " scale Frames"); LoggerInterface.loggerEngine.INFO(scaleFrameTree.size() + " scale Frames");
frameIterator = scaleFrameTree.entrySet().iterator(); frameIterator = scaleFrameTree.entrySet().iterator();
while(frameIterator.hasNext()){ while(frameIterator.hasNext()){
System.out.println(frameIterator.next()); LoggerInterface.loggerEngine.INFO(frameIterator.next() + "");
} }
} }
@ -363,18 +415,37 @@ public class AnimChannel {
} }
} }
/**
* Gets the name of the bone associated with the channel
* @return The name of the bone
*/
public String getNodeID(){ public String getNodeID(){
return nodeID; return nodeID;
} }
/**
* Adds a position frame to the channel
* @param time The time the frame occurs at
* @param frame The frame itself
*/
public void addPositionFrame(double time, Keyframe frame){ public void addPositionFrame(double time, Keyframe frame){
positionFrameTree.put(time, frame); positionFrameTree.put(time, frame);
} }
/**
* Adds a rotation frame to the channel
* @param time The time the frame occurs at
* @param frame The frame itself
*/
public void addRotationFrame(double time, Keyframe frame){ public void addRotationFrame(double time, Keyframe frame){
rotationFrameTree.put(time, frame); rotationFrameTree.put(time, frame);
} }
/**
* Adds a scale frame to the channel
* @param time The time the frame occurs at
* @param frame The frame itself
*/
public void addScaleFrame(double time, Keyframe frame){ public void addScaleFrame(double time, Keyframe frame){
scaleFrameTree.put(time, frame); scaleFrameTree.put(time, frame);
} }

View File

@ -9,7 +9,6 @@ import org.joml.Quaterniond;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.joml.Vector4d; import org.joml.Vector4d;
import org.lwjgl.assimp.AIAnimation; import org.lwjgl.assimp.AIAnimation;
import org.lwjgl.assimp.AIMeshAnim;
import org.lwjgl.assimp.AINodeAnim; import org.lwjgl.assimp.AINodeAnim;
import org.lwjgl.assimp.AIQuatKey; import org.lwjgl.assimp.AIQuatKey;
import org.lwjgl.assimp.AIVectorKey; import org.lwjgl.assimp.AIVectorKey;
@ -17,11 +16,11 @@ import org.lwjgl.assimp.AIVectorKey;
import electrosphere.logger.LoggerInterface; import electrosphere.logger.LoggerInterface;
/** /**
* * An animation on a model
* @author satellite
*/ */
public class Animation { public class Animation {
//common animations
public static final String ANIMATION_MOVEMENT_STARTUP = "WalkStart"; public static final String ANIMATION_MOVEMENT_STARTUP = "WalkStart";
public static final String ANIMATION_MOVEMENT_MOVE = "Walk"; public static final String ANIMATION_MOVEMENT_MOVE = "Walk";
public static final String ANIMATION_IDLE_1 = "Idle1"; public static final String ANIMATION_IDLE_1 = "Idle1";
@ -34,19 +33,46 @@ public class Animation {
/**
* The anim data associated with the animation
*/
AIAnimation animData; AIAnimation animData;
/**
* The name of the animation
*/
public String name; public String name;
public int ID;
ArrayList<AINodeAnim> nodeChannelData; /**
ArrayList<AIMeshAnim> meshChannelData; * The channels that contain the animation data
*/
public ArrayList<AnimChannel> channels; public ArrayList<AnimChannel> channels;
/**
* The duration of the animation
*/
public double duration = 0; public double duration = 0;
/**
* The current time of the animation
*/
public double timeCurrent = 0; public double timeCurrent = 0;
/**
* The ticks per second of animation
*/
public double ticksPerSecond; public double ticksPerSecond;
/**
* The map of bone name to animation channel
*/
Map<String, AnimChannel> channelMap; Map<String, AnimChannel> channelMap;
public Animation(AIAnimation animData, int ID){ /**
* Creates an animation
* @param animData The data for the animation
*/
public Animation(AIAnimation animData){
// //
//Create structures //Create structures
// //
@ -59,16 +85,6 @@ public class Animation {
name = animData.mName().dataString(); name = animData.mName().dataString();
this.ticksPerSecond = animData.mTicksPerSecond(); this.ticksPerSecond = animData.mTicksPerSecond();
this.duration = animData.mDuration() / this.ticksPerSecond; this.duration = animData.mDuration() / this.ticksPerSecond;
this.ID = ID;
//
//Print metadata
//
// System.out.println("Animation name: \"" + name + "\"");
// System.out.println("ID:(" + ID + ")");
// System.out.println("Ticks per second: " + ticksPerSecond);
// System.out.println("Anim sizeof: " + animData.sizeof());
// System.out.println("Duration: " + duration);
// //
//Read in anim channels (bone modifications) //Read in anim channels (bone modifications)
@ -200,14 +216,14 @@ public class Animation {
} }
} }
//gotta free things
nodeChannelData = null;
meshChannelData = null;
} }
/**
* Describes the animation at high level
*/
public void describeAnimation(){ public void describeAnimation(){
LoggerInterface.loggerRenderer.DEBUG("====================="); LoggerInterface.loggerRenderer.DEBUG("=====================");
LoggerInterface.loggerRenderer.DEBUG("Name: \"" + name + "\""); LoggerInterface.loggerRenderer.DEBUG("Name: \"" + name + "\"");
LoggerInterface.loggerRenderer.DEBUG("ID: " + ID);
LoggerInterface.loggerRenderer.DEBUG("Duration: " + duration); LoggerInterface.loggerRenderer.DEBUG("Duration: " + duration);
LoggerInterface.loggerRenderer.DEBUG("Ticks per second: " + ticksPerSecond); LoggerInterface.loggerRenderer.DEBUG("Ticks per second: " + ticksPerSecond);
Iterator<AnimChannel> channelIterator = channels.iterator(); Iterator<AnimChannel> channelIterator = channels.iterator();
@ -218,10 +234,13 @@ public class Animation {
} }
LoggerInterface.loggerRenderer.DEBUG("====================="); LoggerInterface.loggerRenderer.DEBUG("=====================");
} }
/**
* Describes the animation is as much detail as possible
*/
public void fullDescribeAnimation(){ public void fullDescribeAnimation(){
LoggerInterface.loggerRenderer.DEBUG("====================="); LoggerInterface.loggerRenderer.DEBUG("=====================");
LoggerInterface.loggerRenderer.DEBUG("Name: " + name); LoggerInterface.loggerRenderer.DEBUG("Name: " + name);
LoggerInterface.loggerRenderer.DEBUG("ID: " + ID);
LoggerInterface.loggerRenderer.DEBUG("Duration: " + duration); LoggerInterface.loggerRenderer.DEBUG("Duration: " + duration);
LoggerInterface.loggerRenderer.DEBUG("Ticks per second: " + ticksPerSecond); LoggerInterface.loggerRenderer.DEBUG("Ticks per second: " + ticksPerSecond);
Iterator<AnimChannel> channelIterator = channels.iterator(); Iterator<AnimChannel> channelIterator = channels.iterator();
@ -233,19 +252,33 @@ public class Animation {
LoggerInterface.loggerRenderer.DEBUG("====================="); LoggerInterface.loggerRenderer.DEBUG("=====================");
} }
/**
* Increments time on the animation
* @param time The amount of time to increment by
* @return true if the animation has completed, false otherwise
*/
public boolean incrementTime(double time){ public boolean incrementTime(double time){
timeCurrent += time; timeCurrent += time;
if(timeCurrent > duration){ if(timeCurrent > duration || timeCurrent < 0){
return true; return true;
} else { } else {
return false; return false;
} }
} }
/**
* Sets the time of the animation
* @param time The time
*/
public void setTime(double time){ public void setTime(double time){
timeCurrent = time; timeCurrent = time;
} }
/**
* Gets the channel data for a given bone
* @param name The name of the bone
* @return The channel data if it exists, null otherwise
*/
public AnimChannel getChannel(String name){ public AnimChannel getChannel(String name){
return channelMap.get(name); return channelMap.get(name);
} }

View File

@ -7,11 +7,31 @@ import org.joml.Vector3f;
* A single keyframe of a single node within an animation * A single keyframe of a single node within an animation
*/ */
public class Keyframe implements Comparable<Keyframe>{ public class Keyframe implements Comparable<Keyframe>{
/**
* The time the keyframe occurs at
*/
double time; double time;
/**
* The position of the keyframe
*/
Vector3f position; Vector3f position;
/**
* The rotation of the keyframe
*/
Quaterniond rotation; Quaterniond rotation;
/**
* The scale of the keyframe
*/
Vector3f scale; Vector3f scale;
/**
* Creates a keyframe
* @param time The time the keyframe occurs at
*/
public Keyframe(double time){ public Keyframe(double time){
this.time = time; this.time = time;
} }
@ -27,6 +47,10 @@ public class Keyframe implements Comparable<Keyframe>{
} }
} }
/**
* Gets the time of the keyframe
* @return The time
*/
public double getTime(){ public double getTime(){
return time; return time;
} }

View File

@ -187,7 +187,7 @@ public class Model {
rVal.animations = new ArrayList<Animation>(); rVal.animations = new ArrayList<Animation>();
rVal.animMap = new HashMap<String,Animation>(); rVal.animMap = new HashMap<String,Animation>();
for(int i = 0; i < animCount; i++){ for(int i = 0; i < animCount; i++){
Animation newAnim = new Animation(AIAnimation.create(animBuffer.get(i)), i); Animation newAnim = new Animation(AIAnimation.create(animBuffer.get(i)));
rVal.animations.add(newAnim); rVal.animations.add(newAnim);
rVal.animMap.put(newAnim.name,newAnim); rVal.animMap.put(newAnim.name,newAnim);
} }

View File

@ -168,7 +168,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
// //
//handle attacker //handle attacker
this.handleAttackerCollision(impactorEntity,receiverEntity); this.handleAttackerCollision(impactorEntity,receiverEntity, isDamageEvent);
} }
if(isBlockEvent){ if(isBlockEvent){
@ -192,7 +192,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
// //
//handle attacker //handle attacker
this.handleAttackerCollision(impactorEntity,receiverEntity); this.handleAttackerCollision(impactorEntity,receiverEntity, isBlockEvent);
} }
} }
@ -200,8 +200,9 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
* Handles collision tracking from the impactor's side * Handles collision tracking from the impactor's side
* @param impactorEntity The impactor hitbox's parent entity * @param impactorEntity The impactor hitbox's parent entity
* @param receiverParent The receiver hitbox's parent entity * @param receiverParent The receiver hitbox's parent entity
* @param isBlock true if this is a block, false otherwise
*/ */
private void handleAttackerCollision(Entity impactorEntity, Entity receiverEntity){ private void handleAttackerCollision(Entity impactorEntity, Entity receiverEntity, boolean isBlock){
boolean receiverIsItem = ItemUtils.isItem(receiverEntity); boolean receiverIsItem = ItemUtils.isItem(receiverEntity);
boolean receiverHasParent = AttachUtils.hasParent(receiverEntity); boolean receiverHasParent = AttachUtils.hasParent(receiverEntity);
@ -210,6 +211,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
if(impactorEntity != null && ServerAttackTree.getServerAttackTree(impactorEntity) != null){ if(impactorEntity != null && ServerAttackTree.getServerAttackTree(impactorEntity) != null){
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(impactorEntity); ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(impactorEntity);
impactorAttackTree.collideEntity(receiverEntity); impactorAttackTree.collideEntity(receiverEntity);
impactorAttackTree.recoilFromBlock();
//if the receiver is an item that is equipped, collide with parent too //if the receiver is an item that is equipped, collide with parent too
if(receiverIsItem && receiverHasParent){ if(receiverIsItem && receiverHasParent){
impactorAttackTree.collideEntity(AttachUtils.getParent(receiverEntity)); impactorAttackTree.collideEntity(AttachUtils.getParent(receiverEntity));
@ -222,6 +224,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
} else if(impactorEntity != null && AttachUtils.hasParent(impactorEntity) && AttachUtils.getParent(impactorEntity) != null && ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorEntity)) != null){ } else if(impactorEntity != null && AttachUtils.hasParent(impactorEntity) && AttachUtils.getParent(impactorEntity) != null && ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorEntity)) != null){
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorEntity)); ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorEntity));
impactorAttackTree.collideEntity(receiverEntity); impactorAttackTree.collideEntity(receiverEntity);
impactorAttackTree.recoilFromBlock();
//if the receiver is an item that is equipped, collide with parent too //if the receiver is an item that is equipped, collide with parent too
if(receiverIsItem && receiverHasParent){ if(receiverIsItem && receiverHasParent){
impactorAttackTree.collideEntity(AttachUtils.getParent(receiverEntity)); impactorAttackTree.collideEntity(AttachUtils.getParent(receiverEntity));

View File

@ -29,17 +29,34 @@ import electrosphere.renderer.model.Bone;
*/ */
public class PoseActor { public class PoseActor {
/**
* The path of the model for the pose actor
*/
String modelPath; String modelPath;
//scalar on the speed of animation playback
/**
* Scalar on the speed of animation playback
*/
float animationScalar = 1.0f; float animationScalar = 1.0f;
//priority queue of animations to play. Allows masking a higher priority animation over a lower priority one.
/**
* Priority queue of animations to play. Allows masking a higher priority animation over a lower priority one.
*/
Set<ActorAnimationMask> animationQueue = new TreeSet<ActorAnimationMask>(); Set<ActorAnimationMask> animationQueue = new TreeSet<ActorAnimationMask>();
//bone rotation map. Used to apply rotator functionality to bones (think hair, cloth, and camera rotation on looking)
/**
* Bone rotation map. Used to apply rotator functionality to bones (think hair, cloth, and camera rotation on looking)
*/
Map<String,ActorBoneRotator> boneRotators = new HashMap<String,ActorBoneRotator>(); Map<String,ActorBoneRotator> boneRotators = new HashMap<String,ActorBoneRotator>();
//static morph used to apply an initial, static modification to the layout of bones in the pose model
/**
* Static morph used to apply an initial, static modification to the layout of bones in the pose model
*/
ActorStaticMorph staticMorph; ActorStaticMorph staticMorph;
//The bone groups for this pose actor /**
* The bone groups for this pose actor
*/
List<BoneGroup> boneGroups; List<BoneGroup> boneGroups;
@ -55,6 +72,7 @@ public class PoseActor {
//Used to keep track of which animations have completed and therefore should be removed //Used to keep track of which animations have completed and therefore should be removed
//Separate variable so no concurrent modification to anim lists/maps //Separate variable so no concurrent modification to anim lists/maps
List<ActorAnimationMask> toRemoveMasks = new LinkedList<ActorAnimationMask>(); List<ActorAnimationMask> toRemoveMasks = new LinkedList<ActorAnimationMask>();
/** /**
* Increments time of all currently played animations * Increments time of all currently played animations
* @param deltaTime * @param deltaTime

View File

@ -1,9 +1,10 @@
package electrosphere.server.poseactor; package electrosphere.server.poseactor;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
/**
* Utilities for working with pose actors
*/
public class PoseActorUtils { public class PoseActorUtils {
/** /**

View File

@ -98,7 +98,7 @@ public class PoseModel {
animations = new ArrayList<Animation>(); animations = new ArrayList<Animation>();
animMap = new HashMap<String,Animation>(); animMap = new HashMap<String,Animation>();
for(int i = 0; i < animCount; i++){ for(int i = 0; i < animCount; i++){
Animation newAnim = new Animation(AIAnimation.create(animBuffer.get(i)), i); Animation newAnim = new Animation(AIAnimation.create(animBuffer.get(i)));
animations.add(newAnim); animations.add(newAnim);
animMap.put(newAnim.name,newAnim); animMap.put(newAnim.name,newAnim);
} }