Add cat
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
720e147d99
commit
d152047fe1
@ -6,7 +6,8 @@
|
||||
"files" : [
|
||||
"Data/entity/creatures/human.json",
|
||||
"Data/entity/creatures/skeleton.json",
|
||||
"Data/entity/creatures/editor.json"
|
||||
"Data/entity/creatures/editor.json",
|
||||
"Data/entity/creatures/animals.json"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -38,6 +38,80 @@
|
||||
"onDamageIFrames" : 30
|
||||
},
|
||||
"modelPath" : "Models/deer1.fbx"
|
||||
},
|
||||
{
|
||||
"id" : "Cat",
|
||||
"displayName" : "Cat",
|
||||
"hitboxes" : [
|
||||
{
|
||||
"type": "hurt",
|
||||
"bone": "Bone",
|
||||
"radius": 0.04
|
||||
}
|
||||
],
|
||||
"tokens" : [
|
||||
"GRAVITY"
|
||||
],
|
||||
"movementSystems" : [
|
||||
{
|
||||
"type" : "GROUND",
|
||||
"acceleration" : 300.0,
|
||||
"maxVelocity" : 10.0,
|
||||
"strafeMultiplier" : 1.0,
|
||||
"backpedalMultiplier" : 0.5,
|
||||
"footstepFirstAudioOffset" : 0.2,
|
||||
"footstepSecondAudioOffset" : 0.6,
|
||||
"animationStartup" : {
|
||||
"nameThirdPerson" : "Walk",
|
||||
"priorityCategory" : "CORE_MOVEMENT"
|
||||
},
|
||||
"animationLoop" : {
|
||||
"nameThirdPerson" : "Walk",
|
||||
"priorityCategory" : "CORE_MOVEMENT"
|
||||
},
|
||||
"animationWindDown" : {
|
||||
"nameThirdPerson" : "Walk",
|
||||
"priorityCategory" : "CORE_MOVEMENT"
|
||||
}
|
||||
}
|
||||
],
|
||||
"collidable" : {
|
||||
"type" : "CAPSULE",
|
||||
"dimension1" : 0.35,
|
||||
"dimension2" : 0.7,
|
||||
"dimension3" : 0.35,
|
||||
"linearFriction": 0.001,
|
||||
"mass": 0.3,
|
||||
"rotX": 0,
|
||||
"rotY": 0,
|
||||
"rotZ": 0,
|
||||
"rotW": 1,
|
||||
"offsetX" : 0,
|
||||
"offsetY" : 0.7,
|
||||
"offsetZ" : 0,
|
||||
"angularlyStatic" : true
|
||||
},
|
||||
"healthSystem" : {
|
||||
"maxHealth" : 100,
|
||||
"onDamageIFrames" : 30
|
||||
},
|
||||
"aiTrees" : [
|
||||
{
|
||||
"name" : "Wander"
|
||||
}
|
||||
],
|
||||
"graphicsTemplate": {
|
||||
"model": {
|
||||
"idleData": {
|
||||
"animation": {
|
||||
"nameFirstPerson" : "Pose",
|
||||
"nameThirdPerson" : "Pose",
|
||||
"priorityCategory" : "IDLE"
|
||||
}
|
||||
},
|
||||
"path" : "Models/creatures/cat1/cat1.glb"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"files" : []
|
||||
|
||||
BIN
assets/Models/creatures/cat1/Cat.png
Normal file
BIN
assets/Models/creatures/cat1/Cat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 316 KiB |
BIN
assets/Models/creatures/cat1/cat1.glb
Normal file
BIN
assets/Models/creatures/cat1/cat1.glb
Normal file
Binary file not shown.
@ -1,3 +1,3 @@
|
||||
#maven.buildNumber.plugin properties file
|
||||
#Wed Jun 04 22:45:11 EDT 2025
|
||||
buildNumber=645
|
||||
#Thu Jul 03 09:59:19 EDT 2025
|
||||
buildNumber=646
|
||||
|
||||
@ -43,6 +43,9 @@ public class ScriptLevelEditorUtils {
|
||||
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE));
|
||||
}
|
||||
cursorPos = cursorPos.add(cursorVerticalOffset);
|
||||
if(cursorPos.x < 0 || cursorPos.y < 0 || cursorPos.z < 0){
|
||||
return;
|
||||
}
|
||||
realm.getServerWorldData().clampWithinBounds(cursorPos);
|
||||
CreatureUtils.serverSpawnBasicCreature(realm, cursorPos, Globals.clientState.selectedSpawntype.getId(), null);
|
||||
} else if(Globals.clientState.selectedSpawntype instanceof Item){
|
||||
@ -56,6 +59,9 @@ public class ScriptLevelEditorUtils {
|
||||
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE));
|
||||
}
|
||||
cursorPos = cursorPos.add(cursorVerticalOffset);
|
||||
if(cursorPos.x < 0 || cursorPos.y < 0 || cursorPos.z < 0){
|
||||
return;
|
||||
}
|
||||
ItemUtils.serverSpawnBasicItem(realm, cursorPos, Globals.clientState.selectedSpawntype.getId());
|
||||
} else if(Globals.clientState.selectedSpawntype instanceof FoliageType){
|
||||
LoggerInterface.loggerEngine.INFO("spawn " + Globals.clientState.selectedSpawntype.getId() + "!");
|
||||
@ -68,6 +74,9 @@ public class ScriptLevelEditorUtils {
|
||||
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE));
|
||||
}
|
||||
cursorPos = cursorPos.add(cursorVerticalOffset);
|
||||
if(cursorPos.x < 0 || cursorPos.y < 0 || cursorPos.z < 0){
|
||||
return;
|
||||
}
|
||||
FoliageUtils.serverSpawnTreeFoliage(realm, cursorPos, Globals.clientState.selectedSpawntype.getId());
|
||||
} else {
|
||||
LoggerInterface.loggerEngine.INFO("spawn " + Globals.clientState.selectedSpawntype.getId() + "!");
|
||||
@ -80,6 +89,9 @@ public class ScriptLevelEditorUtils {
|
||||
cursorPos = new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE));
|
||||
}
|
||||
cursorPos = cursorPos.add(cursorVerticalOffset);
|
||||
if(cursorPos.x < 0 || cursorPos.y < 0 || cursorPos.z < 0){
|
||||
return;
|
||||
}
|
||||
CommonEntityUtils.serverSpawnBasicObject(realm, cursorPos, Globals.clientState.selectedSpawntype.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.server.ai.trees.test.BlockerAITree;
|
||||
import electrosphere.server.ai.trees.character.StandardCharacterTree;
|
||||
import electrosphere.server.ai.trees.creature.AttackerAITree;
|
||||
import electrosphere.server.ai.trees.creature.WanderTree;
|
||||
import electrosphere.server.ai.trees.hierarchy.MaslowTree;
|
||||
|
||||
/**
|
||||
@ -34,6 +35,9 @@ public class AITreeDataSerializer implements JsonDeserializer<AITreeData> {
|
||||
case StandardCharacterTree.TREE_NAME: {
|
||||
return context.deserialize(json, StandardCharacterTreeData.class);
|
||||
}
|
||||
case WanderTree.TREE_NAME: {
|
||||
return context.deserialize(json, WanderTreeData.class);
|
||||
}
|
||||
}
|
||||
|
||||
LoggerInterface.loggerEngine.ERROR(new IllegalArgumentException("JSON Object provided to AITreeDataSerializer that cannot deserialize into a tree data type cleanly " + json.getAsJsonObject().get("name").getAsString()));
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package electrosphere.data.entity.creature.ai;
|
||||
|
||||
import electrosphere.server.ai.trees.creature.WanderTree;
|
||||
|
||||
/**
|
||||
* Tree data for controlling a wandering creature tree
|
||||
*/
|
||||
public class WanderTreeData implements AITreeData {
|
||||
|
||||
/**
|
||||
* The name of the tree
|
||||
*/
|
||||
String name;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return WanderTree.TREE_NAME;
|
||||
}
|
||||
|
||||
}
|
||||
@ -226,7 +226,7 @@ public class Actor {
|
||||
this.lodLevel == Actor.LOD_LEVEL_STATIC ||
|
||||
//actor doesn't have anything complicated render-wise (animations, custom textures, etc)
|
||||
(
|
||||
this.animationData.isPlayingAnimation() &&
|
||||
!this.animationData.isPlayingAnimation() &&
|
||||
this.meshMask.getBlockedMeshes().size() == 0 &&
|
||||
this.textureMap == null &&
|
||||
this.uniformMap.isEmpty() &&
|
||||
|
||||
@ -6,6 +6,7 @@ import electrosphere.data.entity.creature.ai.AITreeData;
|
||||
import electrosphere.data.entity.creature.ai.AttackerTreeData;
|
||||
import electrosphere.data.entity.creature.ai.BlockerTreeData;
|
||||
import electrosphere.data.entity.creature.ai.StandardCharacterTreeData;
|
||||
import electrosphere.data.entity.creature.ai.WanderTreeData;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityDataStrings;
|
||||
import electrosphere.entity.state.movement.groundmove.ServerGroundMovementTree;
|
||||
@ -15,6 +16,7 @@ import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.trees.character.StandardCharacterTree;
|
||||
import electrosphere.server.ai.trees.creature.AttackerAITree;
|
||||
import electrosphere.server.ai.trees.creature.WanderTree;
|
||||
import electrosphere.server.ai.trees.hierarchy.MaslowTree;
|
||||
import electrosphere.server.ai.trees.test.BlockerAITree;
|
||||
|
||||
@ -72,6 +74,9 @@ public class AI {
|
||||
case StandardCharacterTree.TREE_NAME: {
|
||||
rVal.rootNode = StandardCharacterTree.create((StandardCharacterTreeData) aiData);
|
||||
} break;
|
||||
case WanderTree.TREE_NAME: {
|
||||
rVal.rootNode = WanderTree.create((WanderTreeData) aiData);
|
||||
} break;
|
||||
default: {
|
||||
LoggerInterface.loggerEngine.ERROR(new IllegalArgumentException("Trying to construct ai tree with undefined data type! " + aiData.getName()));
|
||||
} break;
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
package electrosphere.server.ai.nodes.plan;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.blackboard.BlackboardKeys;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
|
||||
/**
|
||||
* Sets the move-to target position to a random nearby point
|
||||
*/
|
||||
public class TargetRandomPositionNode implements AITreeNode {
|
||||
|
||||
/**
|
||||
* The key to lookup the target under
|
||||
*/
|
||||
String targetKey;
|
||||
|
||||
double radius = 5;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param targetKey The key to lookup the target under
|
||||
*/
|
||||
public TargetRandomPositionNode(String targetKey){
|
||||
this.targetKey = targetKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard){
|
||||
Object targetRaw = blackboard.get(this.targetKey);
|
||||
if(targetRaw == null){
|
||||
Vector3d targetPos = null;
|
||||
Random rand = new Random();
|
||||
targetPos = new Vector3d(EntityUtils.getPosition(entity));
|
||||
targetPos.add(
|
||||
rand.nextFloat() * (radius * 2) - radius,
|
||||
0,
|
||||
rand.nextFloat() * (radius * 2) - radius
|
||||
);
|
||||
blackboard.put(targetKey, targetPos);
|
||||
TargetPositionNode.setMoveToTarget(blackboard, targetPos);
|
||||
}
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the move-to target of the blackboard
|
||||
* @param blackboard The blackboard
|
||||
* @param position The target position
|
||||
*/
|
||||
public static void setMoveToTarget(Blackboard blackboard, Vector3d position){
|
||||
blackboard.put(BlackboardKeys.MOVE_TO_TARGET, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the move-to target of the blackboard
|
||||
* @param blackboard The blackboard
|
||||
* @return The move-to target if it exists, null otherwise
|
||||
*/
|
||||
public static Vector3d getMoveToTarget(Blackboard blackboard){
|
||||
return (Vector3d)blackboard.get(BlackboardKeys.MOVE_TO_TARGET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the blackboard has a move to target
|
||||
* @param blackboard the blackboard
|
||||
* @return true if it has a move-to target, false otherwise
|
||||
*/
|
||||
public static boolean hasMoveToTarget(Blackboard blackboard){
|
||||
return blackboard.has(BlackboardKeys.MOVE_TO_TARGET);
|
||||
}
|
||||
|
||||
}
|
||||
@ -32,6 +32,9 @@ public class NearbyEntityService implements AIService {
|
||||
Realm realm = Globals.serverState.realmManager.getEntityRealm(entity);
|
||||
if(realm != null){
|
||||
Vector3d position = EntityUtils.getPosition(entity);
|
||||
if(position.x < 0 || position.y < 0 || position.z < 0){
|
||||
continue;
|
||||
}
|
||||
Collection<Entity> nearbyEntities = realm.getDataCellManager().entityLookup(position, NearbyEntityService.SEARCH_DIST);
|
||||
NearbyEntityService.setNearbyEntities(ai.getBlackboard(), nearbyEntities);
|
||||
}
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
package electrosphere.server.ai.trees.creature;
|
||||
|
||||
import electrosphere.data.entity.creature.ai.WanderTreeData;
|
||||
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementRelativeFacing;
|
||||
import electrosphere.server.ai.blackboard.BlackboardKeys;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.actions.move.FaceTargetNode;
|
||||
import electrosphere.server.ai.nodes.actions.move.MoveStartNode;
|
||||
import electrosphere.server.ai.nodes.actions.move.MoveStopNode;
|
||||
import electrosphere.server.ai.nodes.meta.DataDeleteNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.RandomizerNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.TimerNode;
|
||||
import electrosphere.server.ai.nodes.plan.TargetRandomPositionNode;
|
||||
|
||||
/**
|
||||
* Wanders around aimlessly
|
||||
*/
|
||||
public class WanderTree {
|
||||
|
||||
/**
|
||||
* Name of the tree
|
||||
*/
|
||||
public static final String TREE_NAME = "Wander";
|
||||
|
||||
/**
|
||||
* Creates an wander ai tree
|
||||
* @return The root node of the tree
|
||||
*/
|
||||
public static AITreeNode create(WanderTreeData wanderTreeData){
|
||||
return new SequenceNode(
|
||||
"WanderTree",
|
||||
//select action to perform
|
||||
new RandomizerNode(
|
||||
|
||||
//wait
|
||||
new SequenceNode(
|
||||
"MeleeAITree",
|
||||
new PublishStatusNode("Waiting"),
|
||||
new SucceederNode(new MoveStopNode()),
|
||||
new DataDeleteNode(BlackboardKeys.POINT_TARGET),
|
||||
new TimerNode(new SucceederNode(null), 1200)
|
||||
),
|
||||
|
||||
//move towards a random position
|
||||
new SequenceNode(
|
||||
"WanderMove",
|
||||
new PublishStatusNode("Move into wander target range"),
|
||||
new TargetRandomPositionNode(BlackboardKeys.POINT_TARGET),
|
||||
new FaceTargetNode(BlackboardKeys.MOVE_TO_TARGET),
|
||||
new SucceederNode(new MoveStartNode(MovementRelativeFacing.FORWARD)),
|
||||
new TimerNode(new SucceederNode(null), 600)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user