public bool Test(IActor actor, ISectorTaskSourceContext context, ILogicState currentState, ILogicStrategyData strategyData) { if (actor is null) { throw new ArgumentNullException(nameof(actor)); } if (currentState is null) { throw new ArgumentNullException(nameof(currentState)); } if (strategyData is null) { throw new ArgumentNullException(nameof(strategyData)); } if (!actor.Person.HasModule <IInventoryModule>() || !actor.Person.HasModule <IEquipmentModule>()) { return(false); } var inventoryModule = actor.Person.GetModule <IInventoryModule>(); var inventoryProps = inventoryModule.CalcActualItems(); var currentInventoryEquipments = inventoryProps.OfType <Equipment>(); if (!currentInventoryEquipments.Any()) { strategyData.TargetEquipment = null; strategyData.TargetEquipmentSlotIndex = null; return(false); } var equipmentModule = actor.Person.GetModule <IEquipmentModule>(); for (var slotIndex = 0; slotIndex < equipmentModule.Slots.Length; slotIndex++) { var slotScheme = equipmentModule.Slots[slotIndex]; var equiped = equipmentModule[slotIndex]; if (equiped is null) { var availableEquipments = from equipment in currentInventoryEquipments where IsApplicableForSlot(equipment, slotScheme.Types) where EquipmentCarrierHelper.CanBeEquiped(equipmentModule, slotIndex, equipment) select equipment; var targetEquipmentFromInventory = availableEquipments.FirstOrDefault(); if (targetEquipmentFromInventory != null) { strategyData.TargetEquipment = targetEquipmentFromInventory; strategyData.TargetEquipmentSlotIndex = slotIndex; return(true); } } } return(false); }
public IActorTask GetActorTask(ISectorTaskSourceContext context) { // Для текущего состояния проверяем каждый из переходов. // Если переход выстреливает, то генерируем задачу актёру. // Алгоритм делится на два этапа: // 1. Для текущей логики проверяются все триггеры по порядку. Если какой-то триггер выстреливает, то связанная // через переход логика фиксируется, как текущая. За одну итерацию может быть только один переход. // 2. Получаем задачу из текущей логики. Если текущая логика возвращает пустую задачу - значит // переводим её в соответствующее состояние и ждём перехода из неё с помощью триггеров (этап 1). // Второй пункт означает, что каждая логика обязана выдавать хотя бы пустую задачу, если она // не может выполниться. И выставлять себе статус выполненной. В дереве состояний нужно следить за тем, чтобы // все логики имели триггер на окончание с переходом на какую-либо задачу. // После окончания всех проверок триггеров выполняется обновление состояния триггеров. Некоторые триггеры // могут иметь счётчики или логику, которая выполняется при каждой итерации (считай, каждый ход). var transitionWasPerformed = SelectCurrentState(CurrentState, context, out var newState); if (transitionWasPerformed) { CurrentState = newState; ResetLogicStates(_stateTree); } var actorTask = CurrentState.GetTask(Actor, context, _strategyData); var currentTriggers = _stateTree.Transitions[CurrentState].Select(x => x.Trigger); UpdateCurrentTriggers(currentTriggers); return(actorTask); }
public override IActorTask GetTask(IActor actor, ISectorTaskSourceContext context, ILogicStrategyData strategyData) { var map = context.Sector.Map; var staticObjectManager = context.Sector.StaticObjectManager; var staticObject = FindContainer(actor, staticObjectManager, map); if (staticObject == null || !staticObject.GetModule <IPropContainer>().Content.CalcActualItems().Any()) { Complete = true; return(null); } var distance = map.DistanceBetween(actor.Node, staticObject.Node); if (distance <= 1) { return(TakeAllFromContainerTask(actor, staticObject, context.Sector)); } var storedMoveTask = _moveTask; var moveTask = MoveToContainerTask(actor, staticObject.Node, storedMoveTask, context.Sector); _moveTask = moveTask; return(moveTask); }
public override IActorTask GetTask(IActor actor, ISectorTaskSourceContext context, ILogicStrategyData strategyData) { if (actor is null) { throw new ArgumentNullException(nameof(actor)); } if (context is null) { throw new ArgumentNullException(nameof(context)); } if (strategyData is null) { throw new ArgumentNullException(nameof(strategyData)); } var usePropTask = CreateTask(actor, context, strategyData); if (usePropTask != null) { Complete = true; return(usePropTask); } Complete = true; return(null); }
public bool Test(IActor actor, ISectorTaskSourceContext context, ILogicState currentState, ILogicStrategyData strategyData) { if (actor is null) { throw new ArgumentNullException(nameof(actor)); } if (context is null) { throw new ArgumentNullException(nameof(context)); } if (currentState is null) { throw new ArgumentNullException(nameof(currentState)); } if (strategyData is null) { throw new ArgumentNullException(nameof(strategyData)); } var staticObjectManager = context.Sector.StaticObjectManager; var map = context.Sector.Map; var containers = staticObjectManager.Items.Where(x => x.HasModule <IPropContainer>()); var foundContainers = LootHelper.FindAvailableContainers(containers, actor.Node, map); return(foundContainers.Any()); }
public override IActorTask GetTask(IActor actor, ISectorTaskSourceContext context, ILogicStrategyData strategyData) { var inventory = actor.Person.GetModule <IInventoryModule>(); var currentInventoryProps = inventory.CalcActualItems(); var currentInventoryEquipments = currentInventoryProps.OfType <Equipment>().ToArray(); var equipmentCarrier = actor.Person.GetModule <IEquipmentModule>(); for (var slotIndex = 0; slotIndex < equipmentCarrier.Slots.Length; slotIndex++) { var slot = actor.Person.GetModule <IEquipmentModule>().Slots[slotIndex]; var equiped = actor.Person.GetModule <IEquipmentModule>()[slotIndex]; if (equiped == null) { var availableEquipments = currentInventoryEquipments .Where(equipment => (equipment.Scheme.Equip.SlotTypes[0] & slot.Types) > 0) .Where(equipment => EquipmentCarrierHelper.CanBeEquiped(equipmentCarrier, slotIndex, equipment)) .ToArray(); if (availableEquipments.Any()) { var targetEquipmentFromInventory = availableEquipments.First(); var targetSlotIndex = slotIndex; var taskContext = new ActorTaskContext(context.Sector); return(new EquipTask(actor, taskContext, targetEquipmentFromInventory, targetSlotIndex)); } } } Complete = true; return(null); }
public override IActorTask GetTask(IActor actor, ISectorTaskSourceContext context, ILogicStrategyData strategyData) { var triggerTarget = strategyData.TriggerIntuder; if (triggerTarget == null) { throw new InvalidOperationException( $"Assign {nameof(strategyData.TriggerIntuder)} with not null valie in related trigger."); } var targetCanBeDamaged = triggerTarget.CanBeDamaged(); if (!targetCanBeDamaged) { Complete = true; return(null); } var attackParams = CheckAttackAvailability(actor, triggerTarget, context.Sector.Map); if (attackParams.IsAvailable) { var act = attackParams.CombatAct; var taskContext = new ActorTaskContext(context.Sector); var attackTask = new AttackTask(actor, taskContext, triggerTarget, act, _actService); return(attackTask); } // Маршрут до цели обновляем каждые 3 хода. // Для оптимизации. // Эффект потери цели. if (_refreshCounter > 0 && _moveTask?.CanExecute() == true) { _refreshCounter--; return(_moveTask); } var map = context.Sector.Map; _refreshCounter = REFRESH_COUNTER_VALUE; var targetIsOnLine = map.TargetIsOnLine(actor.Node, triggerTarget.Node); if (targetIsOnLine) { var taskContext = new ActorTaskContext(context.Sector); var moveModule = actor.Person.GetModule <IMovingModule>(); var moveCost = moveModule.CalculateCost(); _moveTask = new MoveTask(actor, taskContext, triggerTarget.Node, map, moveCost); return(_moveTask); } // Цел за пределами видимости. Считается потерянной. return(null); }
public bool Test(IActor actor, ISectorTaskSourceContext context, ILogicState currentState, ILogicStrategyData strategyData) { if (currentState is null) { throw new System.ArgumentNullException(nameof(currentState)); } return(currentState.Complete); }
protected override bool TestInner(IActor actor, ISectorTaskSourceContext context, ILogicState currentState, ILogicStrategyData strategyData) { var taskContext = new ActorTaskContext(context.Sector); return(SurvivalHazardTriggerHelper.TestHazardAndResource( actor, taskContext, strategyData, SurvivalStatType.Satiety, ConsumeCommonRuleType.Satiety)); }
public bool Test(IActor actor, ISectorTaskSourceContext context, ILogicState currentState, ILogicStrategyData strategyData) { foreach (var trigger in _triggers) { if (!trigger.Test(actor, context, currentState, strategyData)) { return(false); } } return(true); }
/// <summary> /// Checks situation when all nodes of a map are explored (known) by the person. /// </summary> /// <returns>True if all nodes are explored. False otherside.</returns> public bool Test(IActor actor, ISectorTaskSourceContext context, ILogicState currentState, ILogicStrategyData strategyData) { if (actor is null) { throw new ArgumentNullException(nameof(actor)); } if (context is null) { throw new ArgumentNullException(nameof(context)); } if (currentState is null) { throw new ArgumentNullException(nameof(currentState)); } if (strategyData is null) { throw new ArgumentNullException(nameof(strategyData)); } var fowModule = actor.Person.GetModuleSafe <IFowData>(); if (fowModule is null) { var notObservedNodes = context.Sector.Map.Nodes.Where(x => !strategyData.ObservedNodes.Contains(x)); var allNodesObserved = !notObservedNodes.Any(); return(allNodesObserved); } else { var fowData = fowModule.GetSectorFowData(context.Sector); var observingNodes = fowData.GetFowNodeByState(SectorMapNodeFowState.Observing).Select(x => x.Node) .ToArray(); var exploredNodes = fowData.GetFowNodeByState(SectorMapNodeFowState.Explored).Select(x => x.Node) .ToArray(); var knownNodes = observingNodes.Union(exploredNodes); var notObservedNodes = context.Sector.Map.Nodes.Where(x => !knownNodes.Contains(x)); var allNodesObserved = !notObservedNodes.Any(); return(allNodesObserved); } }
public bool Test(IActor actor, ISectorTaskSourceContext context, ILogicState currentState, ILogicStrategyData strategyData) { if (actor is null) { throw new ArgumentNullException(nameof(actor)); } if (currentState is null) { throw new ArgumentNullException(nameof(currentState)); } if (strategyData is null) { throw new ArgumentNullException(nameof(strategyData)); } //TODO Здесь лучше проверять на наличие эффекта раны var hpStat = actor.Person.GetModule <ISurvivalModule>().Stats .SingleOrDefault(x => x.Type == SurvivalStatType.Health); var isLowHp = hpStat.ValueShare <= 0.5f; if (!isLowHp) { return(false); } // var props = actor.Person.GetModule <IInventoryModule>().CalcActualItems(); var resources = props.OfType <Resource>(); var taskContext = new ActorTaskContext(context.Sector); var bestResource = ResourceFinder.FindBestConsumableResourceByRule( actor, taskContext, resources, ConsumeCommonRuleType.Health); if (bestResource == null) { return(false); } return(true); }
private static UsePropTask CreateTask(IActor actor, ISectorTaskSourceContext context, ILogicStrategyData strategyData) { if (strategyData.ResourceToReduceHazard is null) { throw new InvalidOperationException( $"Assign {nameof(strategyData.ResourceToReduceHazard)} value in the triggers first."); } var taskContxt = new ActorTaskContext(context.Sector); var prop = strategyData.ResourceToReduceHazard; // When prop was used it no need to store anymore. strategyData.ResourceToReduceHazard = null; return(new UsePropTask(actor, taskContxt, prop)); }
public override IActorTask GetTask(IActor actor, ISectorTaskSourceContext context, ILogicStrategyData strategyData) { if (_idleTask == null) { var taskContext = new ActorTaskContext(context.Sector); _idleTask = new IdleTask(actor, taskContext, _decisionSource); } if (_idleTask.IsComplete) { Complete = true; return(null); } return(_idleTask); }
public override IActorTask GetTask(IActor actor, ISectorTaskSourceContext context, ILogicStrategyData strategyData) { if (actor is null) { throw new System.ArgumentNullException(nameof(actor)); } if (context is null) { throw new System.ArgumentNullException(nameof(context)); } var hpStat = actor.Person.GetModule <ISurvivalModule>().Stats .SingleOrDefault(x => x.Type == SurvivalStatType.Health); if (hpStat == null) { Complete = true; return(null); } var hpStatCoeff = (float)hpStat.Value / (hpStat.Range.Max - hpStat.Range.Min); var isLowHp = hpStatCoeff <= 0.5f; if (!isLowHp) { Complete = true; return(null); } var props = actor.Person.GetModule <IInventoryModule>().CalcActualItems(); var resources = props.OfType <Resource>(); var bestResource = ResourceFinder.FindBestConsumableResourceByRule(resources, ConsumeCommonRuleType.Health); if (bestResource == null) { Complete = true; return(null); } var taskContext = new ActorTaskContext(context.Sector); return(new UsePropTask(actor, taskContext, bestResource)); }
public override IActorTask GetTask(IActor actor, ISectorTaskSourceContext context, ILogicStrategyData strategyData) { if (strategyData.TargetEquipment is null || strategyData.TargetEquipmentSlotIndex is null) { throw new InvalidOperationException("Assign TargetEquipment and TargetEquipmentSlot in trigger first."); } var targetEquipmentFromInventory = strategyData.TargetEquipment; var targetSlotIndex = strategyData.TargetEquipmentSlotIndex; var taskContext = new ActorTaskContext(context.Sector); var task = new EquipTask(actor, taskContext, targetEquipmentFromInventory, targetSlotIndex.Value); Complete = true; return(task); }
public override IActorTask GetTask(IActor actor, ISectorTaskSourceContext context, ILogicStrategyData strategyData) { if (MoveTask == null) { MoveTask = CreateBypassMoveTask(actor, strategyData, context.Sector); if (MoveTask != null) { return(MoveTask); } // Это может произойти, если актёр не выбрал следующий узел. // Тогда переводим актёра в режим ожидания. var taskContext = new ActorTaskContext(context.Sector); IdleTask = new IdleTask(actor, taskContext, DecisionSource); return(IdleTask); } if (!MoveTask.IsComplete) { // Если команда на перемещение к целевой точке патруля не закончена, // тогда продолжаем её. // Предварительно проверяем, не мешает ли что-либо её продолжить выполнять. if (!MoveTask.CanExecute()) { MoveTask = CreateBypassMoveTask(actor, strategyData, context.Sector); } if (MoveTask != null) { return(MoveTask); } var taskContext = new ActorTaskContext(context.Sector); IdleTask = new IdleTask(actor, taskContext, DecisionSource); return(IdleTask); } Complete = true; return(null); }
public override IActorTask GetTask(IActor actor, ISectorTaskSourceContext context, ILogicStrategyData strategyData) { var sector = context.Sector; var map = sector.Map; if (!strategyData.ExitNodes.Any()) { Complete = true; return(null); } var actorNode = actor.Node; if (map.Transitions.TryGetValue(actorNode, out var currentTransition)) { var taskContext = new ActorTaskContext(sector); var transitionTask = new SectorTransitTask(actor, taskContext); Complete = true; return(transitionTask); } if (_moveTask == null || _moveTask.IsComplete || !_moveTask.CanExecute()) { var nearbyExitNode = strategyData.ExitNodes .OrderBy(x => map.DistanceBetween(actor.Node, x)) .First(); _moveTask = CreateMoveTask(actor, nearbyExitNode, sector, map); if (_moveTask == null) { Complete = true; return(null); } return(_moveTask); } return(_moveTask); }
public bool Test(IActor actor, ISectorTaskSourceContext context, ILogicState currentState, ILogicStrategyData strategyData) { if (actor is null) { throw new System.ArgumentNullException(nameof(actor)); } if (currentState is null) { throw new System.ArgumentNullException(nameof(currentState)); } if (strategyData is null) { throw new System.ArgumentNullException(nameof(strategyData)); } var currentInventoryEquipments = actor.Person.GetModule <IInventoryModule>().CalcActualItems().OfType <Equipment>(); for (int i = 0; i < actor.Person.GetModule <IEquipmentModule>().Slots.Length; i++) { var slot = actor.Person.GetModule <IEquipmentModule>().Slots[i]; var equiped = actor.Person.GetModule <IEquipmentModule>()[i]; if (equiped == null) { var availableEquipments = currentInventoryEquipments .Where(x => (x.Scheme.Equip.SlotTypes[0] & slot.Types) > 0); if (availableEquipments.Any()) { return(true); } } } return(false); }
public bool Test(IActor actor, ISectorTaskSourceContext context, ILogicState currentState, ILogicStrategyData strategyData) { if (actor is null) { throw new ArgumentNullException(nameof(actor)); } if (context is null) { throw new ArgumentNullException(nameof(context)); } if (currentState is null) { throw new ArgumentNullException(nameof(currentState)); } if (strategyData is null) { throw new ArgumentNullException(nameof(strategyData)); } var map = context.Sector.Map; var actorManager = context.Sector.ActorManager; var nearbyIntruder = IntruderDetectionHelper.GetIntruder(actor, map, actorManager); // Remember last intruder for logic with will handle reaction. strategyData.TriggerIntuder = nearbyIntruder; if (nearbyIntruder is null) { return(false); } return(true); }
private bool SelectCurrentState(ILogicState currentState, ISectorTaskSourceContext context, out ILogicState newState) { var transitionWasPerformed = false; newState = null; var currentStateTransitions = _stateTree.Transitions[CurrentState]; foreach (var transition in currentStateTransitions) { var trigger = transition.Trigger; var isFired = trigger.Test(Actor, context, currentState, _strategyData); if (isFired) { newState = transition.NextState; transitionWasPerformed = true; break; } } return(transitionWasPerformed); }
protected abstract bool TestInner( [NotNull] IActor actor, [NotNull] ISectorTaskSourceContext context, [NotNull] ILogicState currentState, [NotNull] ILogicStrategyData strategyData);
public abstract IActorTask GetTask(IActor actor, ISectorTaskSourceContext context, ILogicStrategyData strategyData);
protected override bool TestInner(IActor actor, ISectorTaskSourceContext context, ILogicState currentState, ILogicStrategyData strategyData) { return(SurvivalHazardTriggerHelper.TestHazardAndResource(actor, strategyData, SurvivalStatType.Hydration, ConsumeCommonRuleType.Thirst)); }