Beispiel #1
0
 private Vector2Int GetPositionToPlaceItem(Vector2Int position)
 {
     if (_entityDetector.DetectItems(position).Any())
     {
         List <Vector2Int> candidates = Vector2IntUtilities.Neighbours8(position);
         var candidatesFurther        = Vector2IntUtilities.Neighbours8(Vector2Int.zero)
                                        .Select(v => new Vector2Int(v.x * 2, v.y * 2))
                                        .Select(v => position + v);
         candidates.AddRange(candidatesFurther);
         foreach (Vector2Int neighbour in candidates)
         {
             if (_gridInfoProvider.IsWalkable(neighbour) && !_entityDetector.DetectItems(neighbour).Any())
             {
                 position = neighbour;
                 break;
             }
         }
     }
     return(position);
 }
Beispiel #2
0
        public override IEnumerable <IActionEffect> Execute()
        {
            if (_fromInventory)
            {
                _uiConfig.ItemHolder.RemoveItem(_uiConfig.ItemHolder.SelectedItemIndex);
            }
            else
            {
                ItemData itemAtFeet = _entityDetector.DetectItems(ActorData.LogicalPosition).First(i => i.ItemType == _item.ItemType);
                _entityRemover.RemoveItem(itemAtFeet);
            }

            bool isAllowed = !
                             (_gameContext.BasherSteps == 1 &&
                              new[]
            {
                ItemType.PotionOfBuddy, ItemType.PotionOfFriend, ItemType.PotionOfHealing,
                ItemType.PotionOfLight, ItemType.Food
            }
                              .Contains(_item.ItemType)
                             );

            if (_item.ItemType == ItemType.PotionOfRecoverTail)
            {
                _textEffectPresenter.ShowTextEffect(ActorData.LogicalPosition, "Squeak! At last!", Color.yellow);
            }
            else
            {
                _textEffectPresenter.ShowTextEffect(ActorData.LogicalPosition, isAllowed ? "Ha!" : "Oh, it doesn't work!", Color.yellow);
            }

            if (_item.ItemType == ItemType.Weapon)
            {
                ItemDefinition previousWeapon = ActorData.WeaponWeld;
                if (_fromInventory)
                {
                    _uiConfig.ItemHolder.AddItem(previousWeapon);
                }
                else
                {
                    if (previousWeapon.Name == "Key")
                    {
                        _entitySpawner.SpawnItem(previousWeapon, ActorData.LogicalPosition);
                    }
                    else
                    {
                        _entitySpawner.SpawnWeapon(previousWeapon.WeaponDefinition, ActorData.LogicalPosition, previousWeapon);
                    }
                }
                Image currentWeaponSprite = _uiConfig.CurrentWeaponHolder.gameObject.transform.Find("Image")
                                            .gameObject.GetComponent <Image>();
                _uiConfig.TooltipCurrentWeaponPresenter.GetComponent <CurrentWeaponTooltip>().LabelWearingUpper.gameObject.SetActive(true);
                _uiConfig.TooltipCurrentWeaponPresenter.Present(_item, true);
                _uiConfig.TooltipPresenter.gameObject.SetActive(false);
                currentWeaponSprite.sprite = _item.Sprite;
                currentWeaponSprite.color  = Color.white;

                ActorData.WeaponWeld = _item;
                Action effectAction = () => ((ActorBehaviour)ActorData.Entity).WeaponAnimator.Awake();
                var    effect       = new LambdaEffect(effectAction);
                yield return(effect);
            }
            else if (_item.ItemType == ItemType.PotionOfRecoverTail)
            {
                Sprite withTailSprite = Resources.Load <Sprite>("Sprites/Characters/player_with_tail");
                ActorData.Entity.SpriteRenderer.sprite = withTailSprite;
                ActorData.HasTail = true;
            }
            else if (isAllowed)
            {
                if (_item.ItemType == ItemType.Food)
                {
                    ActorData.Health += (int)(ActorData.MaxHealth * 0.3f);
                    if (ActorData.Health > ActorData.MaxHealth)
                    {
                        ActorData.Health = ActorData.MaxHealth;
                    }
                }
                else if (_item.ItemType == ItemType.PotionOfHealing)
                {
                    ActorData.Health += (int)(ActorData.MaxHealth * 0.7f);
                    if (ActorData.Health > ActorData.MaxHealth)
                    {
                        ActorData.Health = ActorData.MaxHealth;
                    }
                }
                else if (_item.ItemType == ItemType.PotionOfBuddy)
                {
                    _entitySpawner.SpawnActor(ActorType.Buddy, ActorData.LogicalPosition);
                }
                else if (_item.ItemType == ItemType.PotionOfFriend)
                {
                    _entitySpawner.SpawnActor(ActorType.Friend, ActorData.LogicalPosition);
                }
                else if (_item.ItemType == ItemType.PotionOfLight)
                {
                    IEnumerable <ActorData> actorsAround = _entityDetector.DetectActors(ActorData.LogicalPosition, 4).Where(a => a != ActorData);
                    foreach (var actorData in actorsAround)
                    {
                        actorData.Energy -= (2 + _rng.NextFloat() * 2f);
                        actorData.Swords -= 1;
                        if (actorData.Swords < 0)
                        {
                            actorData.Swords = 0;
                        }
                        string text = "";
                        if (actorData.ActorType != ActorType.Dog)
                        {
                            text = _rng.Choice(new[] { "My eyes!", "I can't see!", "Oh!", "Squeak!" });
                        }
                        else
                        {
                            text = "Squeak!";
                        }
                        _textEffectPresenter.ShowTextEffect(actorData.LogicalPosition, text);
                    }
                }
            }
        }
