diff --git a/assets/Data/creatures/test.json b/assets/Data/creatures/test.json index 096e2db5..22435e2f 100644 --- a/assets/Data/creatures/test.json +++ b/assets/Data/creatures/test.json @@ -93,12 +93,11 @@ { "type": "hurt", "bone": "Bone", - "radius": 0.04 + "radius": 0.6 } ], "tokens" : [ - "BLENDER_TRANSFORM", - "ATTACKER", + "SHOOTER", "GRAVITY", "TARGETABLE", "OUTLINE", @@ -117,17 +116,6 @@ ], "rotatorSystem" : { "rotatorItems" : [ - { - "boneName" : "Bone", - "constraints" : [ - { - "followsView" : true, - "followsBone" : false, - "parentBone" : "", - "allowedMarginPitch" : 0.2 - } - ] - } ] }, "equipPoints" : [ @@ -142,6 +130,23 @@ "offsetZ" : 0 }, "attackMoves" : [ + { + "attackMoveId" : "ProjectileFire", + "type" : "PROJECTILE", + "windupAnimationName" : "Idle1", + "holdAnimationName" : "Idle1", + "attackAnimationName" : "Idle1", + "damageStartFrame" : 1, + "damageEndFrame" : 2, + "firesProjectile" : true, + "nextMoveId" : "", + "nextAttackMoveWindowStart" : 0, + "nextAttackMoveWindowEnd" : 1, + "movementStart" : 0, + "movementEnd" : 0, + "movementGoal" : 0, + "initialMove" : false + } ], "healthSystem" : { "maxHealth" : 100, diff --git a/assets/Data/objects/testscene1objects.json b/assets/Data/objects/testscene1objects.json index 6748565a..58246558 100644 --- a/assets/Data/objects/testscene1objects.json +++ b/assets/Data/objects/testscene1objects.json @@ -11,6 +11,16 @@ "collidable": null, "graphicsTemplate": null }, + { + "objectId" : "skyscraper1", + "modelPath" : "Models/skyscraper1.fbx", + "tokens" : [ + "DISABLE_COLLISION_REACTION", + "GENERATE_COLLISION_TERRAIN" + ], + "collidable": null, + "graphicsTemplate": null + }, { "objectId" : "smoke1", "modelPath" : "Models/unitcube.fbx", diff --git a/assets/Data/projectile.json b/assets/Data/projectile.json new file mode 100644 index 00000000..f75318aa --- /dev/null +++ b/assets/Data/projectile.json @@ -0,0 +1,12 @@ +{ + "projectiles" : [ + { + "id" : "missile1", + "modelPath" : "Models/unitsphere.fbx", + "maxLife" : 10000, + "velocity" : 0.1, + "damage" : 1, + "hitboxRadius" : 0.4 + } + ] +} \ No newline at end of file diff --git a/assets/Models/modelPretransforms.json b/assets/Models/modelPretransforms.json index 5822e6ce..9aa91d21 100644 --- a/assets/Models/modelPretransforms.json +++ b/assets/Models/modelPretransforms.json @@ -18,7 +18,7 @@ "meshName" : "Cube.001", "rotation" : [0.0, 0.0, -0.7071068, 0.7071068], "offset" : [0.0, 0.0, 0.0], - "scale" : [0.3, 0.3, 0.3] + "scale" : [0.0015, 0.0015, 0.0015] } ] } diff --git a/assets/Models/skyscraper1.fbx b/assets/Models/skyscraper1.fbx new file mode 100644 index 00000000..a104da15 Binary files /dev/null and b/assets/Models/skyscraper1.fbx differ diff --git a/assets/Scenes/testscene1/testscene1.json b/assets/Scenes/testscene1/testscene1.json index 53364f30..c7bbc97b 100644 --- a/assets/Scenes/testscene1/testscene1.json +++ b/assets/Scenes/testscene1/testscene1.json @@ -10,6 +10,28 @@ "rotY": 0, "rotZ": 0, "rotW": 0.7071068 + }, + { + "type": "object", + "subtype": "skyscraper1", + "posX": 2, + "posY": 1, + "posZ": 2, + "rotX": -0.7071068, + "rotY": 0, + "rotZ": 0, + "rotW": 0.7071068 + }, + { + "type": "creature", + "subtype": "fighter", + "posX": 2, + "posY": 1, + "posZ": 2, + "rotX": -0.7071068, + "rotY": 0, + "rotZ": 0, + "rotW": 0.7071068 } ], "scriptPaths": [ diff --git a/assets/Scenes/testscene2/someScript.js b/assets/Scenes/testscene2/someScript.js new file mode 100644 index 00000000..c2804e3a --- /dev/null +++ b/assets/Scenes/testscene2/someScript.js @@ -0,0 +1 @@ +console.log("Loaded testscene1"); \ No newline at end of file diff --git a/assets/Scenes/testscene2/testscene2.json b/assets/Scenes/testscene2/testscene2.json new file mode 100644 index 00000000..79d831e7 --- /dev/null +++ b/assets/Scenes/testscene2/testscene2.json @@ -0,0 +1,30 @@ +{ + "entities": [ + { + "type": "object", + "subtype": "terrain1", + "posX": 2, + "posY": 1, + "posZ": 2, + "rotX": -0.7071068, + "rotY": 0, + "rotZ": 0, + "rotW": 0.7071068 + }, + { + "type": "creature", + "subtype": "fighter", + "posX": 2, + "posY": 1, + "posZ": 2, + "rotX": -0.7071068, + "rotY": 0, + "rotZ": 0, + "rotW": 0.7071068 + } + ], + "scriptPaths": [ + "Scenes/testscene1/someScript.js" + ], + "initScriptPath": "Scenes/testscene1/someScript.js" +} \ No newline at end of file diff --git a/assets/Textures/default_texture_map.json b/assets/Textures/default_texture_map.json index 15316cdd..e193b81d 100644 --- a/assets/Textures/default_texture_map.json +++ b/assets/Textures/default_texture_map.json @@ -425,6 +425,12 @@ "/Textures/f15.png", "/Textures/f15.png" ] + }, + "Models/skyscraper1.fbx" : { + "Cube.001" : [ + "Textures/skyscraper1.png", + "Textures/skyscraper1.png" + ] } } } \ No newline at end of file diff --git a/assets/Textures/skyscraper1.png b/assets/Textures/skyscraper1.png new file mode 100644 index 00000000..ad0c3e65 Binary files /dev/null and b/assets/Textures/skyscraper1.png differ diff --git a/src/main/java/electrosphere/controls/ControlHandler.java b/src/main/java/electrosphere/controls/ControlHandler.java index ff732e5d..9d3fa8f4 100644 --- a/src/main/java/electrosphere/controls/ControlHandler.java +++ b/src/main/java/electrosphere/controls/ControlHandler.java @@ -77,6 +77,7 @@ import electrosphere.controls.Control.ControlType; import electrosphere.entity.Entity; import electrosphere.entity.state.BehaviorTree; import electrosphere.entity.state.attack.AttackTree; +import electrosphere.entity.state.attack.ShooterTree; import electrosphere.entity.state.equip.EquipState; import electrosphere.entity.state.inventory.InventoryUtils; import electrosphere.entity.state.inventory.UnrelationalInventoryState; @@ -808,6 +809,18 @@ public class ControlHandler { // CreatureUtils.setFacingVector(Globals.playerCharacter, new Vector3d(-cameraEyeVector.x,0,-cameraEyeVector.z).normalize()); attackTree.start(); } + ShooterTree shooterTree = ShooterTree.getShooterTree(Globals.playerEntity); + if(shooterTree != null){ + shooterTree.fire(); + } + } + }}); + controls.get(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY).setOnRepeat(new ControlMethod(){public void execute(){ + if(Globals.playerEntity != null){ + ShooterTree shooterTree = ShooterTree.getShooterTree(Globals.playerEntity); + if(shooterTree != null){ + shooterTree.fire(); + } } }}); controls.get(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY).setOnRelease(new ControlMethod(){public void execute(){ @@ -820,6 +833,7 @@ public class ControlHandler { } } }}); + controls.get(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY).setRepeatTimeout(0.5f * Main.targetFrameRate); /* diff --git a/src/main/java/electrosphere/entity/EntityDataStrings.java b/src/main/java/electrosphere/entity/EntityDataStrings.java index b74478b0..3fa704aa 100644 --- a/src/main/java/electrosphere/entity/EntityDataStrings.java +++ b/src/main/java/electrosphere/entity/EntityDataStrings.java @@ -175,6 +175,16 @@ public class EntityDataStrings { public static final String ATTACK_MOVE_TYPE_ACTIVE = "attackMoveTypeActive"; public static final String ATTACK_MOVE_TYPE_MELEE_SWING_ONE_HAND = "MELEE_WEAPON_SWING_ONE_HAND"; public static final String ATTACK_MOVE_TYPE_BOW_TWO_HAND = "RANGED_WEAPON_BOW_TWO_HAND"; + + /* + * Shooter tree + */ + public static final String SHOOTER_TREE = "shooterTree"; + + /* + * Projectile/Projectile tree + */ + public static final String PROJECTILE_TREE = "projectileTree"; /* Health System diff --git a/src/main/java/electrosphere/entity/state/attack/ShooterTree.java b/src/main/java/electrosphere/entity/state/attack/ShooterTree.java index b804ffe4..9351befc 100644 --- a/src/main/java/electrosphere/entity/state/attack/ShooterTree.java +++ b/src/main/java/electrosphere/entity/state/attack/ShooterTree.java @@ -1,7 +1,13 @@ package electrosphere.entity.state.attack; +import org.joml.Vector3d; + import electrosphere.entity.Entity; +import electrosphere.entity.EntityDataStrings; +import electrosphere.entity.EntityUtils; import electrosphere.entity.state.BehaviorTree; +import electrosphere.entity.types.creature.CreatureUtils; +import electrosphere.entity.types.projectile.ProjectileUtils; public class ShooterTree implements BehaviorTree { @@ -15,11 +21,15 @@ public class ShooterTree implements BehaviorTree { Entity parent; - int ammoAvailable; - int ammoMax; + int ammoAvailable = 1; + int ammoMax = 1; + + int cooldownCurrent = 0; + int cooldownMax = 4; public ShooterTree(Entity parent){ this.parent = parent; + this.state = ShooterTreeState.IDLE; } @Override @@ -28,9 +38,19 @@ public class ShooterTree implements BehaviorTree { switch(state){ case ATTACK: { // + Vector3d parentPosition = EntityUtils.getPosition(parent); + Vector3d movementDir = CreatureUtils.getFacingVector(parent); + ProjectileUtils.spawnProjectile("missile1", parentPosition, new Vector3d(movementDir),parent); + this.state = ShooterTreeState.COOLDOWN; + cooldownCurrent = cooldownMax; } break; case COOLDOWN: { // + if(cooldownCurrent > 0){ + cooldownCurrent--; + } else { + state = ShooterTreeState.IDLE; + } } break; case IDLE: { // @@ -48,8 +68,16 @@ public class ShooterTree implements BehaviorTree { } if(canFire){ //fire - System.out.println("Fire!"); + this.state = ShooterTreeState.ATTACK; } } + + public static void setShooterTree(Entity entity, ShooterTree shooterTree){ + entity.putData(EntityDataStrings.SHOOTER_TREE, shooterTree); + } + + public static ShooterTree getShooterTree(Entity entity){ + return (ShooterTree)entity.getData(EntityDataStrings.SHOOTER_TREE); + } } diff --git a/src/main/java/electrosphere/entity/state/life/LifeState.java b/src/main/java/electrosphere/entity/state/life/LifeState.java index bf0af1b0..c815a80d 100644 --- a/src/main/java/electrosphere/entity/state/life/LifeState.java +++ b/src/main/java/electrosphere/entity/state/life/LifeState.java @@ -107,6 +107,7 @@ public class LifeState implements BehaviorTree { public void damage(int damage){ if(!isInvincible){ lifeCurrent = lifeCurrent - damage; + System.out.println(lifeCurrent); isInvincible = true; if(lifeCurrent < 0){ lifeCurrent = 0; diff --git a/src/main/java/electrosphere/entity/state/movement/AirplaneMovementTree.java b/src/main/java/electrosphere/entity/state/movement/AirplaneMovementTree.java index 0bca2c0e..c46f3d6f 100644 --- a/src/main/java/electrosphere/entity/state/movement/AirplaneMovementTree.java +++ b/src/main/java/electrosphere/entity/state/movement/AirplaneMovementTree.java @@ -206,7 +206,8 @@ public class AirplaneMovementTree implements BehaviorTree { //rotate thrust vector - rotationVector.set(new Vector3f((float)rotationVector.x,(float)rotationVector.y,(float)rotationVector.z).mul(1.0f - this.maxRotationSpeed).add(new Vector3f(cameraEyeVector).mul(-this.maxRotationSpeed))); + rotationVector.set(rotation.transform(new Vector3f(0,0,1))); + // rotationVector.set(new Vector3f((float)rotationVector.x,(float)rotationVector.y,(float)rotationVector.z).mul(1.0f - this.maxRotationSpeed).add(new Vector3f(cameraEyeVector).mul(-this.maxRotationSpeed))); rollVal = rollVal * 0.9f; diff --git a/src/main/java/electrosphere/entity/state/movement/ProjectileTree.java b/src/main/java/electrosphere/entity/state/movement/ProjectileTree.java index c6bc364f..24a79eec 100644 --- a/src/main/java/electrosphere/entity/state/movement/ProjectileTree.java +++ b/src/main/java/electrosphere/entity/state/movement/ProjectileTree.java @@ -4,6 +4,7 @@ import org.joml.Vector3d; import org.joml.Vector3f; import electrosphere.entity.Entity; +import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.state.BehaviorTree; import electrosphere.main.Globals; @@ -13,14 +14,31 @@ public class ProjectileTree implements BehaviorTree { Entity parent; int maxLife; int lifeCurrent = 0; - Vector3f vector; + float damage = 0.0f; + Vector3d vector; - public ProjectileTree(Entity parent, int maxLife, Vector3f initialVector, float velocity){ + public ProjectileTree(Entity parent, int maxLife, Vector3d initialVector, float velocity){ this.parent = parent; this.maxLife = maxLife; this.vector = initialVector.mul(velocity); } + /** + * Used when spawning projectiles from projectiles.json file + * Separate constructor so can include damage value + * @param parent Parent entity of the projectile + * @param maxLife Max flight time of the projectile in frames + * @param initialVector The initial velocity vector of the projectile + * @param velocity The intiial velocity magnitude of the projectile + * @param damage The damage of the projectile + */ + public ProjectileTree(Entity parent, int maxLife, Vector3d initialVector, float velocity, float damage){ + this.parent = parent; + this.maxLife = maxLife; + this.vector = initialVector.mul(velocity); + this.damage = damage; + } + @Override public void simulate() { @@ -34,5 +52,31 @@ public class ProjectileTree implements BehaviorTree { positionCurrent.add(vector); } + + /** + * Only relevant when spawned from projectiles.json file + * @return The damage of the projectile as defined in projectiles.json + */ + public float getDamage(){ + return damage; + } + + /** + * Sets the projectile tree of a given entity + * @param entity The entity + * @param tree The projectile tree + */ + public static void setProjectileTree(Entity entity, ProjectileTree tree){ + entity.putData(EntityDataStrings.PROJECTILE_TREE, tree); + } + + /** + * Gets the projectile tree of a given entity + * @param entity The entity + * @return The projectile tree + */ + public static ProjectileTree getProjectileTree(Entity entity){ + return (ProjectileTree)entity.getData(EntityDataStrings.PROJECTILE_TREE); + } } diff --git a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java index f84c8b4a..befea8ec 100644 --- a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java +++ b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java @@ -15,6 +15,7 @@ import electrosphere.game.data.creature.type.CreatureType; import electrosphere.entity.state.BehaviorTree; import electrosphere.entity.state.IdleTree; import electrosphere.entity.state.attack.AttackTree; +import electrosphere.entity.state.attack.ShooterTree; import electrosphere.entity.state.collidable.CollidableTree; import electrosphere.entity.state.equip.EquipState; import electrosphere.entity.state.gravity.GravityTree; @@ -299,6 +300,11 @@ public class CreatureUtils { } } break; + case "SHOOTER": { + ShooterTree shooterTree = new ShooterTree(rVal); + ShooterTree.setShooterTree(rVal, shooterTree); + Globals.entityManager.registerBehaviorTree(shooterTree); + } break; case "GRAVITY": Collidable collidable = (Collidable)rVal.getData(EntityDataStrings.PHYSICS_COLLIDABLE); CollisionObject collisionObject = (CollisionObject)rVal.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); diff --git a/src/main/java/electrosphere/entity/types/hitbox/HitboxData.java b/src/main/java/electrosphere/entity/types/hitbox/HitboxData.java index 31aba347..eb6e7d1f 100644 --- a/src/main/java/electrosphere/entity/types/hitbox/HitboxData.java +++ b/src/main/java/electrosphere/entity/types/hitbox/HitboxData.java @@ -1,11 +1,19 @@ package electrosphere.entity.types.hitbox; +import java.util.List; + +import electrosphere.entity.Entity; +import electrosphere.entity.types.hitbox.HitboxUtils.HitboxPositionCallback; public class HitboxData { String type; String bone; float radius; boolean active = false; + //used for more advanced hitbox spawning to find hitbox position on frame update + HitboxPositionCallback positionCallback; + //used to filter this hitbox to hitting only certain parent entities + List filter; public String getType() { return type; @@ -38,6 +46,38 @@ public class HitboxData { public void setRadius(float radius) { this.radius = radius; } + + /** + * Gets the position callback + * @return The position callback + */ + public HitboxPositionCallback getPositionCallback(){ + return positionCallback; + } + + /** + * Sets the position callback + * @param positionCallback The position callback + */ + public void setPositionCallback(HitboxPositionCallback positionCallback){ + this.positionCallback = positionCallback; + } + + /** + * Sets an entity filter on the hitbox + * @param filter The list of parent entities to exclude from collisions + */ + public void setEntityFilter(List filter){ + this.filter = filter; + } + + /** + * Gets the entity filter + * @return The list of parent entities to exclude from collisions + */ + public List getEntityFilter(){ + return filter; + } } diff --git a/src/main/java/electrosphere/entity/types/hitbox/HitboxUtils.java b/src/main/java/electrosphere/entity/types/hitbox/HitboxUtils.java index f488e7c6..a4ef13c1 100644 --- a/src/main/java/electrosphere/entity/types/hitbox/HitboxUtils.java +++ b/src/main/java/electrosphere/entity/types/hitbox/HitboxUtils.java @@ -4,9 +4,12 @@ import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.types.attach.AttachUtils; +import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.item.ItemUtils; +import electrosphere.entity.state.attack.ShooterTree; import electrosphere.entity.state.life.LifeState; import electrosphere.entity.state.life.LifeUtils; +import electrosphere.entity.state.movement.ProjectileTree; import electrosphere.game.server.effects.ParticleEffects; import electrosphere.main.Globals; @@ -47,7 +50,35 @@ public class HitboxUtils { data.setBone(bone); data.setRadius(size); data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT); - data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT); + rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent); + rVal.putData(EntityDataStrings.HITBOX_DATA, data); + rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); + rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); + Globals.hitboxManager.registerHitbox(rVal); + return rVal; + } + + /** + * More sophisticated function for spawning in hitboxes. Takes a position callback so it's not tied to a bone + * @param parent The parent entity of the hitbox + * @param positionCallback The position callback for keeping hitbox entity position up to date + * @param size The size of the hitbox + * @param hurtbox If true, it will instead be a hurtbox + * @param filter an optional list of parent entities to not colide with + * @return The hitbox entity + */ + public static Entity spawnRegularHitbox(Entity parent, HitboxPositionCallback positionCallback, float size, boolean hurtbox, List filter){ + Entity rVal = new Entity(); + HitboxData data = new HitboxData(); + data.setActive(true); + data.setPositionCallback(positionCallback); + data.setRadius(size); + data.setEntityFilter(filter); + if(hurtbox){ + data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT); + } else { + data.setType(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT); + } rVal.putData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT, parent); rVal.putData(EntityDataStrings.HITBOX_DATA, data); rVal.putData(EntityDataStrings.DATA_STRING_POSITION, new Vector3d(0,0,0)); @@ -60,22 +91,27 @@ public class HitboxUtils { Entity parent = ((Entity)hitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_PARENT)); HitboxData hitboxData = getHitboxData(hitbox); String boneName = hitboxData.getBone(); - Quaternionf parentRotation = ((Quaternionf)EntityUtils.getRotation(parent)); - Vector3f positionScale = ((Vector3f)EntityUtils.getScale(parent)); - Vector3f worldPosition = new Vector3f(); - Vector3f bonePosition = EntityUtils.getActor(parent).getBonePosition(boneName); - Vector3d parentPos = EntityUtils.getPosition(parent); - worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z); - Quaternionf rotation = new Quaternionf(parentRotation); - - worldPosition = worldPosition.mul(positionScale); + if(boneName != null){ + Quaternionf parentRotation = EntityUtils.getRotation(parent); + Vector3f positionScale = EntityUtils.getScale(parent); + Vector3f worldPosition = new Vector3f(); + Vector3f bonePosition = EntityUtils.getActor(parent).getBonePosition(boneName); + Vector3d parentPos = EntityUtils.getPosition(parent); + worldPosition.set(bonePosition.x,bonePosition.y,bonePosition.z); + Quaternionf rotation = new Quaternionf(parentRotation); + + worldPosition = worldPosition.mul(positionScale); - worldPosition = worldPosition.rotate(rotation); - - - worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z)); - - ((Vector3d)hitbox.getData(EntityDataStrings.DATA_STRING_POSITION)).set(worldPosition); + worldPosition = worldPosition.rotate(rotation); + + + worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z)); + + EntityUtils.getPosition(hitbox).set(worldPosition); + } else { + HitboxPositionCallback positionCallback = hitboxData.getPositionCallback(); + EntityUtils.getPosition(hitbox).set(positionCallback.getPosition()); + } } public static void collideEntities(Entity generatorHitbox){ @@ -90,6 +126,17 @@ public class HitboxUtils { HitboxData generatorData = getHitboxData(generatorHitbox); HitboxData receiverData = getHitboxData(receiverHitbox); + + //check projectile filters + List generatorFilter = generatorData.getEntityFilter(); + if(generatorFilter != null && generatorFilter.contains(receiverParent)){ + continue; + } + + List receiverFilter = receiverData.getEntityFilter(); + if(receiverFilter != null && receiverFilter.contains(generatorParent)){ + continue; + } //if there is a collision //and the collision isn't against itself @@ -140,7 +187,16 @@ public class HitboxUtils { } } } else { - int damage = ItemUtils.getWeaponDataRaw(hitboxParent).getDamage(); + int damage = 0; + //for entities using attacktree + if(CreatureUtils.getAttackTree(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); @@ -161,5 +217,16 @@ public class HitboxUtils { public static List getHurtboxAssociatedList(Entity e){ return (List)e.getData(EntityDataStrings.HURTBOX_ASSOCIATED_LIST); } + + /** + * Intended to be implemented as an anonoymous class when needed + */ + public interface HitboxPositionCallback { + /** + * Gets the current position this hitbox should be at + * @return The position this hitbox should be at + */ + public Vector3d getPosition(); + } } diff --git a/src/main/java/electrosphere/entity/types/projectile/ProjectileUtils.java b/src/main/java/electrosphere/entity/types/projectile/ProjectileUtils.java index 5a77697b..6e38de12 100644 --- a/src/main/java/electrosphere/entity/types/projectile/ProjectileUtils.java +++ b/src/main/java/electrosphere/entity/types/projectile/ProjectileUtils.java @@ -1,5 +1,8 @@ package electrosphere.entity.types.projectile; +import java.util.LinkedList; +import java.util.List; + import org.joml.Quaterniond; import org.joml.Quaternionf; import org.joml.Quaternionfc; @@ -9,6 +12,9 @@ import org.joml.Vector3f; import electrosphere.entity.Entity; import electrosphere.entity.EntityUtils; import electrosphere.entity.state.movement.ProjectileTree; +import electrosphere.entity.types.hitbox.HitboxUtils; +import electrosphere.entity.types.hitbox.HitboxUtils.HitboxPositionCallback; +import electrosphere.game.data.projectile.ProjectileType; import electrosphere.main.Globals; public class ProjectileUtils { @@ -16,7 +22,7 @@ public class ProjectileUtils { public static Entity spawnBasicProjectile(String model, Vector3d initialPosition, Quaternionf rotation, int maxLife, Vector3f initialVector, float velocity){ Entity rVal = EntityUtils.spawnDrawableEntity(model); Globals.assetManager.addModelPathToQueue(model); - ProjectileTree tree = new ProjectileTree(rVal,maxLife,initialVector,velocity); + ProjectileTree tree = new ProjectileTree(rVal,maxLife,new Vector3d(initialVector),velocity); EntityUtils.getPosition(rVal).set(initialPosition); // EntityUtils.getRotation(currentEntity).rotationTo(new Vector3f(0,0,1), new Vector3f((float)facingAngle.x,(float)facingAngle.y,(float)facingAngle.z)).mul(parentActor.getBoneRotation(targetBone)).normalize(); EntityUtils.getRotation(rVal).rotationTo(new Vector3f(0,0,1), new Vector3f((float)initialVector.x,(float)initialVector.y,(float)initialVector.z)).normalize(); @@ -27,4 +33,35 @@ public class ProjectileUtils { return rVal; } + /** + * More sophisticated function for spawning projectiles. Uses the projectiles.json file to store data about types to spawn. + * Also filters the parent from being hit by their own projectiles. + * @param projectileType The type in projectiles.json to spawn + * @param initialPosition The initial position of the projectile + * @param initialVector The initial velocity of the projectile + * @param parent The parent that fired said projectile + * @return The projectile entity + */ + public static Entity spawnProjectile(String projectileType, Vector3d initialPosition, Vector3d initialVector, Entity parent){ + ProjectileType rawType = Globals.gameConfigCurrent.getProjectileMap().getType(projectileType); + Entity rVal = EntityUtils.spawnDrawableEntity(rawType.getModelPath()); + //initial coordinates + EntityUtils.getRotation(rVal).rotationTo(new Vector3f(0,0,1), new Vector3f((float)initialVector.x,(float)initialVector.y,(float)initialVector.z)).normalize(); + EntityUtils.getPosition(rVal).set(initialPosition); + //projectile behavior tree + ProjectileTree tree = new ProjectileTree(rVal,rawType.getMaxLife(),initialVector,rawType.getVelocity(), rawType.getDamage()); + Globals.entityManager.registerBehaviorTree(tree); + ProjectileTree.setProjectileTree(rVal, tree); + //filter construction + List filter = new LinkedList(); + filter.add(parent); + //collidable + HitboxUtils.spawnRegularHitbox(rVal, new HitboxPositionCallback() { + public Vector3d getPosition(){ + return EntityUtils.getPosition(rVal); + } + }, rawType.getHitboxRadius(), false, filter); + return rVal; + } + } diff --git a/src/main/java/electrosphere/game/data/Config.java b/src/main/java/electrosphere/game/data/Config.java index e9c26b07..18ac5272 100644 --- a/src/main/java/electrosphere/game/data/Config.java +++ b/src/main/java/electrosphere/game/data/Config.java @@ -12,6 +12,7 @@ import electrosphere.game.data.item.type.model.ItemTypeMap; import electrosphere.game.data.object.type.ObjectData; import electrosphere.game.data.object.type.model.ObjectTypeLoader; import electrosphere.game.data.object.type.model.ObjectTypeMap; +import electrosphere.game.data.projectile.ProjectileTypeHolder; import electrosphere.game.data.structure.type.model.StructureTypeMap; import electrosphere.game.server.race.model.RaceMap; import electrosphere.game.server.symbolism.model.SymbolMap; @@ -30,6 +31,7 @@ public class Config { ObjectTypeLoader objectTypeLoader; SymbolMap symbolMap; RaceMap raceMap; + ProjectileTypeHolder projectileTypeHolder; public static Config loadDefaultConfig(){ Config config = new Config(); @@ -40,6 +42,8 @@ public class Config { config.objectTypeLoader = loadObjectTypes("Data/objects.json"); config.symbolMap = FileUtils.loadObjectFromAssetPath("Data/symbolism.json", SymbolMap.class); config.raceMap = FileUtils.loadObjectFromAssetPath("Data/races.json", RaceMap.class); + config.projectileTypeHolder = FileUtils.loadObjectFromAssetPath("Data/projectile.json", ProjectileTypeHolder.class); + config.projectileTypeHolder.init(); return config; } @@ -131,5 +135,9 @@ public class Config { public ObjectTypeLoader getObjectTypeLoader() { return objectTypeLoader; } + + public ProjectileTypeHolder getProjectileMap(){ + return projectileTypeHolder; + } } diff --git a/src/main/java/electrosphere/game/data/projectile/ProjectileType.java b/src/main/java/electrosphere/game/data/projectile/ProjectileType.java new file mode 100644 index 00000000..33f7f522 --- /dev/null +++ b/src/main/java/electrosphere/game/data/projectile/ProjectileType.java @@ -0,0 +1,37 @@ +package electrosphere.game.data.projectile; + +public class ProjectileType { + + + String id; + String modelPath; + int maxLife; + float velocity; + float damage; + float hitboxRadius; + + public String getId(){ + return id; + } + + public String getModelPath(){ + return modelPath; + } + + public int getMaxLife(){ + return maxLife; + } + + public float getVelocity(){ + return velocity; + } + + public float getDamage(){ + return damage; + } + + public float getHitboxRadius(){ + return hitboxRadius; + } + +} diff --git a/src/main/java/electrosphere/game/data/projectile/ProjectileTypeHolder.java b/src/main/java/electrosphere/game/data/projectile/ProjectileTypeHolder.java new file mode 100644 index 00000000..78451dba --- /dev/null +++ b/src/main/java/electrosphere/game/data/projectile/ProjectileTypeHolder.java @@ -0,0 +1,24 @@ +package electrosphere.game.data.projectile; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ProjectileTypeHolder { + + List projectiles; + + Map projectileTypeMap; + + public void init(){ + projectileTypeMap = new HashMap(); + for(ProjectileType type : projectiles){ + projectileTypeMap.put(type.getId(), type); + } + } + + public ProjectileType getType(String id){ + return projectileTypeMap.get(id); + } + +}