@alife-sdk/ai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +385 -0
- package/dist/animation/AnimationController.d.ts +60 -0
- package/dist/animation/AnimationController.d.ts.map +1 -0
- package/dist/animation/AnimationController.js +71 -0
- package/dist/animation/AnimationController.js.map +1 -0
- package/dist/animation/AnimationSelector.d.ts +108 -0
- package/dist/animation/AnimationSelector.d.ts.map +1 -0
- package/dist/animation/AnimationSelector.js +194 -0
- package/dist/animation/AnimationSelector.js.map +1 -0
- package/dist/animation/index.d.ts +5 -0
- package/dist/animation/index.d.ts.map +1 -0
- package/dist/animation/index.js +4 -0
- package/dist/animation/index.js.map +1 -0
- package/dist/combat/CombatTransitionChain.d.ts +95 -0
- package/dist/combat/CombatTransitionChain.d.ts.map +1 -0
- package/dist/combat/CombatTransitionChain.js +117 -0
- package/dist/combat/CombatTransitionChain.js.map +1 -0
- package/dist/combat/LoadoutBuilder.d.ts +83 -0
- package/dist/combat/LoadoutBuilder.d.ts.map +1 -0
- package/dist/combat/LoadoutBuilder.js +213 -0
- package/dist/combat/LoadoutBuilder.js.map +1 -0
- package/dist/combat/MonsterAbilityData.d.ts +97 -0
- package/dist/combat/MonsterAbilityData.d.ts.map +1 -0
- package/dist/combat/MonsterAbilityData.js +94 -0
- package/dist/combat/MonsterAbilityData.js.map +1 -0
- package/dist/combat/WeaponSelector.d.ts +47 -0
- package/dist/combat/WeaponSelector.d.ts.map +1 -0
- package/dist/combat/WeaponSelector.js +180 -0
- package/dist/combat/WeaponSelector.js.map +1 -0
- package/dist/combat/index.d.ts +9 -0
- package/dist/combat/index.d.ts.map +1 -0
- package/dist/combat/index.js +6 -0
- package/dist/combat/index.js.map +1 -0
- package/dist/conditions/ConditionBank.d.ts +179 -0
- package/dist/conditions/ConditionBank.d.ts.map +1 -0
- package/dist/conditions/ConditionBank.js +220 -0
- package/dist/conditions/ConditionBank.js.map +1 -0
- package/dist/conditions/index.d.ts +3 -0
- package/dist/conditions/index.d.ts.map +1 -0
- package/dist/conditions/index.js +3 -0
- package/dist/conditions/index.js.map +1 -0
- package/dist/config/createDefaultAIConfig.d.ts +25 -0
- package/dist/config/createDefaultAIConfig.d.ts.map +1 -0
- package/dist/config/createDefaultAIConfig.js +147 -0
- package/dist/config/createDefaultAIConfig.js.map +1 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/cover/CoverAccessAdapter.d.ts +61 -0
- package/dist/cover/CoverAccessAdapter.d.ts.map +1 -0
- package/dist/cover/CoverAccessAdapter.js +74 -0
- package/dist/cover/CoverAccessAdapter.js.map +1 -0
- package/dist/cover/CoverEvaluators.d.ts +43 -0
- package/dist/cover/CoverEvaluators.d.ts.map +1 -0
- package/dist/cover/CoverEvaluators.js +193 -0
- package/dist/cover/CoverEvaluators.js.map +1 -0
- package/dist/cover/CoverLockRegistry.d.ts +50 -0
- package/dist/cover/CoverLockRegistry.d.ts.map +1 -0
- package/dist/cover/CoverLockRegistry.js +164 -0
- package/dist/cover/CoverLockRegistry.js.map +1 -0
- package/dist/cover/CoverRecommender.d.ts +32 -0
- package/dist/cover/CoverRecommender.d.ts.map +1 -0
- package/dist/cover/CoverRecommender.js +45 -0
- package/dist/cover/CoverRecommender.js.map +1 -0
- package/dist/cover/CoverRegistry.d.ts +97 -0
- package/dist/cover/CoverRegistry.d.ts.map +1 -0
- package/dist/cover/CoverRegistry.js +223 -0
- package/dist/cover/CoverRegistry.js.map +1 -0
- package/dist/cover/ICoverEvaluator.d.ts +15 -0
- package/dist/cover/ICoverEvaluator.d.ts.map +1 -0
- package/dist/cover/ICoverEvaluator.js +4 -0
- package/dist/cover/ICoverEvaluator.js.map +1 -0
- package/dist/cover/ICoverLockConfig.d.ts +83 -0
- package/dist/cover/ICoverLockConfig.d.ts.map +1 -0
- package/dist/cover/ICoverLockConfig.js +21 -0
- package/dist/cover/ICoverLockConfig.js.map +1 -0
- package/dist/cover/LoopholeGenerator.d.ts +44 -0
- package/dist/cover/LoopholeGenerator.d.ts.map +1 -0
- package/dist/cover/LoopholeGenerator.js +96 -0
- package/dist/cover/LoopholeGenerator.js.map +1 -0
- package/dist/cover/index.d.ts +11 -0
- package/dist/cover/index.d.ts.map +1 -0
- package/dist/cover/index.js +8 -0
- package/dist/cover/index.js.map +1 -0
- package/dist/goap/EvadeHazardAction.d.ts +34 -0
- package/dist/goap/EvadeHazardAction.d.ts.map +1 -0
- package/dist/goap/EvadeHazardAction.js +48 -0
- package/dist/goap/EvadeHazardAction.js.map +1 -0
- package/dist/goap/GOAPController.d.ts +114 -0
- package/dist/goap/GOAPController.d.ts.map +1 -0
- package/dist/goap/GOAPController.js +191 -0
- package/dist/goap/GOAPController.js.map +1 -0
- package/dist/goap/GoalSelector.d.ts +40 -0
- package/dist/goap/GoalSelector.d.ts.map +1 -0
- package/dist/goap/GoalSelector.js +115 -0
- package/dist/goap/GoalSelector.js.map +1 -0
- package/dist/goap/IHazardZoneAccess.d.ts +16 -0
- package/dist/goap/IHazardZoneAccess.d.ts.map +1 -0
- package/dist/goap/IHazardZoneAccess.js +2 -0
- package/dist/goap/IHazardZoneAccess.js.map +1 -0
- package/dist/goap/WorldStateBuilder.d.ts +27 -0
- package/dist/goap/WorldStateBuilder.d.ts.map +1 -0
- package/dist/goap/WorldStateBuilder.js +51 -0
- package/dist/goap/WorldStateBuilder.js.map +1 -0
- package/dist/goap/index.d.ts +9 -0
- package/dist/goap/index.d.ts.map +1 -0
- package/dist/goap/index.js +6 -0
- package/dist/goap/index.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/navigation/PathSmoother.d.ts +29 -0
- package/dist/navigation/PathSmoother.d.ts.map +1 -0
- package/dist/navigation/PathSmoother.js +172 -0
- package/dist/navigation/PathSmoother.js.map +1 -0
- package/dist/navigation/RestrictedZoneManager.d.ts +83 -0
- package/dist/navigation/RestrictedZoneManager.d.ts.map +1 -0
- package/dist/navigation/RestrictedZoneManager.js +179 -0
- package/dist/navigation/RestrictedZoneManager.js.map +1 -0
- package/dist/navigation/SmoothPathFollower.d.ts +55 -0
- package/dist/navigation/SmoothPathFollower.d.ts.map +1 -0
- package/dist/navigation/SmoothPathFollower.js +132 -0
- package/dist/navigation/SmoothPathFollower.js.map +1 -0
- package/dist/navigation/SteeringBehaviors.d.ts +123 -0
- package/dist/navigation/SteeringBehaviors.d.ts.map +1 -0
- package/dist/navigation/SteeringBehaviors.js +211 -0
- package/dist/navigation/SteeringBehaviors.js.map +1 -0
- package/dist/navigation/index.d.ts +7 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +6 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/perception/NPCSensors.d.ts +129 -0
- package/dist/perception/NPCSensors.d.ts.map +1 -0
- package/dist/perception/NPCSensors.js +147 -0
- package/dist/perception/NPCSensors.js.map +1 -0
- package/dist/perception/PerceptionQuery.d.ts +65 -0
- package/dist/perception/PerceptionQuery.d.ts.map +1 -0
- package/dist/perception/PerceptionQuery.js +199 -0
- package/dist/perception/PerceptionQuery.js.map +1 -0
- package/dist/perception/index.d.ts +4 -0
- package/dist/perception/index.d.ts.map +1 -0
- package/dist/perception/index.js +4 -0
- package/dist/perception/index.js.map +1 -0
- package/dist/plugin/AIPlugin.d.ts +71 -0
- package/dist/plugin/AIPlugin.d.ts.map +1 -0
- package/dist/plugin/AIPlugin.js +134 -0
- package/dist/plugin/AIPlugin.js.map +1 -0
- package/dist/plugin/index.d.ts +3 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +3 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/ports/AIPorts.d.ts +13 -0
- package/dist/ports/AIPorts.d.ts.map +1 -0
- package/dist/ports/AIPorts.js +14 -0
- package/dist/ports/AIPorts.js.map +1 -0
- package/dist/ports/ICoverPointSource.d.ts +27 -0
- package/dist/ports/ICoverPointSource.d.ts.map +1 -0
- package/dist/ports/ICoverPointSource.js +4 -0
- package/dist/ports/ICoverPointSource.js.map +1 -0
- package/dist/ports/IPerceptionProvider.d.ts +42 -0
- package/dist/ports/IPerceptionProvider.d.ts.map +1 -0
- package/dist/ports/IPerceptionProvider.js +4 -0
- package/dist/ports/IPerceptionProvider.js.map +1 -0
- package/dist/ports/index.d.ts +4 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +3 -0
- package/dist/ports/index.js.map +1 -0
- package/dist/sound/VocalizationTypes.d.ts +57 -0
- package/dist/sound/VocalizationTypes.d.ts.map +1 -0
- package/dist/sound/VocalizationTypes.js +87 -0
- package/dist/sound/VocalizationTypes.js.map +1 -0
- package/dist/sound/index.d.ts +3 -0
- package/dist/sound/index.d.ts.map +1 -0
- package/dist/sound/index.js +3 -0
- package/dist/sound/index.js.map +1 -0
- package/dist/squad/SquadSharedTarget.d.ts +137 -0
- package/dist/squad/SquadSharedTarget.d.ts.map +1 -0
- package/dist/squad/SquadSharedTarget.js +145 -0
- package/dist/squad/SquadSharedTarget.js.map +1 -0
- package/dist/squad/SquadTactics.d.ts +63 -0
- package/dist/squad/SquadTactics.d.ts.map +1 -0
- package/dist/squad/SquadTactics.js +76 -0
- package/dist/squad/SquadTactics.js.map +1 -0
- package/dist/squad/index.d.ts +5 -0
- package/dist/squad/index.d.ts.map +1 -0
- package/dist/squad/index.js +4 -0
- package/dist/squad/index.js.map +1 -0
- package/dist/states/INPCContext.d.ts +550 -0
- package/dist/states/INPCContext.d.ts.map +1 -0
- package/dist/states/INPCContext.js +17 -0
- package/dist/states/INPCContext.js.map +1 -0
- package/dist/states/INPCOnlineState.d.ts +202 -0
- package/dist/states/INPCOnlineState.d.ts.map +1 -0
- package/dist/states/INPCOnlineState.js +9 -0
- package/dist/states/INPCOnlineState.js.map +1 -0
- package/dist/states/IOnlineStateHandler.d.ts +58 -0
- package/dist/states/IOnlineStateHandler.d.ts.map +1 -0
- package/dist/states/IOnlineStateHandler.js +13 -0
- package/dist/states/IOnlineStateHandler.js.map +1 -0
- package/dist/states/IStateConfig.d.ts +272 -0
- package/dist/states/IStateConfig.d.ts.map +1 -0
- package/dist/states/IStateConfig.js +100 -0
- package/dist/states/IStateConfig.js.map +1 -0
- package/dist/states/IStateTransitionMap.d.ts +89 -0
- package/dist/states/IStateTransitionMap.d.ts.map +1 -0
- package/dist/states/IStateTransitionMap.js +75 -0
- package/dist/states/IStateTransitionMap.js.map +1 -0
- package/dist/states/NPCOnlineState.d.ts +19 -0
- package/dist/states/NPCOnlineState.d.ts.map +1 -0
- package/dist/states/NPCOnlineState.js +75 -0
- package/dist/states/NPCOnlineState.js.map +1 -0
- package/dist/states/NPCPerception.d.ts +108 -0
- package/dist/states/NPCPerception.d.ts.map +1 -0
- package/dist/states/NPCPerception.js +122 -0
- package/dist/states/NPCPerception.js.map +1 -0
- package/dist/states/OnlineAIDriver.d.ts +64 -0
- package/dist/states/OnlineAIDriver.d.ts.map +1 -0
- package/dist/states/OnlineAIDriver.js +171 -0
- package/dist/states/OnlineAIDriver.js.map +1 -0
- package/dist/states/OnlineStateRegistryBuilder.d.ts +115 -0
- package/dist/states/OnlineStateRegistryBuilder.d.ts.map +1 -0
- package/dist/states/OnlineStateRegistryBuilder.js +184 -0
- package/dist/states/OnlineStateRegistryBuilder.js.map +1 -0
- package/dist/states/StateHandlerMap.d.ts +52 -0
- package/dist/states/StateHandlerMap.d.ts.map +1 -0
- package/dist/states/StateHandlerMap.js +88 -0
- package/dist/states/StateHandlerMap.js.map +1 -0
- package/dist/states/eat-corpse/EatCorpseState.d.ts +32 -0
- package/dist/states/eat-corpse/EatCorpseState.d.ts.map +1 -0
- package/dist/states/eat-corpse/EatCorpseState.js +126 -0
- package/dist/states/eat-corpse/EatCorpseState.js.map +1 -0
- package/dist/states/eat-corpse/EatCorpseTransitionGuard.d.ts +34 -0
- package/dist/states/eat-corpse/EatCorpseTransitionGuard.d.ts.map +1 -0
- package/dist/states/eat-corpse/EatCorpseTransitionGuard.js +82 -0
- package/dist/states/eat-corpse/EatCorpseTransitionGuard.js.map +1 -0
- package/dist/states/eat-corpse/ICorpseSource.d.ts +87 -0
- package/dist/states/eat-corpse/ICorpseSource.d.ts.map +1 -0
- package/dist/states/eat-corpse/ICorpseSource.js +5 -0
- package/dist/states/eat-corpse/ICorpseSource.js.map +1 -0
- package/dist/states/eat-corpse/IEatCorpseConfig.d.ts +75 -0
- package/dist/states/eat-corpse/IEatCorpseConfig.d.ts.map +1 -0
- package/dist/states/eat-corpse/IEatCorpseConfig.js +23 -0
- package/dist/states/eat-corpse/IEatCorpseConfig.js.map +1 -0
- package/dist/states/eat-corpse/IEatCorpsePhase.d.ts +23 -0
- package/dist/states/eat-corpse/IEatCorpsePhase.d.ts.map +1 -0
- package/dist/states/eat-corpse/IEatCorpsePhase.js +5 -0
- package/dist/states/eat-corpse/IEatCorpsePhase.js.map +1 -0
- package/dist/states/eat-corpse/index.d.ts +7 -0
- package/dist/states/eat-corpse/index.d.ts.map +1 -0
- package/dist/states/eat-corpse/index.js +11 -0
- package/dist/states/eat-corpse/index.js.map +1 -0
- package/dist/states/handlers/AlertState.d.ts +18 -0
- package/dist/states/handlers/AlertState.d.ts.map +1 -0
- package/dist/states/handlers/AlertState.js +104 -0
- package/dist/states/handlers/AlertState.js.map +1 -0
- package/dist/states/handlers/CampState.d.ts +18 -0
- package/dist/states/handlers/CampState.d.ts.map +1 -0
- package/dist/states/handlers/CampState.js +94 -0
- package/dist/states/handlers/CampState.js.map +1 -0
- package/dist/states/handlers/ChargeState.d.ts +18 -0
- package/dist/states/handlers/ChargeState.d.ts.map +1 -0
- package/dist/states/handlers/ChargeState.js +103 -0
- package/dist/states/handlers/ChargeState.js.map +1 -0
- package/dist/states/handlers/CombatState.d.ts +19 -0
- package/dist/states/handlers/CombatState.d.ts.map +1 -0
- package/dist/states/handlers/CombatState.js +137 -0
- package/dist/states/handlers/CombatState.js.map +1 -0
- package/dist/states/handlers/CombatTransitionHandler.d.ts +34 -0
- package/dist/states/handlers/CombatTransitionHandler.d.ts.map +1 -0
- package/dist/states/handlers/CombatTransitionHandler.js +137 -0
- package/dist/states/handlers/CombatTransitionHandler.js.map +1 -0
- package/dist/states/handlers/DeadState.d.ts +16 -0
- package/dist/states/handlers/DeadState.d.ts.map +1 -0
- package/dist/states/handlers/DeadState.js +35 -0
- package/dist/states/handlers/DeadState.js.map +1 -0
- package/dist/states/handlers/EvadeGrenadeState.d.ts +23 -0
- package/dist/states/handlers/EvadeGrenadeState.d.ts.map +1 -0
- package/dist/states/handlers/EvadeGrenadeState.js +93 -0
- package/dist/states/handlers/EvadeGrenadeState.js.map +1 -0
- package/dist/states/handlers/FleeState.d.ts +18 -0
- package/dist/states/handlers/FleeState.d.ts.map +1 -0
- package/dist/states/handlers/FleeState.js +61 -0
- package/dist/states/handlers/FleeState.js.map +1 -0
- package/dist/states/handlers/GrenadeState.d.ts +18 -0
- package/dist/states/handlers/GrenadeState.d.ts.map +1 -0
- package/dist/states/handlers/GrenadeState.js +61 -0
- package/dist/states/handlers/GrenadeState.js.map +1 -0
- package/dist/states/handlers/HelpWoundedState.d.ts +27 -0
- package/dist/states/handlers/HelpWoundedState.d.ts.map +1 -0
- package/dist/states/handlers/HelpWoundedState.js +131 -0
- package/dist/states/handlers/HelpWoundedState.js.map +1 -0
- package/dist/states/handlers/IdleState.d.ts +18 -0
- package/dist/states/handlers/IdleState.d.ts.map +1 -0
- package/dist/states/handlers/IdleState.js +127 -0
- package/dist/states/handlers/IdleState.js.map +1 -0
- package/dist/states/handlers/InvestigateState.d.ts +27 -0
- package/dist/states/handlers/InvestigateState.d.ts.map +1 -0
- package/dist/states/handlers/InvestigateState.js +145 -0
- package/dist/states/handlers/InvestigateState.js.map +1 -0
- package/dist/states/handlers/KillWoundedState.d.ts +27 -0
- package/dist/states/handlers/KillWoundedState.d.ts.map +1 -0
- package/dist/states/handlers/KillWoundedState.js +147 -0
- package/dist/states/handlers/KillWoundedState.js.map +1 -0
- package/dist/states/handlers/LeapState.d.ts +18 -0
- package/dist/states/handlers/LeapState.d.ts.map +1 -0
- package/dist/states/handlers/LeapState.js +115 -0
- package/dist/states/handlers/LeapState.js.map +1 -0
- package/dist/states/handlers/MonsterCombatController.d.ts +55 -0
- package/dist/states/handlers/MonsterCombatController.d.ts.map +1 -0
- package/dist/states/handlers/MonsterCombatController.js +152 -0
- package/dist/states/handlers/MonsterCombatController.js.map +1 -0
- package/dist/states/handlers/PatrolState.d.ts +18 -0
- package/dist/states/handlers/PatrolState.d.ts.map +1 -0
- package/dist/states/handlers/PatrolState.js +137 -0
- package/dist/states/handlers/PatrolState.js.map +1 -0
- package/dist/states/handlers/PsiAttackState.d.ts +18 -0
- package/dist/states/handlers/PsiAttackState.d.ts.map +1 -0
- package/dist/states/handlers/PsiAttackState.js +101 -0
- package/dist/states/handlers/PsiAttackState.js.map +1 -0
- package/dist/states/handlers/RetreatState.d.ts +18 -0
- package/dist/states/handlers/RetreatState.d.ts.map +1 -0
- package/dist/states/handlers/RetreatState.js +131 -0
- package/dist/states/handlers/RetreatState.js.map +1 -0
- package/dist/states/handlers/SearchState.d.ts +18 -0
- package/dist/states/handlers/SearchState.d.ts.map +1 -0
- package/dist/states/handlers/SearchState.js +64 -0
- package/dist/states/handlers/SearchState.js.map +1 -0
- package/dist/states/handlers/SleepState.d.ts +18 -0
- package/dist/states/handlers/SleepState.d.ts.map +1 -0
- package/dist/states/handlers/SleepState.js +94 -0
- package/dist/states/handlers/SleepState.js.map +1 -0
- package/dist/states/handlers/StalkState.d.ts +18 -0
- package/dist/states/handlers/StalkState.d.ts.map +1 -0
- package/dist/states/handlers/StalkState.js +82 -0
- package/dist/states/handlers/StalkState.js.map +1 -0
- package/dist/states/handlers/TakeCoverState.d.ts +18 -0
- package/dist/states/handlers/TakeCoverState.d.ts.map +1 -0
- package/dist/states/handlers/TakeCoverState.js +208 -0
- package/dist/states/handlers/TakeCoverState.js.map +1 -0
- package/dist/states/handlers/WoundedState.d.ts +18 -0
- package/dist/states/handlers/WoundedState.d.ts.map +1 -0
- package/dist/states/handlers/WoundedState.js +71 -0
- package/dist/states/handlers/WoundedState.js.map +1 -0
- package/dist/states/handlers/_utils.d.ts +55 -0
- package/dist/states/handlers/_utils.d.ts.map +1 -0
- package/dist/states/handlers/_utils.js +88 -0
- package/dist/states/handlers/_utils.js.map +1 -0
- package/dist/states/handlers/index.d.ts +25 -0
- package/dist/states/handlers/index.d.ts.map +1 -0
- package/dist/states/handlers/index.js +28 -0
- package/dist/states/handlers/index.js.map +1 -0
- package/dist/states/index.d.ts +17 -0
- package/dist/states/index.d.ts.map +1 -0
- package/dist/states/index.js +12 -0
- package/dist/states/index.js.map +1 -0
- package/dist/states/pack/IPackAccess.d.ts +46 -0
- package/dist/states/pack/IPackAccess.d.ts.map +1 -0
- package/dist/states/pack/IPackAccess.js +8 -0
- package/dist/states/pack/IPackAccess.js.map +1 -0
- package/dist/suspicion/SuspicionAccumulator.d.ts +166 -0
- package/dist/suspicion/SuspicionAccumulator.d.ts.map +1 -0
- package/dist/suspicion/SuspicionAccumulator.js +191 -0
- package/dist/suspicion/SuspicionAccumulator.js.map +1 -0
- package/dist/suspicion/index.d.ts +3 -0
- package/dist/suspicion/index.d.ts.map +1 -0
- package/dist/suspicion/index.js +2 -0
- package/dist/suspicion/index.js.map +1 -0
- package/dist/types/IAnimationTypes.d.ts +28 -0
- package/dist/types/IAnimationTypes.d.ts.map +1 -0
- package/dist/types/IAnimationTypes.js +17 -0
- package/dist/types/IAnimationTypes.js.map +1 -0
- package/dist/types/ICoverPoint.d.ts +76 -0
- package/dist/types/ICoverPoint.d.ts.map +1 -0
- package/dist/types/ICoverPoint.js +21 -0
- package/dist/types/ICoverPoint.js.map +1 -0
- package/dist/types/IOnlineAIConfig.d.ts +150 -0
- package/dist/types/IOnlineAIConfig.d.ts.map +1 -0
- package/dist/types/IOnlineAIConfig.js +5 -0
- package/dist/types/IOnlineAIConfig.js.map +1 -0
- package/dist/types/IPerceptionTypes.d.ts +94 -0
- package/dist/types/IPerceptionTypes.d.ts.map +1 -0
- package/dist/types/IPerceptionTypes.js +37 -0
- package/dist/types/IPerceptionTypes.js.map +1 -0
- package/dist/types/IWeaponTypes.d.ts +56 -0
- package/dist/types/IWeaponTypes.d.ts.map +1 -0
- package/dist/types/IWeaponTypes.js +15 -0
- package/dist/types/IWeaponTypes.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +123 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CoverRecommender.d.ts","sourceRoot":"","sources":["../../src/cover/CoverRecommender.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uCAAuC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sCAAsC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,eAAe,EAC1B,MAAM,EAAE,YAAY,GACnB,SAAS,CA8BX"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// cover/CoverRecommender.ts
|
|
2
|
+
// Pure decision function: tactical situation → recommended CoverType.
|
|
3
|
+
// No side effects, no state — ideal for unit testing.
|
|
4
|
+
import { CoverType } from '../types/ICoverPoint';
|
|
5
|
+
/**
|
|
6
|
+
* Recommend the best CoverType for a given tactical situation.
|
|
7
|
+
*
|
|
8
|
+
* Decision tree (priority order):
|
|
9
|
+
* 1. No ammo → SAFE (no point being offensive).
|
|
10
|
+
* 2. Critical HP → CLOSE (need cover NOW, closest available).
|
|
11
|
+
* 3. Demoralized → FAR (distance = psychological safety).
|
|
12
|
+
* 4. Outnumbered → SAFE (minimize exposure to multiple threats).
|
|
13
|
+
* 5. Healthy + few enemies → AMBUSH (take offensive position).
|
|
14
|
+
* 6. Default → BALANCED (balanced approach).
|
|
15
|
+
*
|
|
16
|
+
* @param situation - Tactical context describing the NPC's state.
|
|
17
|
+
* @param config - Cover configuration for threshold values.
|
|
18
|
+
* @returns The recommended CoverType.
|
|
19
|
+
*/
|
|
20
|
+
export function recommendCoverType(situation, config) {
|
|
21
|
+
const { hpRatio, morale, enemyCount, hasAmmo } = situation;
|
|
22
|
+
// No ammo: can't fight, maximize safety.
|
|
23
|
+
if (!hasAmmo) {
|
|
24
|
+
return CoverType.SAFE;
|
|
25
|
+
}
|
|
26
|
+
// Critical HP: get behind something immediately.
|
|
27
|
+
if (hpRatio <= config.recommendHpCritical) {
|
|
28
|
+
return CoverType.CLOSE;
|
|
29
|
+
}
|
|
30
|
+
// Demoralized: prefer distance for psychological recovery.
|
|
31
|
+
if (morale <= config.recommendMoraleDemoralized) {
|
|
32
|
+
return CoverType.FAR;
|
|
33
|
+
}
|
|
34
|
+
// Outnumbered: minimize aggregate threat.
|
|
35
|
+
if (enemyCount >= config.recommendOutnumberedCount) {
|
|
36
|
+
return CoverType.SAFE;
|
|
37
|
+
}
|
|
38
|
+
// Healthy and few enemies: take the initiative.
|
|
39
|
+
if (hpRatio >= config.recommendHpHealthy && enemyCount <= 2) {
|
|
40
|
+
return CoverType.AMBUSH;
|
|
41
|
+
}
|
|
42
|
+
// Default: balanced approach.
|
|
43
|
+
return CoverType.BALANCED;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=CoverRecommender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CoverRecommender.js","sourceRoot":"","sources":["../../src/cover/CoverRecommender.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,sEAAsE;AACtE,sDAAsD;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAiBjD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAA0B,EAC1B,MAAoB;IAEpB,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;IAE3D,yCAAyC;IACzC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,SAAS,CAAC,IAAI,CAAC;IACxB,CAAC;IAED,iDAAiD;IACjD,IAAI,OAAO,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAC1C,OAAO,SAAS,CAAC,KAAK,CAAC;IACzB,CAAC;IAED,2DAA2D;IAC3D,IAAI,MAAM,IAAI,MAAM,CAAC,0BAA0B,EAAE,CAAC;QAChD,OAAO,SAAS,CAAC,GAAG,CAAC;IACvB,CAAC;IAED,0CAA0C;IAC1C,IAAI,UAAU,IAAI,MAAM,CAAC,yBAAyB,EAAE,CAAC;QACnD,OAAO,SAAS,CAAC,IAAI,CAAC;IACxB,CAAC;IAED,gDAAgD;IAChD,IAAI,OAAO,IAAI,MAAM,CAAC,kBAAkB,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QAC5D,OAAO,SAAS,CAAC,MAAM,CAAC;IAC1B,CAAC;IAED,8BAA8B;IAC9B,OAAO,SAAS,CAAC,QAAQ,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Vec2, IRandom } from '@alife-sdk/core';
|
|
2
|
+
import type { ICoverPoint, ILoophole } from '../types/ICoverPoint';
|
|
3
|
+
import { CoverType } from '../types/ICoverPoint';
|
|
4
|
+
import type { ICoverConfig } from '../types/IOnlineAIConfig';
|
|
5
|
+
import { type ICoverSituation } from './CoverRecommender';
|
|
6
|
+
import type { ICoverLockRegistry } from './ICoverLockConfig';
|
|
7
|
+
/**
|
|
8
|
+
* Manages a collection of cover points in world space.
|
|
9
|
+
*
|
|
10
|
+
* Responsibilities:
|
|
11
|
+
* - Point registration and removal.
|
|
12
|
+
* - Occupancy tracking (one NPC per point).
|
|
13
|
+
* - Cover search using pluggable evaluator strategies.
|
|
14
|
+
* - Loophole generation and best-loophole queries.
|
|
15
|
+
*
|
|
16
|
+
* This is an instance-based class (not a singleton). Create one per
|
|
17
|
+
* simulation or per scene. Inject via the AI plugin system.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const registry = new CoverRegistry(config.cover, random);
|
|
22
|
+
* registry.addPoints([{ x: 100, y: 200 }, { x: 300, y: 400 }]);
|
|
23
|
+
*
|
|
24
|
+
* const cover = registry.findCover(CoverType.BALANCED, npcPos, enemies, npcId);
|
|
25
|
+
* if (cover) registry.occupy(cover.id, npcId);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare class CoverRegistry {
|
|
29
|
+
private readonly points;
|
|
30
|
+
private readonly evaluators;
|
|
31
|
+
private readonly loopholeGen;
|
|
32
|
+
private readonly config;
|
|
33
|
+
private readonly lockRegistry;
|
|
34
|
+
private idCounter;
|
|
35
|
+
private _allPointsCache;
|
|
36
|
+
private _allPointsDirty;
|
|
37
|
+
/**
|
|
38
|
+
* @param config - Cover evaluator configuration.
|
|
39
|
+
* @param random - Deterministic random source.
|
|
40
|
+
* @param lockRegistry - Optional TTL-based lock registry.
|
|
41
|
+
* When provided, `findCover` filters out points locked
|
|
42
|
+
* by other NPCs instead of relying on the mutable
|
|
43
|
+
* `occupiedBy` field. The legacy `occupy`/`release`
|
|
44
|
+
* methods remain operational for backward compatibility.
|
|
45
|
+
*/
|
|
46
|
+
constructor(config: ICoverConfig, random: IRandom, lockRegistry?: ICoverLockRegistry);
|
|
47
|
+
/**
|
|
48
|
+
* Add a single cover point. Returns the created point with a generated ID.
|
|
49
|
+
*/
|
|
50
|
+
addPoint(x: number, y: number, radius?: number): ICoverPoint;
|
|
51
|
+
/**
|
|
52
|
+
* Bulk-register cover points from coordinate data.
|
|
53
|
+
*/
|
|
54
|
+
addPoints(data: readonly {
|
|
55
|
+
x: number;
|
|
56
|
+
y: number;
|
|
57
|
+
radius?: number;
|
|
58
|
+
}[]): void;
|
|
59
|
+
/**
|
|
60
|
+
* Remove a cover point by ID. Releases any occupancy.
|
|
61
|
+
*/
|
|
62
|
+
removePoint(pointId: string): boolean;
|
|
63
|
+
/** Total number of registered cover points. */
|
|
64
|
+
getSize(): number;
|
|
65
|
+
/** Iterate all points (read-only). */
|
|
66
|
+
getAll(): readonly ICoverPoint[];
|
|
67
|
+
/**
|
|
68
|
+
* Find the best available cover point using the specified evaluator.
|
|
69
|
+
*
|
|
70
|
+
* Filters: unoccupied (or occupied by same NPC), within search radius,
|
|
71
|
+
* score above minimum threshold. Returns null if nothing qualifies.
|
|
72
|
+
*/
|
|
73
|
+
findCover(type: CoverType, npcPosition: Vec2, enemies: readonly Vec2[], npcId: string, maxRadius?: number): ICoverPoint | null;
|
|
74
|
+
/**
|
|
75
|
+
* Recommend cover type then find cover in one call.
|
|
76
|
+
* Convenience method that combines CoverRecommender + findCover.
|
|
77
|
+
*/
|
|
78
|
+
findRecommendedCover(situation: ICoverSituation, npcPosition: Vec2, enemies: readonly Vec2[], npcId: string): ICoverPoint | null;
|
|
79
|
+
/**
|
|
80
|
+
* Check whether a position falls inside any cover point's protection radius.
|
|
81
|
+
* Returns the closest matching point, or null.
|
|
82
|
+
*/
|
|
83
|
+
isInCover(position: Vec2): ICoverPoint | null;
|
|
84
|
+
/** Mark a cover point as occupied. */
|
|
85
|
+
occupy(pointId: string, npcId: string): void;
|
|
86
|
+
/** Release a cover point. If npcId given, only release if that NPC holds it. */
|
|
87
|
+
release(pointId: string, npcId?: string): void;
|
|
88
|
+
/** Release all points held by a specific NPC (e.g. on death). */
|
|
89
|
+
releaseAll(npcId: string): void;
|
|
90
|
+
/** Get loopholes for a cover point (generated lazily). */
|
|
91
|
+
getLoopholes(cover: ICoverPoint): readonly ILoophole[];
|
|
92
|
+
/** Find the best loophole for engaging an enemy from this cover. */
|
|
93
|
+
findBestLoophole(cover: ICoverPoint, enemyX: number, enemyY: number): ILoophole | null;
|
|
94
|
+
/** Clear all points, caches, and cover locks. Call on scene teardown. */
|
|
95
|
+
clear(): void;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=CoverRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CoverRegistry.d.ts","sourceRoot":"","sources":["../../src/cover/CoverRegistry.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAqB,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0C;IACrE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA4B;IACzD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,eAAe,CAAQ;IAE/B;;;;;;;;OAQG;gBACS,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,kBAAkB;IAWpF;;OAEG;IACH,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW;IAe5D;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,SAAS;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,IAAI;IAM3E;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAMrC,+CAA+C;IAC/C,OAAO,IAAI,MAAM;IAIjB,sCAAsC;IACtC,MAAM,IAAI,SAAS,WAAW,EAAE;IAahC;;;;;OAKG;IACH,SAAS,CACP,IAAI,EAAE,SAAS,EACf,WAAW,EAAE,IAAI,EACjB,OAAO,EAAE,SAAS,IAAI,EAAE,EACxB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,WAAW,GAAG,IAAI;IAsCrB;;;OAGG;IACH,oBAAoB,CAClB,SAAS,EAAE,eAAe,EAC1B,WAAW,EAAE,IAAI,EACjB,OAAO,EAAE,SAAS,IAAI,EAAE,EACxB,KAAK,EAAE,MAAM,GACZ,WAAW,GAAG,IAAI;IASrB;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,IAAI,GAAG,WAAW,GAAG,IAAI;IAqB7C,sCAAsC;IACtC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5C,gFAAgF;IAChF,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ9C,iEAAiE;IACjE,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAY/B,0DAA0D;IAC1D,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,SAAS,EAAE;IAItD,oEAAoE;IACpE,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAStF,yEAAyE;IACzE,KAAK,IAAI,IAAI;CAQd"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// cover/CoverRegistry.ts
|
|
2
|
+
// Instance-based cover point registry with occupancy tracking.
|
|
3
|
+
// Replaces the singleton CoverSystem from the game layer.
|
|
4
|
+
import { distanceSq } from '@alife-sdk/core';
|
|
5
|
+
import { createCoverEvaluators } from './CoverEvaluators';
|
|
6
|
+
import { recommendCoverType } from './CoverRecommender';
|
|
7
|
+
import { LoopholeGenerator, findBestLoophole } from './LoopholeGenerator';
|
|
8
|
+
/**
|
|
9
|
+
* Manages a collection of cover points in world space.
|
|
10
|
+
*
|
|
11
|
+
* Responsibilities:
|
|
12
|
+
* - Point registration and removal.
|
|
13
|
+
* - Occupancy tracking (one NPC per point).
|
|
14
|
+
* - Cover search using pluggable evaluator strategies.
|
|
15
|
+
* - Loophole generation and best-loophole queries.
|
|
16
|
+
*
|
|
17
|
+
* This is an instance-based class (not a singleton). Create one per
|
|
18
|
+
* simulation or per scene. Inject via the AI plugin system.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const registry = new CoverRegistry(config.cover, random);
|
|
23
|
+
* registry.addPoints([{ x: 100, y: 200 }, { x: 300, y: 400 }]);
|
|
24
|
+
*
|
|
25
|
+
* const cover = registry.findCover(CoverType.BALANCED, npcPos, enemies, npcId);
|
|
26
|
+
* if (cover) registry.occupy(cover.id, npcId);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export class CoverRegistry {
|
|
30
|
+
/**
|
|
31
|
+
* @param config - Cover evaluator configuration.
|
|
32
|
+
* @param random - Deterministic random source.
|
|
33
|
+
* @param lockRegistry - Optional TTL-based lock registry.
|
|
34
|
+
* When provided, `findCover` filters out points locked
|
|
35
|
+
* by other NPCs instead of relying on the mutable
|
|
36
|
+
* `occupiedBy` field. The legacy `occupy`/`release`
|
|
37
|
+
* methods remain operational for backward compatibility.
|
|
38
|
+
*/
|
|
39
|
+
constructor(config, random, lockRegistry) {
|
|
40
|
+
this.points = new Map();
|
|
41
|
+
this.idCounter = 0;
|
|
42
|
+
this._allPointsCache = [];
|
|
43
|
+
this._allPointsDirty = true;
|
|
44
|
+
this.config = config;
|
|
45
|
+
this.evaluators = createCoverEvaluators(config);
|
|
46
|
+
this.loopholeGen = new LoopholeGenerator(config, random);
|
|
47
|
+
this.lockRegistry = lockRegistry ?? null;
|
|
48
|
+
}
|
|
49
|
+
// -----------------------------------------------------------------
|
|
50
|
+
// Registration
|
|
51
|
+
// -----------------------------------------------------------------
|
|
52
|
+
/**
|
|
53
|
+
* Add a single cover point. Returns the created point with a generated ID.
|
|
54
|
+
*/
|
|
55
|
+
addPoint(x, y, radius) {
|
|
56
|
+
const id = `cover_${String(this.idCounter++).padStart(4, '0')}`;
|
|
57
|
+
const point = {
|
|
58
|
+
id,
|
|
59
|
+
x,
|
|
60
|
+
y,
|
|
61
|
+
radius: radius ?? this.config.pointRadius,
|
|
62
|
+
occupiedBy: null,
|
|
63
|
+
loopholes: [],
|
|
64
|
+
};
|
|
65
|
+
this.points.set(id, point);
|
|
66
|
+
this._allPointsDirty = true;
|
|
67
|
+
return point;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Bulk-register cover points from coordinate data.
|
|
71
|
+
*/
|
|
72
|
+
addPoints(data) {
|
|
73
|
+
for (const p of data) {
|
|
74
|
+
this.addPoint(p.x, p.y, p.radius);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Remove a cover point by ID. Releases any occupancy.
|
|
79
|
+
*/
|
|
80
|
+
removePoint(pointId) {
|
|
81
|
+
const result = this.points.delete(pointId);
|
|
82
|
+
if (result)
|
|
83
|
+
this._allPointsDirty = true;
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
/** Total number of registered cover points. */
|
|
87
|
+
getSize() {
|
|
88
|
+
return this.points.size;
|
|
89
|
+
}
|
|
90
|
+
/** Iterate all points (read-only). */
|
|
91
|
+
getAll() {
|
|
92
|
+
if (this._allPointsDirty) {
|
|
93
|
+
this._allPointsCache.length = 0;
|
|
94
|
+
for (const p of this.points.values())
|
|
95
|
+
this._allPointsCache.push(p);
|
|
96
|
+
this._allPointsDirty = false;
|
|
97
|
+
}
|
|
98
|
+
return this._allPointsCache;
|
|
99
|
+
}
|
|
100
|
+
// -----------------------------------------------------------------
|
|
101
|
+
// Cover Search
|
|
102
|
+
// -----------------------------------------------------------------
|
|
103
|
+
/**
|
|
104
|
+
* Find the best available cover point using the specified evaluator.
|
|
105
|
+
*
|
|
106
|
+
* Filters: unoccupied (or occupied by same NPC), within search radius,
|
|
107
|
+
* score above minimum threshold. Returns null if nothing qualifies.
|
|
108
|
+
*/
|
|
109
|
+
findCover(type, npcPosition, enemies, npcId, maxRadius) {
|
|
110
|
+
const evaluator = this.evaluators.get(type);
|
|
111
|
+
if (!evaluator)
|
|
112
|
+
return null;
|
|
113
|
+
const radius = maxRadius ?? this.config.searchRadius;
|
|
114
|
+
const maxRadiusSq = radius * radius;
|
|
115
|
+
const context = {
|
|
116
|
+
npcPosition,
|
|
117
|
+
enemies,
|
|
118
|
+
maxRadiusSq,
|
|
119
|
+
};
|
|
120
|
+
let bestPoint = null;
|
|
121
|
+
let bestScore = this.config.minScoreThreshold;
|
|
122
|
+
for (const point of this.points.values()) {
|
|
123
|
+
// Skip locked / occupied points.
|
|
124
|
+
if (this.lockRegistry !== null) {
|
|
125
|
+
if (!this.lockRegistry.isAvailable(point.id, npcId))
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
else if (point.occupiedBy !== null && point.occupiedBy !== npcId) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
// Squared distance pre-filter.
|
|
132
|
+
const dSq = distanceSq(npcPosition, point);
|
|
133
|
+
if (dSq > maxRadiusSq)
|
|
134
|
+
continue;
|
|
135
|
+
const score = evaluator.evaluate(point, context);
|
|
136
|
+
if (score > bestScore) {
|
|
137
|
+
bestScore = score;
|
|
138
|
+
bestPoint = point;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return bestPoint;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Recommend cover type then find cover in one call.
|
|
145
|
+
* Convenience method that combines CoverRecommender + findCover.
|
|
146
|
+
*/
|
|
147
|
+
findRecommendedCover(situation, npcPosition, enemies, npcId) {
|
|
148
|
+
const type = recommendCoverType(situation, this.config);
|
|
149
|
+
return this.findCover(type, npcPosition, enemies, npcId);
|
|
150
|
+
}
|
|
151
|
+
// -----------------------------------------------------------------
|
|
152
|
+
// Spatial Query
|
|
153
|
+
// -----------------------------------------------------------------
|
|
154
|
+
/**
|
|
155
|
+
* Check whether a position falls inside any cover point's protection radius.
|
|
156
|
+
* Returns the closest matching point, or null.
|
|
157
|
+
*/
|
|
158
|
+
isInCover(position) {
|
|
159
|
+
const thresholdSq = this.config.occupyDistance * this.config.occupyDistance;
|
|
160
|
+
let closest = null;
|
|
161
|
+
let closestDSq = Infinity;
|
|
162
|
+
for (const point of this.points.values()) {
|
|
163
|
+
const dSq = distanceSq(position, point);
|
|
164
|
+
const effectiveSq = Math.max(thresholdSq, point.radius * point.radius);
|
|
165
|
+
if (dSq <= effectiveSq && dSq < closestDSq) {
|
|
166
|
+
closestDSq = dSq;
|
|
167
|
+
closest = point;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return closest;
|
|
171
|
+
}
|
|
172
|
+
// -----------------------------------------------------------------
|
|
173
|
+
// Occupancy
|
|
174
|
+
// -----------------------------------------------------------------
|
|
175
|
+
/** Mark a cover point as occupied. */
|
|
176
|
+
occupy(pointId, npcId) {
|
|
177
|
+
const point = this.points.get(pointId);
|
|
178
|
+
if (point)
|
|
179
|
+
point.occupiedBy = npcId;
|
|
180
|
+
}
|
|
181
|
+
/** Release a cover point. If npcId given, only release if that NPC holds it. */
|
|
182
|
+
release(pointId, npcId) {
|
|
183
|
+
const point = this.points.get(pointId);
|
|
184
|
+
if (!point)
|
|
185
|
+
return;
|
|
186
|
+
if (npcId === undefined || point.occupiedBy === npcId) {
|
|
187
|
+
point.occupiedBy = null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/** Release all points held by a specific NPC (e.g. on death). */
|
|
191
|
+
releaseAll(npcId) {
|
|
192
|
+
for (const point of this.points.values()) {
|
|
193
|
+
if (point.occupiedBy === npcId) {
|
|
194
|
+
point.occupiedBy = null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// -----------------------------------------------------------------
|
|
199
|
+
// Loopholes
|
|
200
|
+
// -----------------------------------------------------------------
|
|
201
|
+
/** Get loopholes for a cover point (generated lazily). */
|
|
202
|
+
getLoopholes(cover) {
|
|
203
|
+
return this.loopholeGen.getLoopholes(cover);
|
|
204
|
+
}
|
|
205
|
+
/** Find the best loophole for engaging an enemy from this cover. */
|
|
206
|
+
findBestLoophole(cover, enemyX, enemyY) {
|
|
207
|
+
const loopholes = this.getLoopholes(cover);
|
|
208
|
+
return findBestLoophole(loopholes, cover.x, cover.y, enemyX, enemyY);
|
|
209
|
+
}
|
|
210
|
+
// -----------------------------------------------------------------
|
|
211
|
+
// Lifecycle
|
|
212
|
+
// -----------------------------------------------------------------
|
|
213
|
+
/** Clear all points, caches, and cover locks. Call on scene teardown. */
|
|
214
|
+
clear() {
|
|
215
|
+
this.points.clear();
|
|
216
|
+
this.idCounter = 0;
|
|
217
|
+
this._allPointsCache.length = 0;
|
|
218
|
+
this._allPointsDirty = true;
|
|
219
|
+
this.loopholeGen.clearCache();
|
|
220
|
+
this.lockRegistry?.clear();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=CoverRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CoverRegistry.js","sourceRoot":"","sources":["../../src/cover/CoverRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ICoverPoint, ICoverEvalContext } from '../types/ICoverPoint';
|
|
2
|
+
/**
|
|
3
|
+
* Strategy interface for scoring a cover point.
|
|
4
|
+
*
|
|
5
|
+
* Each evaluator optimizes for a different tactical priority (proximity,
|
|
6
|
+
* safety, flanking, etc.). Evaluators are stateless pure functions —
|
|
7
|
+
* they read the cover point and context, return a normalized score.
|
|
8
|
+
*
|
|
9
|
+
* @returns Score in range [0, 1] where 1 is the best possible cover.
|
|
10
|
+
*/
|
|
11
|
+
export interface ICoverEvaluator {
|
|
12
|
+
readonly type: string;
|
|
13
|
+
evaluate(point: ICoverPoint, context: ICoverEvalContext): number;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=ICoverEvaluator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ICoverEvaluator.d.ts","sourceRoot":"","sources":["../../src/cover/ICoverEvaluator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE3E;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAAC;CAClE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ICoverEvaluator.js","sourceRoot":"","sources":["../../src/cover/ICoverEvaluator.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,iDAAiD"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for the CoverLockRegistry.
|
|
3
|
+
*
|
|
4
|
+
* All durations are in milliseconds. Capacity values are positive integers.
|
|
5
|
+
*/
|
|
6
|
+
export interface ICoverLockConfig {
|
|
7
|
+
/**
|
|
8
|
+
* Default time-to-live for a lock in milliseconds.
|
|
9
|
+
* After this duration the lock expires and the point becomes available again.
|
|
10
|
+
* @default 10_000
|
|
11
|
+
*/
|
|
12
|
+
readonly defaultTtlMs: number;
|
|
13
|
+
/**
|
|
14
|
+
* Default maximum number of NPCs that can lock a single cover point.
|
|
15
|
+
* Individual `tryLock` calls can override this per-point via `options.capacity`.
|
|
16
|
+
* @default 1
|
|
17
|
+
*/
|
|
18
|
+
readonly defaultCapacity: number;
|
|
19
|
+
/**
|
|
20
|
+
* Auto-purge cadence: run `purgeExpired()` automatically every N `tryLock` /
|
|
21
|
+
* `isAvailable` calls. Set to 0 to disable auto-purge.
|
|
22
|
+
* @default 32
|
|
23
|
+
*/
|
|
24
|
+
readonly autoPurgeInterval: number;
|
|
25
|
+
}
|
|
26
|
+
export declare function createDefaultCoverLockConfig(overrides?: Partial<ICoverLockConfig>): ICoverLockConfig;
|
|
27
|
+
/**
|
|
28
|
+
* TTL-based reservation system for cover points.
|
|
29
|
+
*
|
|
30
|
+
* Prevents multiple NPCs from occupying the same cover point simultaneously.
|
|
31
|
+
* Locks expire automatically — no manual cleanup on NPC death is required,
|
|
32
|
+
* though `unlockAll(npcId)` is preferred for immediate availability.
|
|
33
|
+
*
|
|
34
|
+
* Cover points are identified by their string ID (`ICoverPoint.id`).
|
|
35
|
+
* Time is provided by an injected `timeFn` for determinism.
|
|
36
|
+
*/
|
|
37
|
+
export interface ICoverLockRegistry {
|
|
38
|
+
/**
|
|
39
|
+
* Attempt to lock a cover point for an NPC.
|
|
40
|
+
*
|
|
41
|
+
* - If the NPC already holds a lock on this point, the TTL is refreshed (idempotent).
|
|
42
|
+
* - Fails (returns false) when the point is at capacity with other NPCs.
|
|
43
|
+
*
|
|
44
|
+
* @param pointId - Cover point ID.
|
|
45
|
+
* @param npcId - NPC claiming the lock.
|
|
46
|
+
* @param options - Per-call overrides for TTL and capacity.
|
|
47
|
+
*/
|
|
48
|
+
tryLock(pointId: string, npcId: string, options?: {
|
|
49
|
+
ttlMs?: number;
|
|
50
|
+
capacity?: number;
|
|
51
|
+
}): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Release a specific NPC's lock on a point.
|
|
54
|
+
* No-op if the NPC does not hold a lock on this point.
|
|
55
|
+
*/
|
|
56
|
+
unlock(pointId: string, npcId: string): void;
|
|
57
|
+
/**
|
|
58
|
+
* Release all locks held by an NPC. Call on NPC death or despawn.
|
|
59
|
+
* O(n) where n = total active locks across all points.
|
|
60
|
+
*/
|
|
61
|
+
unlockAll(npcId: string): void;
|
|
62
|
+
/**
|
|
63
|
+
* Check whether a point can be locked by the given NPC.
|
|
64
|
+
*
|
|
65
|
+
* Returns true when:
|
|
66
|
+
* - The NPC already holds a lock on this point, or
|
|
67
|
+
* - The point has fewer active locks than its tracked capacity
|
|
68
|
+
* (the highest capacity ever passed via `options.capacity` for this
|
|
69
|
+
* point, falling back to `defaultCapacity` for unseen points).
|
|
70
|
+
*/
|
|
71
|
+
isAvailable(pointId: string, npcId: string): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Expire and remove stale lock entries.
|
|
74
|
+
* Called automatically at `autoPurgeInterval` cadence.
|
|
75
|
+
* @returns number of lock entries removed.
|
|
76
|
+
*/
|
|
77
|
+
purgeExpired(): number;
|
|
78
|
+
/** Remove all lock entries. Call on scene teardown. */
|
|
79
|
+
clear(): void;
|
|
80
|
+
/** Number of points that currently have at least one active lock. */
|
|
81
|
+
readonly lockedPointCount: number;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=ICoverLockConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ICoverLockConfig.d.ts","sourceRoot":"","sources":["../../src/cover/ICoverLockConfig.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAEjC;;;;OAIG;IACH,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC;AAED,wBAAgB,4BAA4B,CAC1C,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GACpC,gBAAgB,CAqBlB;AAMD;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;OASG;IACH,OAAO,CACL,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9C,OAAO,CAAC;IAEX;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7C;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B;;;;;;;;OAQG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAErD;;;;OAIG;IACH,YAAY,IAAI,MAAM,CAAC;IAEvB,uDAAuD;IACvD,KAAK,IAAI,IAAI,CAAC;IAEd,qEAAqE;IACrE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// cover/ICoverLockConfig.ts
|
|
2
|
+
// Configuration and public interface for the TTL-based cover lock subsystem.
|
|
3
|
+
export function createDefaultCoverLockConfig(overrides) {
|
|
4
|
+
const cfg = {
|
|
5
|
+
defaultTtlMs: 10000,
|
|
6
|
+
defaultCapacity: 1,
|
|
7
|
+
autoPurgeInterval: 32,
|
|
8
|
+
...overrides,
|
|
9
|
+
};
|
|
10
|
+
if (cfg.defaultTtlMs <= 0) {
|
|
11
|
+
throw new RangeError(`ICoverLockConfig.defaultTtlMs must be > 0, got ${cfg.defaultTtlMs}`);
|
|
12
|
+
}
|
|
13
|
+
if (!Number.isInteger(cfg.defaultCapacity) || cfg.defaultCapacity < 1) {
|
|
14
|
+
throw new RangeError(`ICoverLockConfig.defaultCapacity must be a positive integer, got ${cfg.defaultCapacity}`);
|
|
15
|
+
}
|
|
16
|
+
if (!Number.isInteger(cfg.autoPurgeInterval) || cfg.autoPurgeInterval < 0) {
|
|
17
|
+
throw new RangeError(`ICoverLockConfig.autoPurgeInterval must be a non-negative integer, got ${cfg.autoPurgeInterval}`);
|
|
18
|
+
}
|
|
19
|
+
return cfg;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=ICoverLockConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ICoverLockConfig.js","sourceRoot":"","sources":["../../src/cover/ICoverLockConfig.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,6EAA6E;AAkC7E,MAAM,UAAU,4BAA4B,CAC1C,SAAqC;IAErC,MAAM,GAAG,GAAqB;QAC5B,YAAY,EAAE,KAAM;QACpB,eAAe,EAAE,CAAC;QAClB,iBAAiB,EAAE,EAAE;QACrB,GAAG,SAAS;KACb,CAAC;IACF,IAAI,GAAG,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAAC,kDAAkD,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;IAC7F,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,UAAU,CAClB,oEAAoE,GAAG,CAAC,eAAe,EAAE,CAC1F,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,GAAG,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC;QAC1E,MAAM,IAAI,UAAU,CAClB,0EAA0E,GAAG,CAAC,iBAAiB,EAAE,CAClG,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ICoverPoint, ILoophole } from '../types/ICoverPoint';
|
|
2
|
+
import type { ICoverConfig } from '../types/IOnlineAIConfig';
|
|
3
|
+
import type { IRandom } from '@alife-sdk/core';
|
|
4
|
+
/**
|
|
5
|
+
* Generates and caches loophole positions for cover points.
|
|
6
|
+
*
|
|
7
|
+
* Loopholes are evenly distributed around the cover center at a fixed
|
|
8
|
+
* offset distance, each with a firing arc of configurable width.
|
|
9
|
+
* A seeded random source ensures deterministic generation.
|
|
10
|
+
*/
|
|
11
|
+
export declare class LoopholeGenerator {
|
|
12
|
+
private readonly cache;
|
|
13
|
+
private readonly offsetDistance;
|
|
14
|
+
private readonly fireArc;
|
|
15
|
+
private readonly maxPerCover;
|
|
16
|
+
private readonly random;
|
|
17
|
+
constructor(config: ICoverConfig, random: IRandom);
|
|
18
|
+
/**
|
|
19
|
+
* Get loopholes for a cover point, generating them on first access.
|
|
20
|
+
* Results are cached by cover point ID for the lifetime of this generator.
|
|
21
|
+
*/
|
|
22
|
+
getLoopholes(cover: ICoverPoint): readonly ILoophole[];
|
|
23
|
+
/** Clear the generation cache. Call on scene reset. */
|
|
24
|
+
clearCache(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Generate loopholes for a single cover point.
|
|
27
|
+
*
|
|
28
|
+
* Count is randomized in [1, maxPerCover]. Loopholes are distributed
|
|
29
|
+
* evenly around the cover center with angular jitter for natural feel.
|
|
30
|
+
*/
|
|
31
|
+
private generate;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Find the loophole whose firing arc best covers the angle to an enemy.
|
|
35
|
+
*
|
|
36
|
+
* @param loopholes - Available loopholes on the cover point.
|
|
37
|
+
* @param coverX - Cover point world X.
|
|
38
|
+
* @param coverY - Cover point world Y.
|
|
39
|
+
* @param enemyX - Enemy world X.
|
|
40
|
+
* @param enemyY - Enemy world Y.
|
|
41
|
+
* @returns The best matching loophole, or null if none covers the angle.
|
|
42
|
+
*/
|
|
43
|
+
export declare function findBestLoophole(loopholes: readonly ILoophole[], coverX: number, coverY: number, enemyX: number, enemyY: number): ILoophole | null;
|
|
44
|
+
//# sourceMappingURL=LoopholeGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoopholeGenerator.d.ts","sourceRoot":"","sources":["../../src/cover/LoopholeGenerator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2C;IACjE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;gBAErB,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO;IAOjD;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,SAAS,EAAE;IAStD,uDAAuD;IACvD,UAAU,IAAI,IAAI;IAIlB;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;CA0BjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,SAAS,SAAS,EAAE,EAC/B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,SAAS,GAAG,IAAI,CA0BlB"}
|