initial hitstun implementation
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
b8a0db5974
commit
3d6b71bf01
@ -469,6 +469,7 @@
|
||||
"driftFrameStart" : 1,
|
||||
"driftFrameEnd" : 10,
|
||||
"initialMove" : true,
|
||||
"hitstun" : 7,
|
||||
"attackState" : {
|
||||
"animation" : {
|
||||
"nameFirstPerson" : "SwordR2HSlash",
|
||||
|
||||
@ -353,6 +353,7 @@
|
||||
"driftFrameStart" : 1,
|
||||
"driftFrameEnd" : 10,
|
||||
"initialMove" : true,
|
||||
"hitstun" : 7,
|
||||
"attackState" : {
|
||||
"animation" : {
|
||||
"nameFirstPerson" : "SwordR2HSlash1",
|
||||
|
||||
@ -125,7 +125,7 @@
|
||||
"offsetY" : 0.0,
|
||||
"offsetZ" : 0.0
|
||||
},
|
||||
"iconPath" : "Textures/icons/itemIconWeapon.png"
|
||||
"iconPath" : "Textures/icons/greatsword.png"
|
||||
},
|
||||
{
|
||||
"id" : "bow1",
|
||||
|
||||
BIN
assets/Textures/icons/greatsword.png
Normal file
BIN
assets/Textures/icons/greatsword.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
@ -16,14 +16,21 @@
|
||||
Ticketed randomizer node for BTs to more heavily weight attacking and waiting
|
||||
|
||||
+ feedback driven requirements
|
||||
UI spacing and scaling
|
||||
Come up with a title for the game and create a title menu for it (ideally with some animation and music)
|
||||
Better skybox
|
||||
Model clothing, hair for the human
|
||||
Hitstun, particles, light on sword collision
|
||||
Idle viewmodel does not show hands
|
||||
Add punching/unarmed combat
|
||||
UI spacing and scaling
|
||||
Better skybox
|
||||
- Fix transparency calculations for far-out objects
|
||||
Crouching
|
||||
Model clothing, hair for the human
|
||||
particles, light on sword collision
|
||||
- Requires particle manager overhaul
|
||||
Come up with a title for the game and create a title menu for it (ideally with some animation and music)
|
||||
- Flames moving up the screen
|
||||
- Requires particle manager overhaul
|
||||
- Requires actor panel that can play scenes
|
||||
- Requires rendering overhaul
|
||||
- Requires finding an sfx for flames
|
||||
Objectives
|
||||
- PVP arena mode initially?
|
||||
- Spawn player at start of a dungeon
|
||||
|
||||
@ -792,6 +792,9 @@ Start proliferating audio through ui
|
||||
Item-based ui audio
|
||||
Better sfx for opening/closing inventory menu
|
||||
Different title menu audio
|
||||
New katana icon
|
||||
UI fix
|
||||
Initial hitstun implementation
|
||||
|
||||
|
||||
# TODO
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
package electrosphere.client.collision;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
import org.ode4j.ode.DContactGeom;
|
||||
import org.ode4j.ode.DGeom;
|
||||
|
||||
import electrosphere.collision.collidable.Collidable;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.state.attach.AttachUtils;
|
||||
import electrosphere.entity.state.attack.ClientAttackTree;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxType;
|
||||
|
||||
public class ClientLocalHitboxCollision {
|
||||
|
||||
/**
|
||||
* Handles a damage collision on the client
|
||||
* @param impactor the entity initiating the collision
|
||||
* @param receiver the entity receiving the collision
|
||||
*/
|
||||
public static void clientDamageHitboxColision(DContactGeom contactGeom, DGeom impactorGeom, DGeom receiverGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude){
|
||||
|
||||
Entity impactorParent = impactor.getParent();
|
||||
Entity receiverParent = receiver.getParent();
|
||||
HitboxCollectionState impactorState = HitboxCollectionState.getHitboxState(impactorParent);
|
||||
HitboxCollectionState receiverState = HitboxCollectionState.getHitboxState(receiverParent);
|
||||
HitboxState impactorShapeStatus = impactorState.getShapeStatus(impactorGeom);
|
||||
HitboxState receiverShapeStatus = receiverState.getShapeStatus(receiverGeom);
|
||||
|
||||
|
||||
//currently, impactor needs to be an item, and the receiver must not be an item
|
||||
boolean isDamageEvent =
|
||||
impactorShapeStatus != null &&
|
||||
receiverShapeStatus != null &&
|
||||
impactorShapeStatus.getType() == HitboxType.HIT &&
|
||||
receiverShapeStatus.getType() == HitboxType.HURT &&
|
||||
AttachUtils.getParent(impactorParent) != receiverParent
|
||||
;
|
||||
|
||||
if(impactorShapeStatus != null){
|
||||
impactorShapeStatus.setHadCollision(true);
|
||||
}
|
||||
if(receiverShapeStatus != null){
|
||||
receiverShapeStatus.setHadCollision(true);
|
||||
}
|
||||
|
||||
if(isDamageEvent){
|
||||
//TODO: client logic for audio etc
|
||||
if(AttachUtils.hasParent(impactorParent)){
|
||||
Entity parent = AttachUtils.getParent(impactorParent);
|
||||
if(ClientAttackTree.getClientAttackTree(parent) != null){
|
||||
ClientAttackTree clientAttackTree = ClientAttackTree.getClientAttackTree(parent);
|
||||
if(clientAttackTree.canCollideEntity(receiverParent)){
|
||||
clientAttackTree.collideEntity(receiverParent);
|
||||
clientAttackTree.freezeFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Entity hitboxParent = (Entity)impactor.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
|
||||
// Entity hurtboxParent = (Entity)receiver.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
|
||||
|
||||
//if the entity is attached to is an item, we need to compare with the parent of the item
|
||||
//to make sure you don't stab yourself for instance
|
||||
// boolean isItem = ItemUtils.isItem(hitboxParent);//hitboxParent.containsKey(EntityDataStrings.ITEM_IS_ITEM);
|
||||
// Entity hitboxAttachParent = AttachUtils.getParent(hitboxParent);
|
||||
|
||||
// if(isItem){
|
||||
// if(hitboxAttachParent != hurtboxParent){
|
||||
// Vector3d hurtboxPos = EntityUtils.getPosition(receiver);
|
||||
// ParticleEffects.spawnBloodsplats(new Vector3f((float)hurtboxPos.x,(float)hurtboxPos.y,(float)hurtboxPos.z).add(0,0.1f,0), 20, 40);
|
||||
// }
|
||||
// } else {
|
||||
|
||||
// //client no longer manages damage; however, keeping this code around for the moment to show how we
|
||||
// //might approach adding client-side effects as soon as impact occurs (ie play a sound, shoot sparks, etc)
|
||||
// //before the server responds with a valid collision event or not
|
||||
|
||||
// // int damage = 0;
|
||||
// // //for entities using attacktree
|
||||
// // if(CreatureUtils.clientGetAttackTree(hitboxParent) != null){
|
||||
// // damage = ItemUtils.getWeaponDataRaw(hitboxParent).getDamage();
|
||||
// // } else {
|
||||
// // //for entities using shooter tree
|
||||
// // if(ProjectileTree.getProjectileTree(hitboxParent) != null){
|
||||
// // damage = (int)ProjectileTree.getProjectileTree(hitboxParent).getDamage();
|
||||
// // }
|
||||
// // }
|
||||
// // LifeUtils.getLifeState(hurtboxParent).damage(damage);
|
||||
// // if(!LifeUtils.getLifeState(hurtboxParent).isIsAlive()){
|
||||
// // EntityUtils.getPosition(hurtboxParent).set(Globals.spawnPoint);
|
||||
// // LifeUtils.getLifeState(hurtboxParent).revive();
|
||||
// // }
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
@ -13,7 +13,7 @@ import electrosphere.logger.LoggerInterface;
|
||||
/**
|
||||
* Client methods for handling hitbox collisions reported by the server
|
||||
*/
|
||||
public class ClientHitboxCollision {
|
||||
public class ClientNetworkHitboxCollision {
|
||||
|
||||
/**
|
||||
* Performs client logic for a collision that the server reports
|
||||
@ -29,11 +29,11 @@ public class ClientHitboxCollision {
|
||||
case HitboxData.HITBOX_TYPE_HURT:
|
||||
case HitboxData.HITBOX_TYPE_HURT_CONNECTED: {
|
||||
Globals.hitboxAudioService.playAudioPositional(senderEntity, receiverEntity, hitboxType, hurtboxType, position);
|
||||
ClientHitboxCollision.conditionallySpawnParticles(senderEntity, receiverEntity, hitboxType, hurtboxType, position);
|
||||
ClientNetworkHitboxCollision.conditionallySpawnParticles(senderEntity, receiverEntity, hitboxType, hurtboxType, position);
|
||||
} break;
|
||||
case HitboxData.HITBOX_TYPE_BLOCK_CONNECTED: {
|
||||
Globals.hitboxAudioService.playAudioPositional(senderEntity, receiverEntity, hitboxType, hurtboxType, position);
|
||||
ClientHitboxCollision.conditionallySpawnParticles(senderEntity, receiverEntity, hitboxType, hurtboxType, position);
|
||||
ClientNetworkHitboxCollision.conditionallySpawnParticles(senderEntity, receiverEntity, hitboxType, hurtboxType, position);
|
||||
} break;
|
||||
default: {
|
||||
LoggerInterface.loggerEngine.WARNING("Client handling undefined hurtbox type: " + hurtboxType);
|
||||
@ -7,11 +7,11 @@ import org.joml.Vector3d;
|
||||
import org.ode4j.ode.DContactGeom;
|
||||
import org.ode4j.ode.DGeom;
|
||||
|
||||
import electrosphere.client.collision.ClientLocalHitboxCollision;
|
||||
import electrosphere.collision.CollisionEngine;
|
||||
import electrosphere.collision.CollisionEngine.CollisionResolutionCallback;
|
||||
import electrosphere.collision.collidable.Collidable;
|
||||
import electrosphere.collision.hitbox.HitboxManager;
|
||||
import electrosphere.collision.hitbox.HitboxUtils;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.scene.Scene;
|
||||
@ -225,7 +225,7 @@ public class ClientSceneWrapper {
|
||||
CollisionResolutionCallback resolutionCallback = new CollisionResolutionCallback() {
|
||||
@Override
|
||||
public void resolve(DContactGeom geom, DGeom impactorGeom, DGeom receiverGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude) {
|
||||
HitboxUtils.clientDamageHitboxColision(geom, impactorGeom, receiverGeom, impactor, receiver, normal, localPosition, worldPos, magnitude);
|
||||
ClientLocalHitboxCollision.clientDamageHitboxColision(geom, impactorGeom, receiverGeom, impactor, receiver, normal, localPosition, worldPos, magnitude);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
package electrosphere.client.ui.menu.ingame;
|
||||
|
||||
import electrosphere.audio.VirtualAudioSourceManager.VirtualAudioSourceType;
|
||||
import electrosphere.client.ui.menu.WindowStrings;
|
||||
import electrosphere.client.ui.menu.WindowUtils;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
import electrosphere.entity.types.item.ItemUtils;
|
||||
import electrosphere.game.data.item.type.Item;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.ui.components.PlayerInventoryWindow;
|
||||
import electrosphere.renderer.ui.elements.Div;
|
||||
@ -23,15 +26,23 @@ public class MenuGeneratorsInventory {
|
||||
if(Globals.draggedItem != null){
|
||||
//drop item
|
||||
InventoryUtils.clientAttemptEjectItem(Globals.playerEntity,Globals.draggedItem);
|
||||
//play sound effect
|
||||
if(Globals.virtualAudioSourceManager != null){
|
||||
Item itemData = Globals.gameConfigCurrent.getItemMap().getItem(ItemUtils.getType(Globals.draggedItem));
|
||||
if(itemData.getItemAudio() != null && itemData.getItemAudio().getUIReleaseAudio() != null){
|
||||
Globals.virtualAudioSourceManager.createVirtualAudioSource(itemData.getItemAudio().getUIReleaseAudio(), VirtualAudioSourceType.UI, false);
|
||||
} else {
|
||||
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventorySlotItem.ogg", VirtualAudioSourceType.UI, false);
|
||||
}
|
||||
}
|
||||
//clear ui
|
||||
WindowUtils.cleanItemDraggingWindow();
|
||||
String sourceWindowId = WindowStrings.WINDOW_CHARACTER;
|
||||
WindowUtils.replaceWindow(sourceWindowId,PlayerInventoryWindow.createPlayerInventoryWindow(Globals.playerEntity));
|
||||
//re-render inventory
|
||||
WindowUtils.replaceWindow(WindowStrings.WINDOW_CHARACTER, PlayerInventoryWindow.createPlayerInventoryWindow(Globals.playerEntity));
|
||||
//null globals
|
||||
Globals.dragSourceInventory = null;
|
||||
Globals.draggedItem = null;
|
||||
return false;
|
||||
// }
|
||||
}
|
||||
return true;
|
||||
}});
|
||||
|
||||
@ -1,96 +1,16 @@
|
||||
package electrosphere.collision.hitbox;
|
||||
|
||||
import electrosphere.collision.collidable.Collidable;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.state.attach.AttachUtils;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxState;
|
||||
import electrosphere.entity.state.hitbox.HitboxCollectionState.HitboxType;
|
||||
import electrosphere.game.data.collidable.HitboxData;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
import org.ode4j.ode.DContactGeom;
|
||||
import org.ode4j.ode.DGeom;
|
||||
|
||||
/**
|
||||
* Utilities for working with hitboxes
|
||||
*/
|
||||
public class HitboxUtils {
|
||||
|
||||
|
||||
/**
|
||||
* Handles a damage collision on the client
|
||||
* @param impactor the entity initiating the collision
|
||||
* @param receiver the entity receiving the collision
|
||||
*/
|
||||
public static void clientDamageHitboxColision(DContactGeom contactGeom, DGeom impactorGeom, DGeom receiverGeom, Collidable impactor, Collidable receiver, Vector3d normal, Vector3d localPosition, Vector3d worldPos, float magnitude){
|
||||
|
||||
Entity impactorParent = impactor.getParent();
|
||||
Entity receiverParent = receiver.getParent();
|
||||
HitboxCollectionState impactorState = HitboxCollectionState.getHitboxState(impactorParent);
|
||||
HitboxCollectionState receiverState = HitboxCollectionState.getHitboxState(receiverParent);
|
||||
HitboxState impactorShapeStatus = impactorState.getShapeStatus(impactorGeom);
|
||||
HitboxState receiverShapeStatus = receiverState.getShapeStatus(receiverGeom);
|
||||
|
||||
|
||||
//currently, impactor needs to be an item, and the receiver must not be an item
|
||||
boolean isDamageEvent =
|
||||
impactorShapeStatus != null &&
|
||||
receiverShapeStatus != null &&
|
||||
impactorShapeStatus.getType() == HitboxType.HIT &&
|
||||
receiverShapeStatus.getType() == HitboxType.HURT &&
|
||||
AttachUtils.getParent(impactorParent) != receiverParent
|
||||
;
|
||||
|
||||
if(impactorShapeStatus != null){
|
||||
impactorShapeStatus.setHadCollision(true);
|
||||
}
|
||||
if(receiverShapeStatus != null){
|
||||
receiverShapeStatus.setHadCollision(true);
|
||||
}
|
||||
|
||||
if(isDamageEvent){
|
||||
//TODO: client logic for audio etc
|
||||
}
|
||||
|
||||
// Entity hitboxParent = (Entity)impactor.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
|
||||
// Entity hurtboxParent = (Entity)receiver.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT);
|
||||
|
||||
//if the entity is attached to is an item, we need to compare with the parent of the item
|
||||
//to make sure you don't stab yourself for instance
|
||||
// boolean isItem = ItemUtils.isItem(hitboxParent);//hitboxParent.containsKey(EntityDataStrings.ITEM_IS_ITEM);
|
||||
// Entity hitboxAttachParent = AttachUtils.getParent(hitboxParent);
|
||||
|
||||
// if(isItem){
|
||||
// if(hitboxAttachParent != hurtboxParent){
|
||||
// Vector3d hurtboxPos = EntityUtils.getPosition(receiver);
|
||||
// ParticleEffects.spawnBloodsplats(new Vector3f((float)hurtboxPos.x,(float)hurtboxPos.y,(float)hurtboxPos.z).add(0,0.1f,0), 20, 40);
|
||||
// }
|
||||
// } else {
|
||||
|
||||
// //client no longer manages damage; however, keeping this code around for the moment to show how we
|
||||
// //might approach adding client-side effects as soon as impact occurs (ie play a sound, shoot sparks, etc)
|
||||
// //before the server responds with a valid collision event or not
|
||||
|
||||
// // int damage = 0;
|
||||
// // //for entities using attacktree
|
||||
// // if(CreatureUtils.clientGetAttackTree(hitboxParent) != null){
|
||||
// // damage = ItemUtils.getWeaponDataRaw(hitboxParent).getDamage();
|
||||
// // } else {
|
||||
// // //for entities using shooter tree
|
||||
// // if(ProjectileTree.getProjectileTree(hitboxParent) != null){
|
||||
// // damage = (int)ProjectileTree.getProjectileTree(hitboxParent).getDamage();
|
||||
// // }
|
||||
// // }
|
||||
// // LifeUtils.getLifeState(hurtboxParent).damage(damage);
|
||||
// // if(!LifeUtils.getLifeState(hurtboxParent).isIsAlive()){
|
||||
// // EntityUtils.getPosition(hurtboxParent).set(Globals.spawnPoint);
|
||||
// // LifeUtils.getLifeState(hurtboxParent).revive();
|
||||
// // }
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data for a hitbox
|
||||
* @param e the entity encapsulating the hitbox
|
||||
|
||||
@ -4,6 +4,7 @@ package electrosphere.entity.state.attack;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.btree.BehaviorTree;
|
||||
import electrosphere.entity.btree.StateTransitionUtil;
|
||||
import electrosphere.entity.btree.StateTransitionUtil.StateTransitionUtilItem;
|
||||
@ -25,7 +26,9 @@ import electrosphere.net.synchronization.annotation.SyncedField;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizableEnum;
|
||||
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
|
||||
import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
@ -93,6 +96,11 @@ public class ClientAttackTree implements BehaviorTree {
|
||||
String projectileToFire = null;
|
||||
String attackingPoint = null;
|
||||
|
||||
/**
|
||||
* The list of entities that have collided with the current attack
|
||||
*/
|
||||
List<Entity> collidedEntities = new LinkedList<Entity>();
|
||||
|
||||
//The state transition util
|
||||
StateTransitionUtil stateTransitionUtil;
|
||||
|
||||
@ -505,6 +513,39 @@ public class ClientAttackTree implements BehaviorTree {
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Freezes the animation for a frame or two when a collision occurs
|
||||
*/
|
||||
public void freezeFrame(){
|
||||
Actor actor = EntityUtils.getActor(parent);
|
||||
if(this.currentMove != null && this.currentMove.getHitstun() != null){
|
||||
String animName = this.currentMove.getAttackState().getAnimation().getNameThirdPerson();
|
||||
actor.setFreezeFrames(animName, this.currentMove.getHitstun());
|
||||
if(parent == Globals.playerEntity && !Globals.controlHandler.cameraIsThirdPerson()){
|
||||
Actor viewmodelActor = EntityUtils.getActor(Globals.firstPersonEntity);
|
||||
animName = this.currentMove.getAttackState().getAnimation().getNameFirstPerson();
|
||||
viewmodelActor.setFreezeFrames(animName, this.currentMove.getHitstun());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the target can be collided with
|
||||
* @param target The target
|
||||
* @return true if can be collided with, false otherwise (ie it has already collided)
|
||||
*/
|
||||
public boolean canCollideEntity(Entity target){
|
||||
return !this.collidedEntities.contains(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets that the current attack has collided with the provided entity
|
||||
* @param target The target entity
|
||||
*/
|
||||
public void collideEntity(Entity target){
|
||||
this.collidedEntities.add(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Automatically generated </p>
|
||||
@ -694,6 +735,9 @@ public class ClientAttackTree implements BehaviorTree {
|
||||
if(newState == AttackTreeState.BLOCK_RECOIL){
|
||||
this.stateTransitionUtil.interrupt(AttackTreeState.ATTACK);
|
||||
}
|
||||
if(newState == AttackTreeState.ATTACK){
|
||||
this.collidedEntities.clear();
|
||||
}
|
||||
this.setState(newState);
|
||||
}
|
||||
|
||||
|
||||
@ -46,6 +46,11 @@ public class AttackMove {
|
||||
int driftFrameStart; //when do we start drifting
|
||||
int driftFrameEnd; //when do we stop drifting
|
||||
|
||||
/**
|
||||
* Hitstun
|
||||
*/
|
||||
Integer hitstun;
|
||||
|
||||
/**
|
||||
* Gets the id of the attack move
|
||||
* @return the id of the attack move
|
||||
@ -189,6 +194,15 @@ public class AttackMove {
|
||||
public boolean getFiresProjectile(){
|
||||
return firesProjectile;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The number of frames to freeze for on successfully landing this attack
|
||||
* @return The number of frames or null
|
||||
*/
|
||||
public Integer getHitstun(){
|
||||
return hitstun;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ package electrosphere.net.client.protocol;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.client.collision.ClientHitboxCollision;
|
||||
import electrosphere.client.collision.ClientNetworkHitboxCollision;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.net.parser.net.message.CombatMessage;
|
||||
@ -26,7 +26,7 @@ public class CombatProtocol implements ClientProtocolTemplate<CombatMessage> {
|
||||
Entity senderEntity = Globals.clientSceneWrapper.getEntityFromServerId(message.getentityID());
|
||||
Entity receiverEntity = Globals.clientSceneWrapper.getEntityFromServerId(message.getreceiverEntityID());
|
||||
if(senderEntity != null && receiverEntity != null){
|
||||
ClientHitboxCollision.handleHitboxCollision(senderEntity, receiverEntity, position, message.gethitboxType(), message.gethurtboxType());
|
||||
ClientNetworkHitboxCollision.handleHitboxCollision(senderEntity, receiverEntity, position, message.gethitboxType(), message.gethurtboxType());
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
@ -98,9 +98,13 @@ public class Actor {
|
||||
public void incrementAnimationTime(double deltaTime){
|
||||
toRemoveMasks.clear();
|
||||
for(ActorAnimationMask mask : animationQueue){
|
||||
mask.setTime(mask.getTime() + deltaTime * animationScalar);
|
||||
if(mask.getTime() > mask.getDuration()){
|
||||
toRemoveMasks.add(mask);
|
||||
if(mask.getFreezeFrames() > 0){
|
||||
mask.setFreezeFrames(mask.getFreezeFrames() - 1);
|
||||
} else {
|
||||
mask.setTime(mask.getTime() + deltaTime * animationScalar);
|
||||
if(mask.getTime() > mask.getDuration()){
|
||||
toRemoveMasks.add(mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(ActorAnimationMask mask : toRemoveMasks){
|
||||
@ -673,6 +677,23 @@ public class Actor {
|
||||
this.boneGroups = boneGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of freeze frames for a given animation path if the animation is being played
|
||||
* @param animationPath The path to the animation
|
||||
* @param numFrames The number of frames to freeze for
|
||||
*/
|
||||
public void setFreezeFrames(String animationPath, int numFrames){
|
||||
if(numFrames < 1){
|
||||
throw new Error("Num frames less than 1 !" + numFrames);
|
||||
}
|
||||
for(ActorAnimationMask mask : this.animationQueue){
|
||||
if(mask.getAnimationName().contains(animationPath)){
|
||||
mask.setFreezeFrames(numFrames);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -23,6 +23,11 @@ public class ActorAnimationMask implements Comparable<ActorAnimationMask> {
|
||||
//The mask of bones to apply this animation to
|
||||
List<String> boneMask;
|
||||
|
||||
/**
|
||||
* The number of frames to freeze this animation mask for
|
||||
*/
|
||||
int freezeFrames = 0;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param priority
|
||||
@ -130,6 +135,22 @@ public class ActorAnimationMask implements Comparable<ActorAnimationMask> {
|
||||
return timeMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current freeze frame count
|
||||
* @return The number of freeze frames
|
||||
*/
|
||||
public int getFreezeFrames(){
|
||||
return freezeFrames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of freeze frames remaining in the mask
|
||||
* @param frameCount The number of frames
|
||||
*/
|
||||
public void setFreezeFrames(int frameCount){
|
||||
this.freezeFrames = frameCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ActorAnimationMask o) {
|
||||
ActorAnimationMask otherMask = (ActorAnimationMask)o;
|
||||
|
||||
@ -51,7 +51,13 @@ public class NaturalInventoryPanel {
|
||||
LoggerInterface.loggerUI.INFO("Natural inventory received drag release event");
|
||||
if(Globals.draggedItem != null){
|
||||
if(Globals.dragSourceInventory != inventory){
|
||||
if(Globals.dragSourceInventory instanceof UnrelationalInventoryState){
|
||||
if(Globals.dragSourceInventory instanceof RelationalInventoryState){
|
||||
if(ClientEquipState.hasEquipState(entity) && InventoryUtils.hasEquipInventory(entity)){
|
||||
RelationalInventoryState equipInventory = InventoryUtils.getEquipInventory(entity);
|
||||
ClientEquipState equipState = ClientEquipState.getEquipState(entity);
|
||||
equipState.commandAttemptUnequip(equipInventory.getItemSlot(Globals.draggedItem));
|
||||
}
|
||||
} if(Globals.dragSourceInventory instanceof UnrelationalInventoryState){
|
||||
//transfer item
|
||||
// sourceInventory.removeItem(Globals.draggedItem);
|
||||
// inventory.addItem(Globals.draggedItem);
|
||||
|
||||
@ -168,7 +168,7 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
||||
|
||||
//
|
||||
//handle attacker
|
||||
this.handleAttackerCollision(impactorEntity,receiverEntity, isDamageEvent);
|
||||
this.handleAttackerCollision(impactorEntity,receiverEntity, isBlockEvent);
|
||||
}
|
||||
|
||||
if(isBlockEvent){
|
||||
@ -211,7 +211,9 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
||||
if(impactorEntity != null && ServerAttackTree.getServerAttackTree(impactorEntity) != null){
|
||||
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(impactorEntity);
|
||||
impactorAttackTree.collideEntity(receiverEntity);
|
||||
impactorAttackTree.recoilFromBlock();
|
||||
if(isBlock){
|
||||
impactorAttackTree.recoilFromBlock();
|
||||
}
|
||||
//if the receiver is an item that is equipped, collide with parent too
|
||||
if(receiverIsItem && receiverHasParent){
|
||||
impactorAttackTree.collideEntity(AttachUtils.getParent(receiverEntity));
|
||||
@ -224,7 +226,9 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
|
||||
} else if(impactorEntity != null && AttachUtils.hasParent(impactorEntity) && AttachUtils.getParent(impactorEntity) != null && ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorEntity)) != null){
|
||||
ServerAttackTree impactorAttackTree = ServerAttackTree.getServerAttackTree(AttachUtils.getParent(impactorEntity));
|
||||
impactorAttackTree.collideEntity(receiverEntity);
|
||||
impactorAttackTree.recoilFromBlock();
|
||||
if(isBlock){
|
||||
impactorAttackTree.recoilFromBlock();
|
||||
}
|
||||
//if the receiver is an item that is equipped, collide with parent too
|
||||
if(receiverIsItem && receiverHasParent){
|
||||
impactorAttackTree.collideEntity(AttachUtils.getParent(receiverEntity));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user