Beispiel #3
0
        public virtual void Process()
        {
            bool visibleEnemiesClose = ActorData.ControlledByPlayer &&
                                       _entityDetector.DetectActors(ActorData.LogicalPosition, 3)
                                       .Count(a => a.Team != Team.Beasts && a.Entity.IsVisible) > 0;

            if (visibleEnemiesClose)
            {
                DateTime potentialBlockedUntil = DateTime.UtcNow + TimeSpan.FromMilliseconds(150);
                ActorData.BlockedUntil = potentialBlockedUntil > ActorData.BlockedUntil
                                        ? potentialBlockedUntil : ActorData.BlockedUntil;
            }

            IGameEntity     entity         = ActorData.Entity;
            IEntityAnimator entityAnimator = entity.EntityAnimator;

            IEnumerable <ActorData> enemiesNearby = _entityDetector.DetectActors(ActorData.LogicalPosition, 3)
                                                    .Where(e => ActorData.Team != e.Team)
                                                    .Where(e => Vector2IntUtilities.IsOneTwoOrThreeSteps(e.LogicalPosition, ActorData.LogicalPosition));

            // this code orientates the actor to face the closest danger, even if it means stepping backwards
            List <Vector2Int> directionsToOneStepEnemiesNearby = enemiesNearby.Select(e => e.LogicalPosition - ActorData.LogicalPosition)
                                                                 .Where(direction => Vector2IntUtilities.IsOneStep(direction))
                                                                 .ToList();
            List <Vector2Int> directionsToAllEnemiesNearby = enemiesNearby.Select(e => e.LogicalPosition - ActorData.LogicalPosition).ToList();
            List <Vector2Int> directionsToRelevantEnemiesNearby
                = directionsToOneStepEnemiesNearby.Any() ? directionsToOneStepEnemiesNearby : directionsToAllEnemiesNearby;

            bool thereAreSomeEnemiesOnOneSide = directionsToRelevantEnemiesNearby.Any()
                                                &&
                                                (directionsToRelevantEnemiesNearby.All(direction => direction.x < 0) ||
                                                 directionsToRelevantEnemiesNearby.All(direction => direction.x > 0));

            if (thereAreSomeEnemiesOnOneSide)
            {
                _actorAligner.AlignActorToDirection(ActorData.Entity, directionsToRelevantEnemiesNearby.First().x);
            }
            else
            {
                _actorAligner.AlignActorToDirection(ActorData.Entity, ActorData.LogicalPosition.x - PreviousPosition.x);
            }

            if (entity.IsVisible)
            {
                entityAnimator.MoveTo(PreviousPosition, ActorData.LogicalPosition);
            }
            else
            {
                Vector3 animationTargetPosition = _gridInfoProvider.GetCellCenterWorld(ActorData.LogicalPosition);

                // The next line makes this class kind of untestable, because ActorData.Entity is a MonoBehaviour. I believe it must be so,
                // so that we can see and assign the reference to it in the inspector window. If this happens more often in other effects,
                // we could maybe extract some kind of proxy class to keep the Entity, so that we can test with fake proxy.
                entity.Position = animationTargetPosition;
            }

            if (!ActorData.ControlledByPlayer)
            {
                return;
            }

            ItemData itemOnTheGround = _entityDetector.DetectItems(ActorData.LogicalPosition).FirstOrDefault();

            if (itemOnTheGround != null)
            {
                _uiConfig.TooltipPresenter.Present(itemOnTheGround.ItemDefinition, false);
            }
        }
