ai work
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
4b8aa104b5
commit
4b25c110ee
@ -596,9 +596,7 @@
|
|||||||
},
|
},
|
||||||
"aiTrees" : [
|
"aiTrees" : [
|
||||||
{
|
{
|
||||||
"name" : "Attacker",
|
"name" : "Maslow"
|
||||||
"aggroRange" : 10,
|
|
||||||
"attackRange" : 0.8
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"cameraData" : {
|
"cameraData" : {
|
||||||
|
|||||||
@ -1627,6 +1627,7 @@ Blocks stack
|
|||||||
Item tag adjustments
|
Item tag adjustments
|
||||||
Pine tree loot pool update
|
Pine tree loot pool update
|
||||||
DB characters store toolbar items
|
DB characters store toolbar items
|
||||||
|
Scaffolding for new macro-cognizating ai approach
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
package electrosphere.client.ui.menu.debug;
|
package electrosphere.client.ui.menu.debug;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
||||||
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
|
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
|
||||||
import electrosphere.server.ai.AI;
|
import electrosphere.server.ai.AI;
|
||||||
|
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
||||||
import imgui.ImGui;
|
import imgui.ImGui;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,6 +40,15 @@ public class ImGuiAI {
|
|||||||
Globals.aiManager.setActive(!Globals.aiManager.isActive());
|
Globals.aiManager.setActive(!Globals.aiManager.isActive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int serverIdForClientEntity = Globals.clientSceneWrapper.mapClientToServerId(Globals.playerEntity.getId());
|
||||||
|
Entity serverPlayerEntity = EntityLookupUtils.getEntityById(serverIdForClientEntity);
|
||||||
|
AI playerAi = AI.getAI(serverPlayerEntity);
|
||||||
|
ImGui.text("AI applied to player entity: " + playerAi.isApplyToPlayer());
|
||||||
|
if(ImGui.button("Toggle AI on player entity")){
|
||||||
|
playerAi.setApplyToPlayer(!playerAi.isApplyToPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
if(ImGui.collapsingHeader("Statuses")){
|
if(ImGui.collapsingHeader("Statuses")){
|
||||||
for(AI ai : Globals.aiManager.getAIList()){
|
for(AI ai : Globals.aiManager.getAIList()){
|
||||||
ImGui.text(ai.getParent().getId() + " - " + ai.getStatus());
|
ImGui.text(ai.getParent().getId() + " - " + ai.getStatus());
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import electrosphere.logger.LoggerInterface;
|
|||||||
import electrosphere.server.ai.blackboard.Blackboard;
|
import electrosphere.server.ai.blackboard.Blackboard;
|
||||||
import electrosphere.server.ai.nodes.AITreeNode;
|
import electrosphere.server.ai.nodes.AITreeNode;
|
||||||
import electrosphere.server.ai.trees.creature.AttackerAITree;
|
import electrosphere.server.ai.trees.creature.AttackerAITree;
|
||||||
|
import electrosphere.server.ai.trees.hierarchy.MaslowTree;
|
||||||
import electrosphere.server.ai.trees.test.BlockerAITree;
|
import electrosphere.server.ai.trees.test.BlockerAITree;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,6 +48,11 @@ public class AI {
|
|||||||
*/
|
*/
|
||||||
List<AITreeNode> evaluatedNodes = new LinkedList<AITreeNode>();
|
List<AITreeNode> evaluatedNodes = new LinkedList<AITreeNode>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks whether this should apply even if there is a controlling player
|
||||||
|
*/
|
||||||
|
boolean applyToPlayer = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The status of the ai
|
* The status of the ai
|
||||||
*/
|
*/
|
||||||
@ -69,6 +75,9 @@ public class AI {
|
|||||||
case AttackerAITree.TREE_NAME: {
|
case AttackerAITree.TREE_NAME: {
|
||||||
rVal.rootNode = AttackerAITree.create((AttackerTreeData) aiData);
|
rVal.rootNode = AttackerAITree.create((AttackerTreeData) aiData);
|
||||||
} break;
|
} break;
|
||||||
|
case MaslowTree.TREE_NAME: {
|
||||||
|
rVal.rootNode = MaslowTree.create();
|
||||||
|
} break;
|
||||||
default: {
|
default: {
|
||||||
LoggerInterface.loggerEngine.ERROR(new IllegalArgumentException("Trying to construct ai tree with undefined data type! " + aiData.getName()));
|
LoggerInterface.loggerEngine.ERROR(new IllegalArgumentException("Trying to construct ai tree with undefined data type! " + aiData.getName()));
|
||||||
} break;
|
} break;
|
||||||
@ -137,7 +146,7 @@ public class AI {
|
|||||||
* @return true if should simulate, false otherwise
|
* @return true if should simulate, false otherwise
|
||||||
*/
|
*/
|
||||||
private boolean shouldExecute(){
|
private boolean shouldExecute(){
|
||||||
return !CreatureUtils.hasControllerPlayerId(this.parent);
|
return this.applyToPlayer || !CreatureUtils.hasControllerPlayerId(this.parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,4 +174,22 @@ public class AI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this should apply ai behavior even if the entity is controlled by a player
|
||||||
|
* @return true if it should always apply ai behavior, false if it should defer to player
|
||||||
|
*/
|
||||||
|
public boolean isApplyToPlayer() {
|
||||||
|
return applyToPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether this should apply ai behavior even if the entity is controlled by a player
|
||||||
|
* @param applyToPlayer true if it sohuld always apply ai behavior, false if it should defer to player
|
||||||
|
*/
|
||||||
|
public void setApplyToPlayer(boolean applyToPlayer) {
|
||||||
|
this.applyToPlayer = applyToPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
package electrosphere.server.ai.nodes.checks.macro;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.state.server.ServerCharacterData;
|
||||||
|
import electrosphere.server.ai.blackboard.Blackboard;
|
||||||
|
import electrosphere.server.ai.nodes.AITreeNode;
|
||||||
|
import electrosphere.server.macro.character.Character;
|
||||||
|
import electrosphere.server.macro.character.CharacterUtils;
|
||||||
|
import electrosphere.server.macro.structure.Structure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the character has shelter
|
||||||
|
*/
|
||||||
|
public class HasShelter implements AITreeNode {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
|
||||||
|
ServerCharacterData serverCharacterData = ServerCharacterData.getServerCharacterData(entity);
|
||||||
|
Character character = Globals.macroData.getCharacter(serverCharacterData.getCharacterId());
|
||||||
|
Structure shelter = CharacterUtils.getShelter(character);
|
||||||
|
if(shelter == null){
|
||||||
|
return AITreeNodeResult.FAILURE;
|
||||||
|
}
|
||||||
|
return AITreeNodeResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package electrosphere.server.ai.nodes.checks.macro;
|
||||||
|
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.state.server.ServerCharacterData;
|
||||||
|
import electrosphere.server.ai.blackboard.Blackboard;
|
||||||
|
import electrosphere.server.ai.nodes.AITreeNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this entity is a character
|
||||||
|
*/
|
||||||
|
public class IsCharacterNode implements AITreeNode {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
|
||||||
|
if(ServerCharacterData.hasServerCharacterDataTree(entity)){
|
||||||
|
return AITreeNodeResult.SUCCESS;
|
||||||
|
}
|
||||||
|
return AITreeNodeResult.FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package electrosphere.server.ai.trees.hierarchy;
|
||||||
|
|
||||||
|
import electrosphere.server.ai.nodes.AITreeNode;
|
||||||
|
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||||
|
import electrosphere.server.ai.trees.hierarchy.safety.MaslowSafetyTree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arranges goals based on an approximation of Maslow's hierarchy of needs
|
||||||
|
*/
|
||||||
|
public class MaslowTree {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the tree
|
||||||
|
*/
|
||||||
|
public static final String TREE_NAME = "Maslow";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an attacker ai tree
|
||||||
|
* @return The root node of the tree
|
||||||
|
*/
|
||||||
|
public static AITreeNode create(){
|
||||||
|
return new SequenceNode(
|
||||||
|
MaslowSafetyTree.create()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package electrosphere.server.ai.trees.hierarchy.safety;
|
||||||
|
|
||||||
|
import electrosphere.server.ai.nodes.AITreeNode;
|
||||||
|
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tree that causes the entity to engage in combat when it determines it needs to in order to maintain its safety
|
||||||
|
*/
|
||||||
|
public class CombatTree {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the tree
|
||||||
|
*/
|
||||||
|
public static final String TREE_NAME = "CombatTree";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a combat tree
|
||||||
|
* @return The root node of the tree
|
||||||
|
*/
|
||||||
|
public static AITreeNode create(){
|
||||||
|
return new SucceederNode(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package electrosphere.server.ai.trees.hierarchy.safety;
|
||||||
|
|
||||||
|
import electrosphere.server.ai.nodes.AITreeNode;
|
||||||
|
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tree that causes the entity to flee in terror if it deems it needs to
|
||||||
|
*/
|
||||||
|
public class FleeTree {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the tree
|
||||||
|
*/
|
||||||
|
public static final String TREE_NAME = "FleeTree";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an flee tree
|
||||||
|
* @return The root node of the tree
|
||||||
|
*/
|
||||||
|
public static AITreeNode create(){
|
||||||
|
return new SucceederNode(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package electrosphere.server.ai.trees.hierarchy.safety;
|
||||||
|
|
||||||
|
import electrosphere.server.ai.nodes.AITreeNode;
|
||||||
|
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||||
|
import electrosphere.server.ai.trees.hierarchy.safety.shelter.ShelterTree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tree that runs all of the tier 1 maslow need trees
|
||||||
|
*/
|
||||||
|
public class MaslowSafetyTree {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the tree
|
||||||
|
*/
|
||||||
|
public static final String TREE_NAME = "MaslowSafetyTree";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a tier 1 maslow tree
|
||||||
|
* @return The root node of the tree
|
||||||
|
*/
|
||||||
|
public static AITreeNode create(){
|
||||||
|
return new SequenceNode(
|
||||||
|
FleeTree.create(),
|
||||||
|
CombatTree.create(),
|
||||||
|
ShelterTree.create()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
package electrosphere.server.ai.trees.hierarchy.safety.shelter;
|
||||||
|
|
||||||
|
import electrosphere.server.ai.nodes.AITreeNode;
|
||||||
|
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tree for constructing shelter
|
||||||
|
*/
|
||||||
|
public class ConstructShelterTree {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the tree
|
||||||
|
*/
|
||||||
|
public static final String TREE_NAME = "ConstructShelterTree";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a construct shelter tree
|
||||||
|
* @return The root node of the tree
|
||||||
|
*/
|
||||||
|
public static AITreeNode create(){
|
||||||
|
return new SucceederNode(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
package electrosphere.server.ai.trees.hierarchy.safety.shelter;
|
||||||
|
|
||||||
|
import electrosphere.server.ai.nodes.AITreeNode;
|
||||||
|
import electrosphere.server.ai.nodes.checks.macro.HasShelter;
|
||||||
|
import electrosphere.server.ai.nodes.checks.macro.IsCharacterNode;
|
||||||
|
import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
|
||||||
|
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tree that causes the entity to try to secure shelter
|
||||||
|
*/
|
||||||
|
public class ShelterTree {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the tree
|
||||||
|
*/
|
||||||
|
public static final String TREE_NAME = "ShelterTree";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a shelter tree
|
||||||
|
* @return The root node of the tree
|
||||||
|
*/
|
||||||
|
public static AITreeNode create(){
|
||||||
|
return new SequenceNode(
|
||||||
|
//make sure that this entity actually cares about shelter
|
||||||
|
new SequenceNode(
|
||||||
|
//if this is a character
|
||||||
|
new IsCharacterNode()
|
||||||
|
),
|
||||||
|
//now that we know the entity cares about shelter, check if they have shelter
|
||||||
|
new SequenceNode(
|
||||||
|
//if has shelter..
|
||||||
|
new SelectorNode(
|
||||||
|
new SequenceNode(
|
||||||
|
new HasShelter(),
|
||||||
|
//does not have shelter
|
||||||
|
ConstructShelterTree.create()
|
||||||
|
),
|
||||||
|
new SequenceNode(
|
||||||
|
//already has shelter
|
||||||
|
//TODO: check environment (ie time of day) to see if we should return to shelter
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -302,4 +302,18 @@ public class MacroData {
|
|||||||
return blockers;
|
return blockers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a character by its id
|
||||||
|
* @param id The id
|
||||||
|
* @return The character if it exists, null otherwise
|
||||||
|
*/
|
||||||
|
public Character getCharacter(int id){
|
||||||
|
for(Character character : this.characters){
|
||||||
|
if(character.getId() == id){
|
||||||
|
return character;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user