ecspresso
Version:
A minimal Entity-Component-System library for typescript and javascript.
5 lines (3 loc) • 5.18 kB
JavaScript
var D=((j)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(j,{get:(z,J)=>(typeof require<"u"?require:z)[J]}):j)(function(j){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+j+'" is not supported')});import{definePlugin as $}from"ecspresso";var H={Success:0,Failure:1,Running:2};function G(j,z,J){return{type:"action",name:j,tick:z,onAbort:J?.onAbort,nodeIndex:-1}}function P(j,z){return{type:"condition",name:j,check:z,nodeIndex:-1}}function T(j){return{type:"sequence",children:j,nodeIndex:-1}}function B(j){return{type:"selector",children:j,nodeIndex:-1}}function C(j,z){return{type:"parallel",children:j,successThreshold:z?.successThreshold??j.length,failureThreshold:z?.failureThreshold??j.length,nodeIndex:-1}}function m(j){return{type:"inverter",child:j,nodeIndex:-1}}function w(j,z=-1){return{type:"repeat",child:j,count:z,nodeIndex:-1}}function v(j,z){return{type:"cooldown",child:j,duration:z,nodeIndex:-1}}function q(j,z){return{type:"guard",condition:j,child:z,nodeIndex:-1}}var X=new WeakMap,Z=new WeakMap;function A(j,z){let J=0,E=[];function K(M){if(M.nodeIndex=J,E[J]=M,J++,"children"in M)for(let U of M.children)K(U);if("child"in M)K(M.child)}K(z.root);let L=Object.freeze({id:j,root:z.root,nodeCount:J});return X.set(L,E),Z.set(L,z.blackboard),L}function I(j,z){let E={...Z.get(j),...z};return{behaviorTree:{definition:j,blackboard:E,runningNodeIndex:-1,nodeState:new Float64Array(j.nodeCount),elapsedTime:0}}}function g(j,z){let J=j.getComponent(z,"behaviorTree");return J!==void 0&&J.runningNodeIndex!==-1}function p(j,z,J){let E=j.getComponent(z,"behaviorTree");if(!E)return;if(E.runningNodeIndex!==-1){let L=X.get(E.definition)?.[E.runningNodeIndex];if(L&&L.type==="action"&&L.onAbort)L.onAbort({ecs:j,entityId:z,dt:0,blackboard:E.blackboard});E.runningNodeIndex=-1}if(E.nodeState.fill(0),E.elapsedTime=0,J)Object.assign(E.blackboard,J)}function _(j,z){let E=X.get(j.definition)?.[j.runningNodeIndex];if(E&&E.type==="action")E.onAbort?.(z),z.ecs.eventBus.publish("behaviorTreeAbort",{entityId:z.entityId,nodeIndex:j.runningNodeIndex,nodeName:E.name,definitionId:j.definition.id});j.nodeState.fill(0),j.runningNodeIndex=-1}function Q(j,z,J){switch(j.type){case"condition":return j.check(J)?H.Success:H.Failure;case"action":{let E=j.tick(J);if(E===H.Running){if(z.runningNodeIndex!==-1&&z.runningNodeIndex!==j.nodeIndex)_(z,J);z.runningNodeIndex=j.nodeIndex}else if(z.runningNodeIndex===j.nodeIndex)z.runningNodeIndex=-1;return E}case"sequence":{let E=z.runningNodeIndex!==-1?z.nodeState[j.nodeIndex]??0:0;for(let K=E;K<j.children.length;K++){let L=Q(j.children[K],z,J);if(L===H.Failure)return z.nodeState[j.nodeIndex]=0,H.Failure;if(L===H.Running)return z.nodeState[j.nodeIndex]=K,H.Running}return z.nodeState[j.nodeIndex]=0,H.Success}case"selector":{for(let E=0;E<j.children.length;E++){let K=Q(j.children[E],z,J);if(K===H.Success)return H.Success;if(K===H.Running)return H.Running}return H.Failure}case"parallel":{let E=0,K=0,L=!1;for(let M=0;M<j.children.length;M++){let U=Q(j.children[M],z,J);if(U===H.Success)E++;else if(U===H.Failure)K++;else L=!0}if(E>=j.successThreshold)return H.Success;if(K>=j.failureThreshold)return H.Failure;if(L)return H.Running;return H.Failure}case"inverter":{let E=Q(j.child,z,J);if(E===H.Success)return H.Failure;if(E===H.Failure)return H.Success;return H.Running}case"repeat":{let E=z.nodeState[j.nodeIndex]??0,K=Q(j.child,z,J);if(K===H.Failure)return z.nodeState[j.nodeIndex]=0,H.Failure;if(K===H.Running)return H.Running;let L=E+1;if(j.count!==-1&&L>=j.count)return z.nodeState[j.nodeIndex]=0,H.Success;return z.nodeState[j.nodeIndex]=L,H.Running}case"cooldown":{let E=z.nodeState[j.nodeIndex]??0;if(E>0&&z.elapsedTime<E)return H.Failure;let K=Q(j.child,z,J);if(K!==H.Running)z.nodeState[j.nodeIndex]=z.elapsedTime+j.duration;return K}case"guard":{if(!j.condition(J))return H.Failure;return Q(j.child,z,J)}}}function y(j){return{defineBehaviorTree:A,action:G,condition:P,guard:q}}function k(j){let{systemGroup:z="ai",priority:J=0,phase:E="update"}=j??{};return $("behaviorTree").withComponentTypes().withEventTypes().withLabels().withGroups().install((K)=>{K.registerDispose("behaviorTree",({value:L,entityId:M})=>{if(L.runningNodeIndex!==-1){let O=X.get(L.definition)?.[L.runningNodeIndex];if(O&&O.type==="action"&&O.onAbort)O.onAbort({ecs:K,entityId:M,dt:0,blackboard:L.blackboard})}}),K.addSystem("behavior-tree-update").setPriority(J).inPhase(E).inGroup(z).addQuery("trees",{with:["behaviorTree"]}).setProcess(({queries:L,dt:M,ecs:U})=>{let O={ecs:U,entityId:0,dt:0,blackboard:{}};for(let Y of L.trees){let V=Y.components.behaviorTree;if(O.entityId=Y.id,O.dt=M,O.blackboard=V.blackboard,V.elapsedTime+=M,Q(V.definition.root,V,O)!==H.Running&&V.runningNodeIndex!==-1)_(V,O)}})})}export{T as sequence,B as selector,p as resetBehaviorTree,w as repeat,C as parallel,g as isBehaviorTreeRunning,m as inverter,q as guard,A as defineBehaviorTree,k as createBehaviorTreePlugin,y as createBehaviorTreeHelpers,I as createBehaviorTree,v as cooldown,P as condition,G as action,H as NodeStatus};
//# debugId=71DF25393349415964756E2164756E21
//# sourceMappingURL=behavior-tree.js.map