@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,213 @@
|
|
|
1
|
+
// combat/LoadoutBuilder.ts
|
|
2
|
+
// Builder pattern for creating NPC weapon loadouts.
|
|
3
|
+
// Clean, fluent API — no framework dependencies.
|
|
4
|
+
import { WeaponCategory } from '../types/IWeaponTypes';
|
|
5
|
+
/**
|
|
6
|
+
* Builds an NPC loadout step-by-step with a fluent API.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const loadout = new LoadoutBuilder(config.weapon)
|
|
11
|
+
* .withPrimary(WeaponCategory.RIFLE)
|
|
12
|
+
* .withSecondary(WeaponCategory.PISTOL)
|
|
13
|
+
* .withGrenades(2)
|
|
14
|
+
* .withMedkits(1)
|
|
15
|
+
* .build();
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export class LoadoutBuilder {
|
|
19
|
+
constructor(weaponConfigs) {
|
|
20
|
+
this.primary = null;
|
|
21
|
+
this.secondary = null;
|
|
22
|
+
this.grenades = 0;
|
|
23
|
+
this.medkits = 0;
|
|
24
|
+
this.weaponConfigs = weaponConfigs;
|
|
25
|
+
}
|
|
26
|
+
withPrimary(category, ammo) {
|
|
27
|
+
this.primary = this.createSlot(category, ammo);
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
withSecondary(category, ammo) {
|
|
31
|
+
this.secondary = this.createSlot(category, ammo);
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
withGrenades(count) {
|
|
35
|
+
this.grenades = Math.max(0, count);
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
withMedkits(count) {
|
|
39
|
+
this.medkits = Math.max(0, count);
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
build() {
|
|
43
|
+
return {
|
|
44
|
+
primary: this.primary,
|
|
45
|
+
secondary: this.secondary,
|
|
46
|
+
grenades: this.grenades,
|
|
47
|
+
medkits: this.medkits,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
createSlot(category, ammoOverride) {
|
|
51
|
+
const cfg = this.weaponConfigs.weapons[category];
|
|
52
|
+
if (!cfg) {
|
|
53
|
+
throw new Error(`[LoadoutBuilder] Unknown weapon category: ${String(category)}. Register it in IWeaponSelectionConfig.weapons.`);
|
|
54
|
+
}
|
|
55
|
+
const ammo = ammoOverride ?? cfg.defaultAmmo;
|
|
56
|
+
return {
|
|
57
|
+
category,
|
|
58
|
+
ammo,
|
|
59
|
+
maxAmmo: cfg.defaultAmmo,
|
|
60
|
+
range: cfg.range,
|
|
61
|
+
damage: cfg.damage,
|
|
62
|
+
fireRate: cfg.fireRate,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Default rank → loadout recipes matching the original if-else chain.
|
|
68
|
+
* Ranks not present (7+) fall through to formula-based generation.
|
|
69
|
+
*/
|
|
70
|
+
export const DEFAULT_LOADOUT_RECIPES = {
|
|
71
|
+
1: { primary: WeaponCategory.PISTOL, grenades: 0, medkits: 0 },
|
|
72
|
+
2: { primary: WeaponCategory.PISTOL, grenades: 0, medkits: 1 },
|
|
73
|
+
3: { primary: WeaponCategory.PISTOL, grenades: 0, medkits: 1, useFactionPreference: true, secondary: WeaponCategory.PISTOL },
|
|
74
|
+
4: { primary: WeaponCategory.PISTOL, grenades: 1, medkits: 2, useFactionPreference: true, secondary: WeaponCategory.PISTOL },
|
|
75
|
+
5: { primary: WeaponCategory.RIFLE, secondary: WeaponCategory.SHOTGUN, grenades: 1, medkits: 2 },
|
|
76
|
+
6: { primary: WeaponCategory.RIFLE, secondary: WeaponCategory.SHOTGUN, grenades: 2, medkits: 2 },
|
|
77
|
+
};
|
|
78
|
+
export const FactionWeaponPreference = {
|
|
79
|
+
rifle: WeaponCategory.RIFLE,
|
|
80
|
+
shotgun: WeaponCategory.SHOTGUN,
|
|
81
|
+
pistol: WeaponCategory.PISTOL,
|
|
82
|
+
sniper: WeaponCategory.SNIPER,
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Resolve the primary weapon for mid-rank NPCs (rank 3–4) based on faction preference.
|
|
86
|
+
* Sniper is too advanced for rookies — falls back to rifle.
|
|
87
|
+
*/
|
|
88
|
+
function resolveMidRankPrimary(preference) {
|
|
89
|
+
if (preference === WeaponCategory.SHOTGUN)
|
|
90
|
+
return WeaponCategory.SHOTGUN;
|
|
91
|
+
if (preference === WeaponCategory.SNIPER)
|
|
92
|
+
return WeaponCategory.RIFLE;
|
|
93
|
+
return WeaponCategory.RIFLE;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Create a rank-appropriate loadout for an NPC.
|
|
97
|
+
*
|
|
98
|
+
* Rank determines the tier of equipment. Faction preference
|
|
99
|
+
* influences weapon choice at mid ranks where multiple options
|
|
100
|
+
* are viable.
|
|
101
|
+
*
|
|
102
|
+
* | Rank | Primary | Secondary | Grenades | Medkits |
|
|
103
|
+
* |------|---------|-----------|----------|---------|
|
|
104
|
+
* | 1 | PISTOL | — | 0 | 0 |
|
|
105
|
+
* | 2 | PISTOL | — | 0 | 1 |
|
|
106
|
+
* | 3 | faction | PISTOL | 0 | 1 |
|
|
107
|
+
* | 4 | faction | PISTOL | 1 | 2 |
|
|
108
|
+
* | 5 | RIFLE | SHOTGUN | 1 | 2 |
|
|
109
|
+
* | 6 | RIFLE* | SHOTGUN | 2 | 2 |
|
|
110
|
+
* | 7+ | SNIPER | RIFLE | min(r-4,3) | 3 |
|
|
111
|
+
*
|
|
112
|
+
* *At rank 6, sniper factions get SNIPER as primary.
|
|
113
|
+
*
|
|
114
|
+
* @param recipes - Optional custom recipe map. If provided and a matching rank
|
|
115
|
+
* entry exists (exact or highest rank <= current), it is used instead of the
|
|
116
|
+
* built-in if-else chain. If not provided, the original hardcoded logic applies.
|
|
117
|
+
*/
|
|
118
|
+
export function createLoadout(rank, factionPreference, config, recipes) {
|
|
119
|
+
if (recipes) {
|
|
120
|
+
const recipe = findRecipe(rank, recipes);
|
|
121
|
+
if (recipe) {
|
|
122
|
+
return applyRecipe(recipe, factionPreference, config);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return createLoadoutDefault(rank, factionPreference, config);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Find the best matching recipe for the given rank.
|
|
129
|
+
* Returns exact match, or the highest rank key <= current rank.
|
|
130
|
+
* Returns undefined if no suitable recipe exists.
|
|
131
|
+
*/
|
|
132
|
+
function findRecipe(rank, recipes) {
|
|
133
|
+
if (recipes[rank])
|
|
134
|
+
return recipes[rank];
|
|
135
|
+
// Find highest rank key that is <= current rank.
|
|
136
|
+
let bestKey = -1;
|
|
137
|
+
for (const key of Object.keys(recipes)) {
|
|
138
|
+
const k = Number(key);
|
|
139
|
+
if (k <= rank && k > bestKey)
|
|
140
|
+
bestKey = k;
|
|
141
|
+
}
|
|
142
|
+
return bestKey >= 0 ? recipes[bestKey] : undefined;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Apply a recipe to build a loadout.
|
|
146
|
+
*/
|
|
147
|
+
function applyRecipe(recipe, factionPreference, config) {
|
|
148
|
+
const b = new LoadoutBuilder(config);
|
|
149
|
+
const primaryCategory = recipe.useFactionPreference
|
|
150
|
+
? resolveMidRankPrimary(factionPreference)
|
|
151
|
+
: recipe.primary;
|
|
152
|
+
b.withPrimary(primaryCategory);
|
|
153
|
+
if (recipe.secondary != null) {
|
|
154
|
+
b.withSecondary(recipe.secondary);
|
|
155
|
+
}
|
|
156
|
+
b.withGrenades(recipe.grenades);
|
|
157
|
+
b.withMedkits(recipe.medkits);
|
|
158
|
+
return b.build();
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Original hardcoded loadout creation logic (unchanged).
|
|
162
|
+
*/
|
|
163
|
+
function createLoadoutDefault(rank, factionPreference, config) {
|
|
164
|
+
const b = new LoadoutBuilder(config);
|
|
165
|
+
if (rank <= 1) {
|
|
166
|
+
return b.withPrimary(WeaponCategory.PISTOL).build();
|
|
167
|
+
}
|
|
168
|
+
if (rank === 2) {
|
|
169
|
+
return b.withPrimary(WeaponCategory.PISTOL).withMedkits(1).build();
|
|
170
|
+
}
|
|
171
|
+
if (rank === 3) {
|
|
172
|
+
return b
|
|
173
|
+
.withPrimary(resolveMidRankPrimary(factionPreference))
|
|
174
|
+
.withSecondary(WeaponCategory.PISTOL)
|
|
175
|
+
.withMedkits(1)
|
|
176
|
+
.build();
|
|
177
|
+
}
|
|
178
|
+
if (rank === 4) {
|
|
179
|
+
return b
|
|
180
|
+
.withPrimary(resolveMidRankPrimary(factionPreference))
|
|
181
|
+
.withSecondary(WeaponCategory.PISTOL)
|
|
182
|
+
.withGrenades(1)
|
|
183
|
+
.withMedkits(2)
|
|
184
|
+
.build();
|
|
185
|
+
}
|
|
186
|
+
if (rank === 5) {
|
|
187
|
+
return b
|
|
188
|
+
.withPrimary(WeaponCategory.RIFLE)
|
|
189
|
+
.withSecondary(WeaponCategory.SHOTGUN)
|
|
190
|
+
.withGrenades(1)
|
|
191
|
+
.withMedkits(2)
|
|
192
|
+
.build();
|
|
193
|
+
}
|
|
194
|
+
if (rank === 6) {
|
|
195
|
+
const primary = factionPreference === WeaponCategory.SNIPER
|
|
196
|
+
? WeaponCategory.SNIPER
|
|
197
|
+
: WeaponCategory.RIFLE;
|
|
198
|
+
return b
|
|
199
|
+
.withPrimary(primary)
|
|
200
|
+
.withSecondary(WeaponCategory.SHOTGUN)
|
|
201
|
+
.withGrenades(2)
|
|
202
|
+
.withMedkits(2)
|
|
203
|
+
.build();
|
|
204
|
+
}
|
|
205
|
+
// Rank 7+
|
|
206
|
+
return b
|
|
207
|
+
.withPrimary(WeaponCategory.SNIPER)
|
|
208
|
+
.withSecondary(WeaponCategory.RIFLE)
|
|
209
|
+
.withGrenades(Math.min(rank - 4, 3))
|
|
210
|
+
.withMedkits(3)
|
|
211
|
+
.build();
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=LoadoutBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LoadoutBuilder.js","sourceRoot":"","sources":["../../src/combat/LoadoutBuilder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monster ability type identifiers.
|
|
3
|
+
* Used to determine which ability phase data to create.
|
|
4
|
+
*/
|
|
5
|
+
export declare const MonsterAbility: {
|
|
6
|
+
readonly CHARGE: "charge";
|
|
7
|
+
readonly STALK: "stalk";
|
|
8
|
+
readonly LEAP: "leap";
|
|
9
|
+
readonly PSI_ATTACK: "psi_attack";
|
|
10
|
+
};
|
|
11
|
+
export type MonsterAbility = (typeof MonsterAbility)[keyof typeof MonsterAbility] | (string & {});
|
|
12
|
+
export type LinearChargePhase = 'windup' | 'charging' | 'impact';
|
|
13
|
+
export interface ILinearChargeData {
|
|
14
|
+
phase: LinearChargePhase;
|
|
15
|
+
timer: number;
|
|
16
|
+
startX: number;
|
|
17
|
+
startY: number;
|
|
18
|
+
targetX: number;
|
|
19
|
+
targetY: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function createLinearChargeData(startX: number, startY: number, targetX: number, targetY: number, windupMs: number): ILinearChargeData;
|
|
22
|
+
export type ApproachPhase = 'approach' | 'uncloak';
|
|
23
|
+
export interface IApproachData {
|
|
24
|
+
phase: ApproachPhase;
|
|
25
|
+
targetX: number;
|
|
26
|
+
targetY: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function createApproachData(targetX: number, targetY: number): IApproachData;
|
|
29
|
+
export type LeapPhase = 'windup' | 'airborne' | 'land';
|
|
30
|
+
export interface ILeapData {
|
|
31
|
+
phase: LeapPhase;
|
|
32
|
+
timer: number;
|
|
33
|
+
startX: number;
|
|
34
|
+
startY: number;
|
|
35
|
+
targetX: number;
|
|
36
|
+
targetY: number;
|
|
37
|
+
}
|
|
38
|
+
export declare function createLeapData(startX: number, startY: number, targetX: number, targetY: number, windupMs: number): ILeapData;
|
|
39
|
+
export type ChannelAbilityPhase = 'channel' | 'fire';
|
|
40
|
+
export interface IChannelAbilityData {
|
|
41
|
+
phase: ChannelAbilityPhase;
|
|
42
|
+
timer: number;
|
|
43
|
+
targetX: number;
|
|
44
|
+
targetY: number;
|
|
45
|
+
}
|
|
46
|
+
export declare function createChannelAbilityData(targetX: number, targetY: number, channelMs: number): IChannelAbilityData;
|
|
47
|
+
/**
|
|
48
|
+
* Context for determining which monster ability to trigger.
|
|
49
|
+
*/
|
|
50
|
+
export interface IMonsterAbilityContext {
|
|
51
|
+
readonly monsterType: string;
|
|
52
|
+
readonly distanceToEnemy: number;
|
|
53
|
+
readonly attackRange: number;
|
|
54
|
+
readonly meleeCooldownRemaining: number;
|
|
55
|
+
readonly hpRatio: number;
|
|
56
|
+
readonly moraleValue: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Strategy rule for monster ability activation.
|
|
60
|
+
* Evaluated in order — first rule whose `shouldTrigger` returns true wins.
|
|
61
|
+
*/
|
|
62
|
+
export interface IMonsterAbilityRule {
|
|
63
|
+
readonly abilityId: string;
|
|
64
|
+
shouldTrigger(ctx: IMonsterAbilityContext): boolean;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Default ability rules per monster type, extracted from the original switch logic.
|
|
68
|
+
* Each entry is evaluated in order; the first matching rule's abilityId is returned.
|
|
69
|
+
*/
|
|
70
|
+
export declare const DEFAULT_ABILITY_RULES: Readonly<Record<string, readonly IMonsterAbilityRule[]>>;
|
|
71
|
+
/**
|
|
72
|
+
* Determine which ability a monster should use, if any.
|
|
73
|
+
*
|
|
74
|
+
* Only fires when melee cooldown has expired. Rules are evaluated in order
|
|
75
|
+
* per monster type — first matching rule wins.
|
|
76
|
+
*
|
|
77
|
+
* @param ctx - Monster ability context (type, distance, cooldowns, etc.)
|
|
78
|
+
* @param rules - Optional custom ability rules. Defaults to DEFAULT_ABILITY_RULES.
|
|
79
|
+
* @returns The ability ID to use, or null if none should trigger.
|
|
80
|
+
*/
|
|
81
|
+
export declare function selectMonsterAbility(ctx: IMonsterAbilityContext, rules?: Readonly<Record<string, readonly IMonsterAbilityRule[]>>): string | null;
|
|
82
|
+
/**
|
|
83
|
+
* Configuration for monster flee behavior.
|
|
84
|
+
*/
|
|
85
|
+
export interface IMonsterFleeConfig {
|
|
86
|
+
/** HP ratio threshold below which flee is considered. Default 0.2. */
|
|
87
|
+
readonly hpThreshold: number;
|
|
88
|
+
/** Morale threshold below which flee is triggered. Default -0.3. */
|
|
89
|
+
readonly moraleThreshold: number;
|
|
90
|
+
}
|
|
91
|
+
export declare const DEFAULT_MONSTER_FLEE_CONFIG: IMonsterFleeConfig;
|
|
92
|
+
/**
|
|
93
|
+
* Check if a monster should flee based on critical state.
|
|
94
|
+
* Common to all monster types.
|
|
95
|
+
*/
|
|
96
|
+
export declare function shouldMonsterFlee(hpRatio: number, moraleValue: number, config?: IMonsterFleeConfig): boolean;
|
|
97
|
+
//# sourceMappingURL=MonsterAbilityData.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MonsterAbilityData.d.ts","sourceRoot":"","sources":["../../src/combat/MonsterAbilityData.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// combat/MonsterAbilityData.ts
|
|
2
|
+
// Value objects for monster ability state tracking.
|
|
3
|
+
// These are mutable phase-state objects consumed by the host's state machine.
|
|
4
|
+
/**
|
|
5
|
+
* Monster ability type identifiers.
|
|
6
|
+
* Used to determine which ability phase data to create.
|
|
7
|
+
*/
|
|
8
|
+
export const MonsterAbility = {
|
|
9
|
+
CHARGE: 'charge',
|
|
10
|
+
STALK: 'stalk',
|
|
11
|
+
LEAP: 'leap',
|
|
12
|
+
PSI_ATTACK: 'psi_attack',
|
|
13
|
+
};
|
|
14
|
+
export function createLinearChargeData(startX, startY, targetX, targetY, windupMs) {
|
|
15
|
+
return {
|
|
16
|
+
phase: 'windup',
|
|
17
|
+
timer: windupMs,
|
|
18
|
+
startX,
|
|
19
|
+
startY,
|
|
20
|
+
targetX,
|
|
21
|
+
targetY,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function createApproachData(targetX, targetY) {
|
|
25
|
+
return { phase: 'approach', targetX, targetY };
|
|
26
|
+
}
|
|
27
|
+
export function createLeapData(startX, startY, targetX, targetY, windupMs) {
|
|
28
|
+
return {
|
|
29
|
+
phase: 'windup',
|
|
30
|
+
timer: windupMs,
|
|
31
|
+
startX,
|
|
32
|
+
startY,
|
|
33
|
+
targetX,
|
|
34
|
+
targetY,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function createChannelAbilityData(targetX, targetY, channelMs) {
|
|
38
|
+
return { phase: 'channel', timer: channelMs, targetX, targetY };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Default ability rules per monster type, extracted from the original switch logic.
|
|
42
|
+
* Each entry is evaluated in order; the first matching rule's abilityId is returned.
|
|
43
|
+
*/
|
|
44
|
+
export const DEFAULT_ABILITY_RULES = {
|
|
45
|
+
boar: [
|
|
46
|
+
{ abilityId: 'charge', shouldTrigger: (ctx) => ctx.distanceToEnemy > ctx.attackRange },
|
|
47
|
+
],
|
|
48
|
+
bloodsucker: [
|
|
49
|
+
{ abilityId: 'stalk', shouldTrigger: (ctx) => ctx.distanceToEnemy > ctx.attackRange * 2 },
|
|
50
|
+
],
|
|
51
|
+
snork: [
|
|
52
|
+
{
|
|
53
|
+
abilityId: 'leap',
|
|
54
|
+
shouldTrigger: (ctx) => ctx.distanceToEnemy > ctx.attackRange && ctx.distanceToEnemy <= ctx.attackRange * 3,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
controller: [
|
|
58
|
+
{ abilityId: 'psi_attack', shouldTrigger: (ctx) => ctx.distanceToEnemy > ctx.attackRange },
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Determine which ability a monster should use, if any.
|
|
63
|
+
*
|
|
64
|
+
* Only fires when melee cooldown has expired. Rules are evaluated in order
|
|
65
|
+
* per monster type — first matching rule wins.
|
|
66
|
+
*
|
|
67
|
+
* @param ctx - Monster ability context (type, distance, cooldowns, etc.)
|
|
68
|
+
* @param rules - Optional custom ability rules. Defaults to DEFAULT_ABILITY_RULES.
|
|
69
|
+
* @returns The ability ID to use, or null if none should trigger.
|
|
70
|
+
*/
|
|
71
|
+
export function selectMonsterAbility(ctx, rules) {
|
|
72
|
+
if (ctx.meleeCooldownRemaining > 0)
|
|
73
|
+
return null;
|
|
74
|
+
const monsterRules = (rules ?? DEFAULT_ABILITY_RULES)[ctx.monsterType];
|
|
75
|
+
if (!monsterRules)
|
|
76
|
+
return null;
|
|
77
|
+
for (const rule of monsterRules) {
|
|
78
|
+
if (rule.shouldTrigger(ctx))
|
|
79
|
+
return rule.abilityId;
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
export const DEFAULT_MONSTER_FLEE_CONFIG = {
|
|
84
|
+
hpThreshold: 0.2,
|
|
85
|
+
moraleThreshold: -0.3,
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Check if a monster should flee based on critical state.
|
|
89
|
+
* Common to all monster types.
|
|
90
|
+
*/
|
|
91
|
+
export function shouldMonsterFlee(hpRatio, moraleValue, config = DEFAULT_MONSTER_FLEE_CONFIG) {
|
|
92
|
+
return hpRatio < config.hpThreshold && moraleValue < config.moraleThreshold;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=MonsterAbilityData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MonsterAbilityData.js","sourceRoot":"","sources":["../../src/combat/MonsterAbilityData.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { IWeaponSlot, INPCLoadout } from '../types/IWeaponTypes';
|
|
2
|
+
import type { IWeaponSelectionConfig } from '../types/IOnlineAIConfig';
|
|
3
|
+
/**
|
|
4
|
+
* Tactical context for weapon selection decisions.
|
|
5
|
+
* Groups NPC loadout and combat situation into a single parameter object.
|
|
6
|
+
*/
|
|
7
|
+
export interface IWeaponContext {
|
|
8
|
+
readonly loadout: INPCLoadout;
|
|
9
|
+
readonly distanceToEnemy: number;
|
|
10
|
+
readonly enemyCount: number;
|
|
11
|
+
readonly hpRatio: number;
|
|
12
|
+
readonly inCombat?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Select the highest-scoring weapon from an NPC's loadout.
|
|
16
|
+
*
|
|
17
|
+
* Scoring formula: `distanceScore × enemyCountModifier × hpRatioModifier`.
|
|
18
|
+
* Primary weapon wins ties. Returns null if the NPC has no ammo at all
|
|
19
|
+
* (signal to flee/retreat).
|
|
20
|
+
*
|
|
21
|
+
* Single-pass, zero-allocation — no intermediate arrays.
|
|
22
|
+
*
|
|
23
|
+
* @param ctx - Weapon context (loadout, distance, enemy count, HP).
|
|
24
|
+
* @param config - Weapon selection configuration.
|
|
25
|
+
* @returns Best weapon slot, or null if no ammo.
|
|
26
|
+
*/
|
|
27
|
+
export declare function selectBestWeapon(ctx: IWeaponContext, config: IWeaponSelectionConfig): IWeaponSlot | null;
|
|
28
|
+
/**
|
|
29
|
+
* Check whether a grenade throw is tactically advisable.
|
|
30
|
+
*
|
|
31
|
+
* All three conditions must be true:
|
|
32
|
+
* 1. NPC has grenades remaining.
|
|
33
|
+
* 2. At least `grenadeMinEnemies` visible.
|
|
34
|
+
* 3. Enemy within throw range [grenadeMinDistance, grenadeMaxDistance].
|
|
35
|
+
*/
|
|
36
|
+
export declare function shouldThrowGrenade(ctx: IWeaponContext, config: IWeaponSelectionConfig): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Check whether the NPC should use a medkit now.
|
|
39
|
+
*
|
|
40
|
+
* Rules:
|
|
41
|
+
* - Has medkits remaining.
|
|
42
|
+
* - HP below `medkitHpThreshold`.
|
|
43
|
+
* - If HP below `medkitEmergencyThreshold`, use even mid-combat.
|
|
44
|
+
* - Otherwise, only use when not actively in combat.
|
|
45
|
+
*/
|
|
46
|
+
export declare function shouldUseMedkit(ctx: IWeaponContext, config: IWeaponSelectionConfig): boolean;
|
|
47
|
+
//# sourceMappingURL=WeaponSelector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WeaponSelector.d.ts","sourceRoot":"","sources":["../../src/combat/WeaponSelector.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAuID;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,sBAAsB,GAC7B,WAAW,GAAG,IAAI,CAqBpB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAQT;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAMT"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// combat/WeaponSelector.ts
|
|
2
|
+
// Pure-function weapon selection — multi-factor scoring.
|
|
3
|
+
// No side effects, no framework dependencies.
|
|
4
|
+
import { WeaponCategory } from '../types/IWeaponTypes';
|
|
5
|
+
/**
|
|
6
|
+
* Distance-based effectiveness score for a weapon category.
|
|
7
|
+
* Returns a value in [0, 1] where 1 = optimal engagement range.
|
|
8
|
+
*/
|
|
9
|
+
function distanceScore(category, distance, config) {
|
|
10
|
+
switch (category) {
|
|
11
|
+
case WeaponCategory.PISTOL:
|
|
12
|
+
return 0.4;
|
|
13
|
+
case WeaponCategory.SHOTGUN: {
|
|
14
|
+
if (config.shotgunEffectiveMax <= 0)
|
|
15
|
+
return 0;
|
|
16
|
+
if (distance <= config.shotgunEffectiveMax * 0.66)
|
|
17
|
+
return 1.0;
|
|
18
|
+
if (distance > config.shotgunEffectiveMax * 1.33)
|
|
19
|
+
return 0.0;
|
|
20
|
+
const overshoot = (distance - config.shotgunEffectiveMax * 0.66) /
|
|
21
|
+
(config.shotgunEffectiveMax * 0.66);
|
|
22
|
+
return Math.max(0, 1.0 - overshoot);
|
|
23
|
+
}
|
|
24
|
+
case WeaponCategory.RIFLE: {
|
|
25
|
+
if (config.rifleEffectiveMin <= 0)
|
|
26
|
+
return 0.6;
|
|
27
|
+
if (distance >= config.rifleEffectiveMin && distance <= config.rifleEffectiveMax)
|
|
28
|
+
return 1.0;
|
|
29
|
+
if (distance < config.rifleEffectiveMin)
|
|
30
|
+
return 0.6 + 0.4 * (distance / config.rifleEffectiveMin);
|
|
31
|
+
const falloff = (distance - config.rifleEffectiveMax) / 200;
|
|
32
|
+
return Math.max(0.2, 1.0 - falloff);
|
|
33
|
+
}
|
|
34
|
+
case WeaponCategory.SNIPER: {
|
|
35
|
+
if (config.sniperEffectiveMin <= 0)
|
|
36
|
+
return 0.1;
|
|
37
|
+
if (distance >= config.sniperEffectiveMin)
|
|
38
|
+
return 1.0;
|
|
39
|
+
return 0.1 + 0.9 * (distance / config.sniperEffectiveMin);
|
|
40
|
+
}
|
|
41
|
+
default:
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Modifier based on number of visible enemies.
|
|
47
|
+
* Only activates at 3+ enemies.
|
|
48
|
+
* If `config.scoringFactors` contains an entry for the category, uses its `multiEnemyModifier`.
|
|
49
|
+
*/
|
|
50
|
+
function enemyCountModifier(category, count, config) {
|
|
51
|
+
if (count <= 2)
|
|
52
|
+
return 1.0;
|
|
53
|
+
const factors = config.scoringFactors?.[String(category)];
|
|
54
|
+
if (factors)
|
|
55
|
+
return factors.multiEnemyModifier;
|
|
56
|
+
switch (category) {
|
|
57
|
+
case WeaponCategory.SHOTGUN:
|
|
58
|
+
return 1.5;
|
|
59
|
+
case WeaponCategory.RIFLE:
|
|
60
|
+
return 1.3;
|
|
61
|
+
case WeaponCategory.SNIPER:
|
|
62
|
+
return 0.6;
|
|
63
|
+
default:
|
|
64
|
+
return 1.0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Modifier based on NPC's current HP ratio.
|
|
69
|
+
* Low HP favors ranged weapons; high HP allows aggression.
|
|
70
|
+
* If `config.scoringFactors` contains an entry for the category, uses its `lowHpModifier` / `highHpModifier`.
|
|
71
|
+
*/
|
|
72
|
+
function hpRatioModifier(category, hp, config) {
|
|
73
|
+
const factors = config.scoringFactors?.[String(category)];
|
|
74
|
+
if (hp < 0.3) {
|
|
75
|
+
if (factors)
|
|
76
|
+
return factors.lowHpModifier;
|
|
77
|
+
switch (category) {
|
|
78
|
+
case WeaponCategory.SNIPER:
|
|
79
|
+
return 1.3;
|
|
80
|
+
case WeaponCategory.RIFLE:
|
|
81
|
+
return 1.2;
|
|
82
|
+
case WeaponCategory.PISTOL:
|
|
83
|
+
return 0.9;
|
|
84
|
+
case WeaponCategory.SHOTGUN:
|
|
85
|
+
return 0.7;
|
|
86
|
+
default:
|
|
87
|
+
return 1.0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (hp > 0.7) {
|
|
91
|
+
if (factors)
|
|
92
|
+
return factors.highHpModifier;
|
|
93
|
+
switch (category) {
|
|
94
|
+
case WeaponCategory.SHOTGUN:
|
|
95
|
+
return 1.2;
|
|
96
|
+
case WeaponCategory.PISTOL:
|
|
97
|
+
return 1.1;
|
|
98
|
+
case WeaponCategory.SNIPER:
|
|
99
|
+
return 0.9;
|
|
100
|
+
default:
|
|
101
|
+
return 1.0;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return 1.0;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Compute the composite weapon score (distance × enemyCount × hpRatio modifiers).
|
|
108
|
+
*/
|
|
109
|
+
function weaponScore(category, distanceToEnemy, enemyCount, hpRatio, config) {
|
|
110
|
+
return (distanceScore(category, distanceToEnemy, config) *
|
|
111
|
+
enemyCountModifier(category, enemyCount, config) *
|
|
112
|
+
hpRatioModifier(category, hpRatio, config));
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Select the highest-scoring weapon from an NPC's loadout.
|
|
116
|
+
*
|
|
117
|
+
* Scoring formula: `distanceScore × enemyCountModifier × hpRatioModifier`.
|
|
118
|
+
* Primary weapon wins ties. Returns null if the NPC has no ammo at all
|
|
119
|
+
* (signal to flee/retreat).
|
|
120
|
+
*
|
|
121
|
+
* Single-pass, zero-allocation — no intermediate arrays.
|
|
122
|
+
*
|
|
123
|
+
* @param ctx - Weapon context (loadout, distance, enemy count, HP).
|
|
124
|
+
* @param config - Weapon selection configuration.
|
|
125
|
+
* @returns Best weapon slot, or null if no ammo.
|
|
126
|
+
*/
|
|
127
|
+
export function selectBestWeapon(ctx, config) {
|
|
128
|
+
const { loadout, distanceToEnemy, enemyCount, hpRatio } = ctx;
|
|
129
|
+
let bestSlot = null;
|
|
130
|
+
let bestScore = -Infinity;
|
|
131
|
+
// Score primary (wins ties via evaluation order — scored first).
|
|
132
|
+
if (loadout.primary && loadout.primary.ammo > 0) {
|
|
133
|
+
bestScore = weaponScore(loadout.primary.category, distanceToEnemy, enemyCount, hpRatio, config);
|
|
134
|
+
bestSlot = loadout.primary;
|
|
135
|
+
}
|
|
136
|
+
// Score secondary — must strictly beat primary to win.
|
|
137
|
+
if (loadout.secondary && loadout.secondary.ammo > 0) {
|
|
138
|
+
const secScore = weaponScore(loadout.secondary.category, distanceToEnemy, enemyCount, hpRatio, config);
|
|
139
|
+
if (secScore > bestScore) {
|
|
140
|
+
bestScore = secScore;
|
|
141
|
+
bestSlot = loadout.secondary;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return bestSlot;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Check whether a grenade throw is tactically advisable.
|
|
148
|
+
*
|
|
149
|
+
* All three conditions must be true:
|
|
150
|
+
* 1. NPC has grenades remaining.
|
|
151
|
+
* 2. At least `grenadeMinEnemies` visible.
|
|
152
|
+
* 3. Enemy within throw range [grenadeMinDistance, grenadeMaxDistance].
|
|
153
|
+
*/
|
|
154
|
+
export function shouldThrowGrenade(ctx, config) {
|
|
155
|
+
const { loadout, enemyCount, distanceToEnemy } = ctx;
|
|
156
|
+
return (loadout.grenades > 0 &&
|
|
157
|
+
enemyCount >= config.grenadeMinEnemies &&
|
|
158
|
+
distanceToEnemy >= config.grenadeMinDistance &&
|
|
159
|
+
distanceToEnemy <= config.grenadeMaxDistance);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check whether the NPC should use a medkit now.
|
|
163
|
+
*
|
|
164
|
+
* Rules:
|
|
165
|
+
* - Has medkits remaining.
|
|
166
|
+
* - HP below `medkitHpThreshold`.
|
|
167
|
+
* - If HP below `medkitEmergencyThreshold`, use even mid-combat.
|
|
168
|
+
* - Otherwise, only use when not actively in combat.
|
|
169
|
+
*/
|
|
170
|
+
export function shouldUseMedkit(ctx, config) {
|
|
171
|
+
const { loadout, hpRatio, inCombat } = ctx;
|
|
172
|
+
if (loadout.medkits <= 0)
|
|
173
|
+
return false;
|
|
174
|
+
if (hpRatio >= config.medkitHpThreshold)
|
|
175
|
+
return false;
|
|
176
|
+
if (hpRatio < config.medkitEmergencyThreshold)
|
|
177
|
+
return true;
|
|
178
|
+
return !inCombat;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=WeaponSelector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WeaponSelector.js","sourceRoot":"","sources":["../../src/combat/WeaponSelector.ts"],"names":[],"mappings":"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"}
|