Beispiel #4
0
        public IGameAction GetAction(ActorData actorData)
        {
            if (_inputHolder.PlayerInput == PlayerInput.None)
            {
                return(null);
            }

            if (_inputHolder.PlayerInput != PlayerInput.UseCurrentItem && _inputHolder.PlayerInput != PlayerInput.DropCurrentItem)
            {
                _uiConfig.ItemHolder.DeselectItem();
                _uiConfig.TooltipPresenter.Panel.gameObject.SetActive(false);
                _uiConfig.TooltipCurrentWeaponPresenter.gameObject.SetActive(false);
                _uiConfig.TooltipCurrentWeaponPresenter.GetComponent <CurrentWeaponTooltip>().LabelWearingUpper.gameObject.SetActive(false);
                var quitButton = GameObject.FindGameObjectWithTag("button_quit");
                if (quitButton != null)
                {
                    quitButton.SetActive(false);
                }
            }
            if (_uiConfig.WalkAbilityButton.GetComponentInChildren <Text>() != null)
            {
                _uiConfig.WalkAbilityButton.GetComponentInChildren <Text>().gameObject.SetActive(false);
            }
            if (_uiConfig.DaringBlowAbilityButton.GetComponentInChildren <Text>() != null)
            {
                _uiConfig.DaringBlowAbilityButton.GetComponentInChildren <Text>().gameObject.SetActive(false);
            }
            if (_uiConfig.PushAbilityButton.GetComponentInChildren <Text>() != null)
            {
                _uiConfig.PushAbilityButton.GetComponentInChildren <Text>().gameObject.SetActive(false);
            }

            IGameAction gameActionToReturn;

            if (_inputHolder.PlayerInput == PlayerInput.PickUp)
            {
                IList <ItemData> items            = _entityDetector.DetectItems(actorData.LogicalPosition).ToList();
                bool             allSlotsOccupied = _uiConfig.ItemHolder.Items.All(i => i != null);
                if (!items.Any() || allSlotsOccupied)
                {
                    return(null);
                }
                ItemData itemToPickUp = items.First();
                _inputHolder.PlayerInput = PlayerInput.None;
                return(_actionFactory.CreatePickUpAction(actorData, itemToPickUp));
            }

            if (_inputHolder.PlayerInput == PlayerInput.Drop)
            {
                ItemData firstItem = actorData.Items.FirstOrDefault();
                if (firstItem == null)
                {
                    return(null);
                }
                _inputHolder.PlayerInput = PlayerInput.None;
                return(_actionFactory.CreateDropAction(actorData, firstItem));
            }
            if (_inputHolder.PlayerInput == PlayerInput.Catch)
            {
                ActorData caughtActor = _entityDetector.DetectActors(actorData.LogicalPosition, 1).FirstOrDefault();
                if (caughtActor == null)
                {
                    return(null);
                }
                _inputHolder.PlayerInput = PlayerInput.None;
                return(_actionFactory.CreateCatchAction(actorData, caughtActor));
            }
            if (_inputHolder.PlayerInput == PlayerInput.Release)
            {
                if (actorData.CaughtActor == null)
                {
                    return(null);
                }
                _inputHolder.PlayerInput = PlayerInput.None;
                return(_actionFactory.CreateReleaseAction(actorData));
            }
            if (_inputHolder.PlayerInput == PlayerInput.Pass)
            {
                _inputHolder.PlayerInput = PlayerInput.None;
                return(_actionFactory.CreatePassAction(actorData));
            }
            if (_inputHolder.PlayerInput == PlayerInput.Eat)
            {
                _inputHolder.PlayerInput = PlayerInput.None;
                ItemData foodAtFeet = _entityDetector.DetectItems(actorData.LogicalPosition).FirstOrDefault(i => i.ItemType == ItemType.DeadBody);
                if (foodAtFeet == null)
                {
                    return(null);
                }
                return(_actionFactory.CreateEatAction(actorData, foodAtFeet));
            }
            if (_inputHolder.PlayerInput == PlayerInput.UseCurrentItem)
            {
                _inputHolder.PlayerInput = PlayerInput.None;
                ItemDefinition item;
                item = _uiConfig.ItemHolder.CurrentItem();
                if (item == null)
                {
                    ItemData itemAtFeet = _entityDetector.DetectItems(actorData.LogicalPosition).FirstOrDefault();
                    if (itemAtFeet != null)
                    {
                        item = itemAtFeet.ItemDefinition;
                        return(_actionFactory.CreateUseItemAction(actorData, item, false));
                    }
                    return(null);
                }
                return(_actionFactory.CreateUseItemAction(actorData, item, true));
            }
            if (_inputHolder.PlayerInput == PlayerInput.DropCurrentItem)
            {
                _inputHolder.PlayerInput = PlayerInput.None;
                ItemDefinition item = _uiConfig.ItemHolder.CurrentItem();
                if (item == null)
                {
                    return(null);
                }

                return(_actionFactory.CreateDropItemAction(actorData, item));
            }
            if (_inputHolder.PlayerInput == PlayerInput.Ascend)
            {
                TileBase stairsDown = Resources.Load <TileBase>("Tiles/Environment/Stairs_down");

                _inputHolder.PlayerInput = PlayerInput.None;
                Vector2Int playerPosition     = _gameContext.PlayerActor.ActorData.LogicalPosition;
                TileBase   envTileBelowPlayer = _gameContext.EnvironmentTilemap.GetTile(playerPosition.ToVector3Int());
                if (envTileBelowPlayer != null && envTileBelowPlayer != stairsDown)
                {
                    return(_actionFactory.CreateAscendAction(actorData));
                }
                return(null);
            }
            Vector2Int actionVector   = GetActionVector(_inputHolder.PlayerInput);
            Vector2Int targetPosition = actionVector + actorData.LogicalPosition;

            if (_inputHolder.PlayerInputModifier == PlayerInputModifier.Move)
            {
                _inputHolder.PlayerInputModifier = PlayerInputModifier.None;
                _inputHolder.PlayerInput         = PlayerInput.None;
                _arrowsVisibilityManager.Hide();

                IEnumerable <ActorData> actorsAtTarget = _entityDetector.DetectActors(targetPosition);
                if (actorsAtTarget.Any())
                {
                    return(null);
                }
                gameActionToReturn = _actionFactory.CreateMoveAction(actorData, actionVector);
                return(gameActionToReturn);
            }
            bool isAggressiveAttack = false;

            if (_inputHolder.PlayerInputModifier == PlayerInputModifier.DaringBlow)
            {
                isAggressiveAttack = true;
                _inputHolder.PlayerInputModifier = PlayerInputModifier.None;
                _inputHolder.PlayerInput         = PlayerInput.None;
                _weaponColorizer.Decolorize((actorData.Entity as ActorBehaviour).WeaponAnimator);
            }

            IList <Vector2Int> targetPositionsCone = Vector2IntUtilities.GetCone(actionVector)
                                                     .Select(zeroBasedPosition => actorData.LogicalPosition + zeroBasedPosition)
                                                     .ToList();
            IList <ActorData> actorsCloseToCone = _entityDetector.DetectActors(targetPosition, 2).ToList();

            ActorData targetActor;
            ActorData actorAtTargetPosition = actorsCloseToCone.FirstOrDefault(a => a.LogicalPosition == targetPosition);

            if (actorAtTargetPosition != null && actorAtTargetPosition.Team == actorData.Team)
            {
                _inputHolder.PlayerInput = PlayerInput.None;
                gameActionToReturn       = _actionFactory.CreateDisplaceAction(actorData, actorAtTargetPosition);
                return(gameActionToReturn);
            }

            bool isPushing = _inputHolder.PlayerInputModifier == PlayerInputModifier.Push;

            _arrowsVisibilityManager.Hide();
            _inputHolder.PlayerInputModifier = PlayerInputModifier.None;
            if ((actorAtTargetPosition != null || isPushing) || actorData.WeaponWeld.WeaponDefinition.AllowsFarCombat == false)
            {
                targetActor = actorAtTargetPosition;
            }
            else
            {
                targetActor = actorsCloseToCone
                              .FirstOrDefault(potentialTarget => potentialTarget.Team != actorData.Team &&
                                              targetPositionsCone.Contains(potentialTarget.LogicalPosition) &&
                                              _clearWayBetweenTwoPointsDetector.ClearWayExists(actorData.LogicalPosition, potentialTarget.LogicalPosition));
            }

            if (targetActor != null)            // hit!
            {
                gameActionToReturn = isPushing
                                        ? _actionFactory.CreatePushAction(actorData, targetActor)
                                        : _actionFactory.CreateAttackAction(actorData, targetActor, isAggressiveAttack);
            }
            else
            {
                TileBase wallTileAtTarget = _gameContext.WallsTilemap.GetTile(targetPosition.ToVector3Int());
                if (wallTileAtTarget != null)
                {
                    _heavyDoorsHClosedTile = Resources.Load <Tile>("Tiles/Environment/doors_HEAVY_0");
                    _heavyDoorsVClosedTile = Resources.Load <Tile>("Tiles/Environment/doors_HEAVY_2");
                    if ((wallTileAtTarget == _heavyDoorsHClosedTile || wallTileAtTarget == _heavyDoorsVClosedTile) &&
                        _uiConfig.ItemHolder.Items.Where(i => i != null).All(i => i.Name != "Key") &&
                        _gameContext.PlayerActor.ActorData.WeaponWeld.Name != "Key")
                    {
                        // bump
                        gameActionToReturn = _actionFactory.CreateMoveAction(actorData, actionVector);
                        _textEffectPresenter.ShowTextEffect(actorData.LogicalPosition, "Umph! Locked!", Color.yellow);
                    }
                    else
                    {
                        var doorsHClosedTile = Resources.Load <Tile>("Tiles/Environment/doors_H_closed");
                        var doorsVClosedTile = Resources.Load <Tile>("Tiles/Environment/doors_V_closed");

                        if (wallTileAtTarget == doorsHClosedTile || wallTileAtTarget == doorsVClosedTile)
                        {
                            bool isHorizontal = wallTileAtTarget == doorsHClosedTile;
                            gameActionToReturn = _actionFactory.CreateOpenDoorAction(actorData, targetPosition, isHorizontal);
                        }
                        else if (wallTileAtTarget == _heavyDoorsHClosedTile || wallTileAtTarget == _heavyDoorsVClosedTile)
                        {
                            bool isHorizontal = wallTileAtTarget == _heavyDoorsHClosedTile;
                            gameActionToReturn = _actionFactory.CreateOpenDoorAction(actorData, targetPosition, isHorizontal, true);
                        }
                        else
                        {
                            gameActionToReturn = _actionFactory.CreateMoveAction(actorData, actionVector);
                        }
                    }
                }
                else
                {
                    gameActionToReturn = _actionFactory.CreateMoveAction(actorData, actionVector);
                }
            }
            _inputHolder.PlayerInput = PlayerInput.None;
            return(gameActionToReturn);
        }