ai tool equipping
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
f0ff713413
commit
af0e30dd95
@ -200,7 +200,8 @@
|
||||
"GRAVITY",
|
||||
"MELEE",
|
||||
"TARGETABLE",
|
||||
"OUTLINE"
|
||||
"OUTLINE",
|
||||
"AXE"
|
||||
],
|
||||
"graphicsTemplate": {
|
||||
"model": {
|
||||
|
||||
@ -1636,6 +1636,8 @@ Many new AI trees
|
||||
- AI can harvest entities
|
||||
- AI can pick up items
|
||||
- AI can craft
|
||||
- AI can equip tools
|
||||
- AI can fell trees
|
||||
|
||||
|
||||
|
||||
|
||||
@ -358,13 +358,15 @@ public class ClientAttackTree implements BehaviorTree {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(this.currentMove.getActiveBones() != null && HitboxCollectionState.hasHitboxState(this.parent)){
|
||||
HitboxCollectionState hitboxCollectionState = HitboxCollectionState.getHitboxState(this.parent);
|
||||
for(String boneName : this.currentMove.getActiveBones()){
|
||||
List<HitboxState> hitboxes = hitboxCollectionState.getHitboxes(boneName);
|
||||
for(HitboxState hitbox : hitboxes){
|
||||
if(hitbox.getType() == HitboxType.HIT){
|
||||
hitbox.setActive(true);
|
||||
if(this.currentMove != null){
|
||||
if(this.currentMove.getActiveBones() != null && HitboxCollectionState.hasHitboxState(this.parent)){
|
||||
HitboxCollectionState hitboxCollectionState = HitboxCollectionState.getHitboxState(this.parent);
|
||||
for(String boneName : this.currentMove.getActiveBones()){
|
||||
List<HitboxState> hitboxes = hitboxCollectionState.getHitboxes(boneName);
|
||||
for(HitboxState hitbox : hitboxes){
|
||||
if(hitbox.getType() == HitboxType.HIT){
|
||||
hitbox.setActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -382,13 +384,15 @@ public class ClientAttackTree implements BehaviorTree {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(this.currentMove.getActiveBones() != null && HitboxCollectionState.hasHitboxState(this.parent)){
|
||||
HitboxCollectionState hitboxCollectionState = HitboxCollectionState.getHitboxState(this.parent);
|
||||
for(String boneName : this.currentMove.getActiveBones()){
|
||||
List<HitboxState> hitboxes = hitboxCollectionState.getHitboxes(boneName);
|
||||
for(HitboxState hitbox : hitboxes){
|
||||
if(hitbox.getType() == HitboxType.HIT){
|
||||
hitbox.setActive(false);
|
||||
if(this.currentMove != null){
|
||||
if(this.currentMove.getActiveBones() != null && HitboxCollectionState.hasHitboxState(this.parent)){
|
||||
HitboxCollectionState hitboxCollectionState = HitboxCollectionState.getHitboxState(this.parent);
|
||||
for(String boneName : this.currentMove.getActiveBones()){
|
||||
List<HitboxState> hitboxes = hitboxCollectionState.getHitboxes(boneName);
|
||||
for(HitboxState hitbox : hitboxes){
|
||||
if(hitbox.getType() == HitboxType.HIT){
|
||||
hitbox.setActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -406,13 +410,15 @@ public class ClientAttackTree implements BehaviorTree {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(this.currentMove.getActiveBones() != null && HitboxCollectionState.hasHitboxState(this.parent)){
|
||||
HitboxCollectionState hitboxCollectionState = HitboxCollectionState.getHitboxState(this.parent);
|
||||
for(String boneName : this.currentMove.getActiveBones()){
|
||||
List<HitboxState> hitboxes = hitboxCollectionState.getHitboxes(boneName);
|
||||
for(HitboxState hitbox : hitboxes){
|
||||
if(hitbox.getType() == HitboxType.HIT){
|
||||
hitbox.setActive(false);
|
||||
if(this.currentMove != null){
|
||||
if(this.currentMove.getActiveBones() != null && HitboxCollectionState.hasHitboxState(this.parent)){
|
||||
HitboxCollectionState hitboxCollectionState = HitboxCollectionState.getHitboxState(this.parent);
|
||||
for(String boneName : this.currentMove.getActiveBones()){
|
||||
List<HitboxState> hitboxes = hitboxCollectionState.getHitboxes(boneName);
|
||||
for(HitboxState hitbox : hitboxes){
|
||||
if(hitbox.getType() == HitboxType.HIT){
|
||||
hitbox.setActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
package electrosphere.server.ai.nodes.actions.inventory;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.state.equip.ServerToolbarState;
|
||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
import electrosphere.entity.state.inventory.RelationalInventoryState;
|
||||
import electrosphere.entity.state.inventory.UnrelationalInventoryState;
|
||||
import electrosphere.entity.types.common.CommonEntityUtils;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
|
||||
/**
|
||||
* Tries to equip a type of item to the toolbar and select that item in the toolbar
|
||||
*/
|
||||
public class EquipToolbarNode implements AITreeNode {
|
||||
|
||||
/**
|
||||
* Key to lookup the item type under
|
||||
*/
|
||||
String itemTypeKey;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param itemTypeKey The blackboard key to lookup the item type under
|
||||
*/
|
||||
public EquipToolbarNode(String itemTypeKey){
|
||||
this.itemTypeKey = itemTypeKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
|
||||
String targetItemType = (String)blackboard.get(itemTypeKey);
|
||||
|
||||
//check if that item type is already equipped
|
||||
ServerToolbarState serverToolbarState = ServerToolbarState.getServerToolbarState(entity);
|
||||
if(serverToolbarState.getRealWorldItem() != null){
|
||||
Entity realWorldItem = serverToolbarState.getRealWorldItem();
|
||||
String type = CommonEntityUtils.getEntitySubtype(realWorldItem);
|
||||
if(type.equals(targetItemType)){
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
//check if this item type is already in toolbar and we can just swap to it
|
||||
if(InventoryUtils.hasToolbarInventory(entity)){
|
||||
RelationalInventoryState toolbarInventory = InventoryUtils.getToolbarInventory(entity);
|
||||
for(Entity itemEnt : toolbarInventory.getItems()){
|
||||
if(itemEnt == null){
|
||||
continue;
|
||||
}
|
||||
String type = CommonEntityUtils.getEntitySubtype(itemEnt);
|
||||
if(type.equals(targetItemType)){
|
||||
String slotId = toolbarInventory.getItemSlot(itemEnt);
|
||||
serverToolbarState.attemptChangeSelection(Integer.parseInt(slotId));
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//make sure we have a free toolbar slot
|
||||
int freeToolbarSlot = 0;
|
||||
if(InventoryUtils.hasToolbarInventory(entity)){
|
||||
RelationalInventoryState toolbarInventory = InventoryUtils.getToolbarInventory(entity);
|
||||
int i = 0;
|
||||
for(Entity itemEnt : toolbarInventory.getItems()){
|
||||
if(itemEnt == null){
|
||||
freeToolbarSlot = i;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
//check if this item type is in the natural inventory, if it is, try to equip it
|
||||
if(InventoryUtils.hasNaturalInventory(entity)){
|
||||
UnrelationalInventoryState naturalInventory = InventoryUtils.getNaturalInventory(entity);
|
||||
//find matching natural item
|
||||
Entity naturalItem = null;
|
||||
for(Entity itemEnt : naturalInventory.getItems()){
|
||||
String type = CommonEntityUtils.getEntitySubtype(itemEnt);
|
||||
if(type.equals(targetItemType)){
|
||||
naturalItem = itemEnt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(naturalItem != null){
|
||||
serverToolbarState.attemptEquip(naturalItem, freeToolbarSlot);
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,8 +5,6 @@ import java.util.stream.Collectors;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
import electrosphere.entity.state.inventory.RelationalInventoryState;
|
||||
import electrosphere.entity.state.inventory.UnrelationalInventoryState;
|
||||
import electrosphere.entity.types.common.CommonEntityUtils;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.blackboard.BlackboardKeys;
|
||||
@ -33,11 +31,6 @@ public class InventoryContainsNode implements AITreeNode {
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
|
||||
|
||||
//error checking
|
||||
if(!InventoryContainsNode.hasInventoryCheckType(blackboard)){
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
|
||||
//key isn't defined
|
||||
if(!blackboard.has(key)){
|
||||
return AITreeNodeResult.FAILURE;
|
||||
@ -46,31 +39,11 @@ public class InventoryContainsNode implements AITreeNode {
|
||||
//type to look for
|
||||
String type = (String)blackboard.get(this.key);
|
||||
|
||||
//check equip inventory if it exists
|
||||
if(InventoryUtils.hasEquipInventory(entity)){
|
||||
RelationalInventoryState equipInventory = InventoryUtils.getEquipInventory(entity);
|
||||
if(equipInventory.getSlots().contains(type)){
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
List<Entity> items = InventoryUtils.getAllInventoryItems(entity);
|
||||
List<String> itemIds = items.stream().map((Entity itemEnt) -> {return CommonEntityUtils.getEntitySubtype(itemEnt);}).collect(Collectors.toList());
|
||||
if(itemIds.contains(type)){
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
|
||||
//check natural inventory if it exists
|
||||
if(InventoryUtils.hasNaturalInventory(entity)){
|
||||
UnrelationalInventoryState naturalInventory = InventoryUtils.getNaturalInventory(entity);
|
||||
List<String> itemIds = naturalInventory.getItems().stream().map((Entity itemEnt) -> {return CommonEntityUtils.getEntitySubtype(entity);}).collect(Collectors.toList());
|
||||
if(itemIds.contains(type)){
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
//check toolbar inventory if it exists
|
||||
if(InventoryUtils.hasToolbarInventory(entity)){
|
||||
RelationalInventoryState toolbarInventory = InventoryUtils.getToolbarInventory(entity);
|
||||
if(toolbarInventory.getSlots().contains(type)){
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ public class TargetRangeCheckNode implements AITreeNode {
|
||||
Object targetRaw = blackboard.get(this.targetKey);
|
||||
Vector3d targetPos = null;
|
||||
if(targetRaw == null){
|
||||
throw new Error("Target undefined!");
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
if(targetRaw instanceof Vector3d){
|
||||
targetPos = (Vector3d)targetRaw;
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
package electrosphere.server.ai.nodes.meta;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
|
||||
/**
|
||||
* Stores a piece of data into a blackboard
|
||||
*/
|
||||
public class DataStorageNode implements AITreeNode {
|
||||
|
||||
/**
|
||||
* The data to store in the key
|
||||
*/
|
||||
Object data;
|
||||
|
||||
/**
|
||||
* The key to push data into
|
||||
*/
|
||||
String destinationKey;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param destinationKey The key to push data into
|
||||
* @param data The data to store at the key
|
||||
*/
|
||||
public DataStorageNode(String destinationKey, Object data){
|
||||
this.data = data;
|
||||
this.destinationKey = destinationKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
|
||||
blackboard.put(this.destinationKey, this.data);
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
@ -44,6 +44,8 @@ public class SolveSourcingTreeNode implements AITreeNode {
|
||||
//set the type to harvest if this is a harvest type
|
||||
if(sourcingData.getHarvestTargets().size() > 0){
|
||||
HarvestNode.setHarvestTargetType(blackboard, sourcingData.getHarvestTargets().get(0).getId());
|
||||
} else if(sourcingData.getTrees().size() > 0){
|
||||
HarvestNode.setHarvestTargetType(blackboard, sourcingData.getTrees().get(0).getId());
|
||||
}
|
||||
SolveSourcingTreeNode.setItemSourcingData(blackboard, sourcingData);
|
||||
SolveSourcingTreeNode.setItemTargetCategory(blackboard, sourcingData.getGoalItem());
|
||||
|
||||
@ -15,6 +15,7 @@ import electrosphere.server.ai.nodes.meta.decorators.RunnerNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
||||
import electrosphere.server.ai.nodes.plan.SolveSourcingTreeNode;
|
||||
import electrosphere.server.ai.nodes.plan.TargetEntityCategoryNode;
|
||||
import electrosphere.server.ai.trees.creature.melee.FellTree;
|
||||
|
||||
/**
|
||||
* A tree to acquire an item
|
||||
@ -67,7 +68,8 @@ public class AcquireItemTree {
|
||||
new PublishStatusNode("Fell a tree"),
|
||||
//check if we should be sourcing this from felling a tree
|
||||
new SourcingTypeNode(SourcingType.TREE, blackboardKey),
|
||||
//TODO: logic to fell a tree
|
||||
new TargetEntityCategoryNode(BlackboardKeys.HARVEST_TARGET_TYPE),
|
||||
FellTree.create(BlackboardKeys.ENTITY_TARGET),
|
||||
new RunnerNode(null)
|
||||
)
|
||||
),
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
package electrosphere.server.ai.trees.creature.inventory;
|
||||
|
||||
import electrosphere.server.ai.blackboard.BlackboardKeys;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.actions.inventory.EquipToolbarNode;
|
||||
import electrosphere.server.ai.nodes.checks.inventory.InventoryContainsNode;
|
||||
import electrosphere.server.ai.nodes.meta.DataTransferNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
|
||||
|
||||
/**
|
||||
* Tries to equip an item into the toolbar
|
||||
*/
|
||||
public class EquipToolbarTree {
|
||||
|
||||
/**
|
||||
* Name of the tree
|
||||
*/
|
||||
public static final String TREE_NAME = "EquipToolbar";
|
||||
|
||||
/**
|
||||
* Creates an equip toolbar tree
|
||||
* @param itemType The type of item to try to equip in the toolbar
|
||||
* @return The root node of the tree
|
||||
*/
|
||||
public static AITreeNode create(String targetKey){
|
||||
return new SequenceNode(
|
||||
new PublishStatusNode("Equip an item"),
|
||||
//check that we have this type of item
|
||||
new DataTransferNode(targetKey, BlackboardKeys.INVENTORY_CHECK_TYPE),
|
||||
new InventoryContainsNode(BlackboardKeys.INVENTORY_CHECK_TYPE),
|
||||
|
||||
//try to equip the item to the toolbar
|
||||
new EquipToolbarNode(BlackboardKeys.INVENTORY_CHECK_TYPE)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
package electrosphere.server.ai.trees.creature.melee;
|
||||
|
||||
import electrosphere.game.data.item.ItemIdStrings;
|
||||
import electrosphere.server.ai.blackboard.BlackboardKeys;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.AITreeNode.AITreeNodeResult;
|
||||
import electrosphere.server.ai.nodes.actions.combat.AttackStartNode;
|
||||
import electrosphere.server.ai.nodes.actions.move.FaceTargetNode;
|
||||
import electrosphere.server.ai.nodes.actions.move.MoveStopNode;
|
||||
import electrosphere.server.ai.nodes.checks.IsMovingNode;
|
||||
import electrosphere.server.ai.nodes.checks.spatial.TargetRangeCheckNode;
|
||||
import electrosphere.server.ai.nodes.meta.DataStorageNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.RunnerNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.TimerNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.UntilNode;
|
||||
import electrosphere.server.ai.trees.creature.MoveToTarget;
|
||||
import electrosphere.server.ai.trees.creature.inventory.EquipToolbarTree;
|
||||
|
||||
/**
|
||||
* A behavior tree to fell a tree entity
|
||||
*/
|
||||
public class FellTree {
|
||||
|
||||
/**
|
||||
* Name of the tree
|
||||
*/
|
||||
public static final String TREE_NAME = "Fell";
|
||||
|
||||
/**
|
||||
* Distance to start attacking at
|
||||
*/
|
||||
static final float FELL_RANGE = 0.5f;
|
||||
|
||||
/**
|
||||
* Creates a fell tree
|
||||
* @param targetKey The key to lookup the target entity under
|
||||
* @return The root node of the tree
|
||||
*/
|
||||
public static AITreeNode create(String targetKey){
|
||||
|
||||
return new SequenceNode(
|
||||
//preconditions here
|
||||
new DataStorageNode(BlackboardKeys.INVENTORY_CHECK_TYPE, ItemIdStrings.ITEM_STONE_AXE),
|
||||
EquipToolbarTree.create(BlackboardKeys.INVENTORY_CHECK_TYPE),
|
||||
|
||||
//perform different actions based on distance to target
|
||||
new SelectorNode(
|
||||
|
||||
//in attack range
|
||||
new SequenceNode(
|
||||
//check if in range of target
|
||||
new TargetRangeCheckNode(FellTree.FELL_RANGE, targetKey),
|
||||
//stop walking now that we're in range
|
||||
new PublishStatusNode("Slowing down"),
|
||||
new MoveStopNode(),
|
||||
new UntilNode(AITreeNodeResult.FAILURE, new IsMovingNode()),
|
||||
|
||||
//attack
|
||||
new SequenceNode(
|
||||
new PublishStatusNode("Attacking"),
|
||||
new FaceTargetNode(BlackboardKeys.ENTITY_TARGET),
|
||||
new AttackStartNode(),
|
||||
new TimerNode(new RunnerNode(null), 300)
|
||||
)
|
||||
),
|
||||
|
||||
//move to target
|
||||
MoveToTarget.create(FellTree.FELL_RANGE, targetKey),
|
||||
|
||||
//movement succeeded, but failed to attack -- tree is currently running
|
||||
new RunnerNode(null)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user