public override IEnumerable <IActionEffect> Execute() { ++_gameContext.CurrentDungeonIndex; if (_gameContext.CurrentDungeonIndex < 6) { GameObject.Find("PrisonLevelIndicator").GetComponent <Text>().text = "Prison level: " + -(5 - _gameContext.CurrentDungeonIndex); } if (_gameContext.CurrentDungeonIndex >= _gameContext.Dungeons.Count) { _textEffectPresenter.ShowTextEffect(ActorData.LogicalPosition, "Sniff! It's... It's fresh air!", Color.yellow); _gameContext.PlayerActor.ActorData.LogicalPosition = new Vector2Int(6, -41); // dawno tego nie robiłem... niesamowite uczucie //new Vector2Int(5, -65); // this leads close to Farwis. dawno tego nie robiłem... niesamowite uczucie _gameContext.PlayerActor.ActorData.VisionRayLength = 8; _gameContext.VisiblePositions = new HashSet <Vector2Int>(); IEnumerable <ActorData> enemiesAround = _entityDetector.DetectActors(_gameContext.PlayerActor.ActorData.LogicalPosition, 20) .Where(a => a.Team == Team.Beasts); foreach (var actorData in enemiesAround) { actorData.VisionRayLength = 8; } //this still breaks the field of view! } else { Dungeon nextDungeon = _gameContext.Dungeons[_gameContext.CurrentDungeonIndex]; BoundsInt furthestRoomToStairs = FurthestRoomToStairsResolver.GetFurthestRoomToStairs(nextDungeon); Vector2Int startingPosition = new Vector2Int((int)furthestRoomToStairs.center.x, (int)furthestRoomToStairs.center.y); _gameContext.PlayerActor.ActorData.LogicalPosition = startingPosition; TileBase stairsDownTile = Resources.Load <TileBase>("Tiles/Environment/Stairs_down"); _gameContext.EnvironmentTilemap.SetTile(startingPosition.ToVector3Int(), stairsDownTile); _gameContext.WallsTilemap.SetTile(startingPosition.ToVector3Int(), null); IEnumerable <ActorData> actorAround = _entityDetector.DetectActors(startingPosition, 3); foreach (var actorData in actorAround) { _entityRemover.CleanSceneAndGameContextAfterDeath(actorData); Debug.Log("Removing an actor, because he was too close: " + actorData.ActorType); } } Action action = () => { _gameContext.PlayerActor.RefreshWorldPosition(); }; yield return(new LambdaEffect(action)); }
/// <summary> /// It's assuming that from @from to to there are exactly two steps! /// </summary> public bool ClearWayExists(Vector2Int @from, Vector2Int to) { Func <float, bool> isIntegral = val => Math.Abs(val % 1) < .001f; float middleX = ((float)@from.x + to.x) / 2; float middleY = ((float)@from.y + to.y) / 2; int[] xsToCheck = isIntegral(middleX) ? new[] { (int)middleX } : new[] { Mathf.CeilToInt(middleX), Mathf.FloorToInt(middleX) }; int[] ysToCheck = isIntegral(middleY) ? new[] { (int)middleY } : new[] { Mathf.CeilToInt(middleY), Mathf.FloorToInt(middleY) }; foreach (int x in xsToCheck) { foreach (int y in ysToCheck) { bool actorIsBlockingWay = _entityDetector.DetectActors(new Vector2Int(x, y)).Any(); bool wayIsWalkable = _gridInfoProvider.IsWalkable(new Vector2Int(x, y)); if (wayIsWalkable && !actorIsBlockingWay) { return(true); } } } return(false); }
private int GetEmptyPositionsAround(ActorData actorData) { int emptyPositions = 8; var positionsAround = Vector2IntUtilities.Neighbours8(actorData.LogicalPosition); foreach (Vector2Int position in positionsAround) { if (!_gridInfoProvider.IsWalkable(position) || _entityDetector.DetectActors(position).Any()) { --emptyPositions; } } return(emptyPositions); }
public override IEnumerable <IActionEffect> Execute() { Vector2Int previousPosition = ActorData.LogicalPosition; Vector2Int newPosition = previousPosition + Direction; if (_gridInfoProvider.IsWalkable(newPosition)) { if (ActorData.ActorType == ActorType.Player && _gameContext.EnvironmentTilemap.HasTile(newPosition.ToVector3Int())) { TileBase stairsDownTile = Resources.Load <TileBase>("Tiles/Environment/Stairs_down"); if (_gameContext.EnvironmentTilemap.GetTile(newPosition.ToVector3Int()) == stairsDownTile) { _textEffectPresenter.ShowTextEffect(ActorData.LogicalPosition, "Back down? Never!", Color.yellow); } } if (_gameContext.BasherSteps == 0 && ActorData.ActorType == ActorType.Basher && Vector2IntUtilities.WalkDistance(ActorData.LogicalPosition, _gameContext.PlayerActor.ActorData.LogicalPosition) <= 5) { _gameContext.BasherSteps = 1; _uiConfig.BasherMessage.gameObject.SetActive(true); _uiConfig.BasherMessage.SetMessage("Ha! So you didn't disappoint me! Finally I see you again, my rattish friend! As you might " + "have guessed, that was me that sent you the key. I'll be happy to take you away from this scary place. But first " + "we have to deal with one thing. You saved my life by attributing to yourself my deeds against the revolutionists. " + "But this also made me feel like a lousy coward. My honour has been terribly undermined and I need to clean it. " + "I challenge you to a duel! No magic, no eating, just me, you and steel. Prepare!"); IEnumerable <ActorData> friendsAndBuddies = _entityDetector.DetectActors(ActorData.LogicalPosition, 15) .Where(a => a.ActorType == ActorType.Friend || a.ActorType == ActorType.Buddy); foreach (var friendOrBuddy in friendsAndBuddies) { _deathHandler.HandleDeath(friendOrBuddy); } } IActionEffect effect = ActionEffectFactory.CreateMoveEffect(ActorData, previousPosition); ActorData.LogicalPosition = newPosition; if (ActorData.CaughtActor != null) { ActorData.CaughtActor.LogicalPosition = newPosition; } yield return(effect); } else { IActionEffect effect = ActionEffectFactory.CreateBumpEffect(ActorData, newPosition); yield return(effect); } }
private Vector2Int GetPositionToPlaceActor(Vector2Int position) { 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.DetectActors(neighbour).Any()) { return(neighbour); } } return(position); }
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); } } } }
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); } }
private IGameAction ResolveActionForAggresion(ActorData actorData) { if (_rng.Check(0.04f)) { if (_gameContext.PlayerActor.ActorData.Health <= 0) { if (_rng.Check(0.07f)) { string text = _rng.Choice(new[] { "Ha, ha!", "I got him!", "I know my strength!", "Got what he deserved!", "Guess what we'll cook for dinner..." }); _textEffectPresenter.ShowTextEffect(actorData.LogicalPosition, text); } } else if (actorData.ActorType == ActorType.Dog && actorData.Team != Team.Beasts) { string text = _rng.Choice(new[] { "Woof", "Wrrrr!" }); _textEffectPresenter.ShowTextEffect(actorData.LogicalPosition, text); } else if (actorData.ActorType == ActorType.LastMonster) { var potential = new[] { "Whshsh!", "Rrrruv!" }.ToList(); if (!actorData.Entity.IsVisible) { potential.AddRange(new[] { "[THUD!]", "[THUD!]", "[THUD!]" }); } string text = _rng.Choice(potential); _textEffectPresenter.ShowTextEffect(actorData.LogicalPosition, text, text == "[THUD!]" ? Color.white : Color.magenta, true); } else if (actorData.ActorType == ActorType.Friend || actorData.ActorType == ActorType.Buddy) { string text = _rng.Choice(new[] { "Ma-uluh, ruv!", "Suku bgeve lir...", "Alir tak rettenekopast!" }); _textEffectPresenter.ShowTextEffect(actorData.LogicalPosition, text, new Color(0.7f, 0.8f, 1f)); } else if (actorData.ActorType != ActorType.Basher && actorData.ActorType != ActorType.LastMonster) { string text = _rng.Choice(new[] { "Back to your ward!", "Squeak!", "You're mine!", "Comrades, help me!", "Aah!" }); _textEffectPresenter.ShowTextEffect(actorData.LogicalPosition, text); } } List <ActorData> enemiesClose = _entityDetector.DetectActors(actorData.LogicalPosition, actorData.VisionRayLength) .Where(a => a.Team != actorData.Team && a.Entity.IsVisible) .ToList(); enemiesClose.Sort((first, second) => Vector2IntUtilities.WalkDistance(first.LogicalPosition, actorData.LogicalPosition) .CompareTo(Vector2IntUtilities.WalkDistance(second.LogicalPosition, actorData.LogicalPosition)) ); ActorData closestEnemy = enemiesClose.FirstOrDefault(); if (closestEnemy != null) { Vector2Int toEnemy = closestEnemy.LogicalPosition - actorData.LogicalPosition; // mam nadzieje, ze zadziala if (Vector2IntUtilities.WalkDistance(closestEnemy.LogicalPosition, actorData.LogicalPosition) == 2) { // move towards player if possible and desired bool possible = false; Vector2Int?legalMove = null; Vector2Int directionToEnemy = Vector2IntUtilities.Normalized(toEnemy); IEnumerable <Vector2Int> candidateMovesToEnemy = Vector2IntUtilities.GetCone(directionToEnemy) .Select(coneVector => coneVector - directionToEnemy) .Where(fixedConeVector => fixedConeVector != actorData.LogicalPosition); IList <Vector2Int> candidateMovesShuffled = _rng.Shuffle(candidateMovesToEnemy); foreach (var cand in candidateMovesShuffled) { if (!_entityDetector.DetectActors(actorData.LogicalPosition + cand).Any() && _gridInfoProvider.IsWalkable(actorData.LogicalPosition + cand)) { legalMove = cand; break; } } if (legalMove.HasValue) { int closeCombatAdvantage = actorData.WeaponWeld.WeaponDefinition.CloseCombatModifier - closestEnemy.WeaponWeld.WeaponDefinition.CloseCombatModifier; if (closeCombatAdvantage < 0) { closeCombatAdvantage = 0; } float chanceToMove = .1f + 0.2f * closeCombatAdvantage; if (_rng.Check(chanceToMove)) { return(_actionFactory.CreateMoveAction(actorData, legalMove.Value)); } } } if (Vector2IntUtilities.IsOneStep(toEnemy) || (actorData.WeaponWeld.WeaponDefinition.AllowsFarCombat && Vector2IntUtilities.IsOneOrTwoSteps(toEnemy) && _clearWayBetweenTwoPointsDetector.ClearWayExists(actorData.LogicalPosition, closestEnemy.LogicalPosition))) { IGameAction actionToPerform; bool pushingIsPossible = actorData.AiTraits.Contains(AiTrait.Pusher) && Vector2IntUtilities.IsOneStep(toEnemy) && _gridInfoProvider.IsWalkable(closestEnemy.LogicalPosition + toEnemy); bool pushingIsDesired = false; if (pushingIsPossible) { float pushingChanceScore = 0.08f; if (actorData.WeaponWeld.WeaponDefinition.CloseCombatModifier < closestEnemy.WeaponWeld.WeaponDefinition.CloseCombatModifier) { pushingChanceScore += .25f; } if (!_gridInfoProvider.IsWalkable(closestEnemy.LogicalPosition + toEnemy + toEnemy)) { pushingChanceScore += .2f; } if (_rng.Check(pushingChanceScore)) { pushingIsDesired = true; } } if (pushingIsPossible && pushingIsDesired) { actionToPerform = _actionFactory.CreatePushAction(actorData, closestEnemy); } else { bool isInGoodPosition = Vector2IntUtilities.IsOneStep(toEnemy) && actorData.WeaponWeld.WeaponDefinition.CloseCombatModifier > closestEnemy.WeaponWeld.WeaponDefinition.CloseCombatModifier; if (Vector2IntUtilities.IsOneOrTwoSteps(toEnemy) && !isInGoodPosition) // && actorData.AiTraits.Contains(AiTrait.Careful))) { float chanceToStepBack = 0f; float healthFactor = (1 - actorData.HealthProgress) * .15f; float swordsFactor = (closestEnemy.Swords - actorData.Swords) * .15f; chanceToStepBack = healthFactor + swordsFactor; if (_rng.Check(chanceToStepBack)) { Vector2Int directionFromEnemy = Vector2IntUtilities.Normalized(toEnemy) * -1; IEnumerable <Vector2Int> positionsToStepBack = Vector2IntUtilities.GetCone(directionFromEnemy) .Select(coneVector => actorData.LogicalPosition + coneVector - directionFromEnemy) .Where(position => position != actorData.LogicalPosition); foreach (var conePosition in positionsToStepBack) { if (!_gridInfoProvider.IsWalkable(conePosition) || _entityDetector.DetectEntities(conePosition).Any()) { continue; } Vector2Int stepBackMoveVector = conePosition - actorData.LogicalPosition; return(_actionFactory.CreateMoveAction(actorData, stepBackMoveVector)); } } } bool isDaringBlow = false; if (actorData.Traits.Contains(Trait.DaringBlow) && actorData.Swords >= 2) { float daringBlowChance = actorData.AiTraits.Contains(AiTrait.Aggressive) ? .5f : .2f; if (actorData.ActorType == ActorType.Basher) { daringBlowChance += .2f; } if (_rng.Check(daringBlowChance)) { isDaringBlow = true; } } actionToPerform = _actionFactory.CreateAttackAction(actorData, closestEnemy, isDaringBlow); } if (DateTime.UtcNow < closestEnemy.BlockedUntil) { actorData.StoredAction = actionToPerform; actorData.BlockedUntil = closestEnemy.BlockedUntil; return(null); } return(actionToPerform); } int moveX = toEnemy.x.CompareTo(0); int moveY = toEnemy.y.CompareTo(0); Vector2Int moveVector = new Vector2Int(moveX, moveY); Func <Vector2Int, bool> isWalkableAndFree = position => _gridInfoProvider.IsWalkable(position) && !_entityDetector.DetectActors(position).Any(); if (!isWalkableAndFree(actorData.LogicalPosition + moveVector)) { Vector2Int?finalMoveVector = null; Vector2Int alternativeMoveVector1; Vector2Int alternativeMoveVector2; // trying to find best alternative vectors to move if (moveVector.x == 0) { alternativeMoveVector1 = new Vector2Int(+1, moveVector.y); alternativeMoveVector2 = new Vector2Int(-1, moveVector.y); } else if (moveVector.y == 0) { alternativeMoveVector1 = new Vector2Int(moveVector.x, -1); alternativeMoveVector2 = new Vector2Int(moveVector.x, +1); } else { alternativeMoveVector1 = new Vector2Int(moveVector.x, 0); alternativeMoveVector2 = new Vector2Int(0, moveVector.y); } if (isWalkableAndFree(actorData.LogicalPosition + alternativeMoveVector1)) { finalMoveVector = alternativeMoveVector1; } else if (isWalkableAndFree(actorData.LogicalPosition + alternativeMoveVector2)) { finalMoveVector = alternativeMoveVector2; } if (finalMoveVector.HasValue) { return(_actionFactory.CreateMoveAction(actorData, finalMoveVector.Value)); } return(_actionFactory.CreatePassAction(actorData)); } return(_actionFactory.CreateMoveAction(actorData, moveVector)); } else if (actorData.Team == Team.Beasts) { ActorData playerClose = _entityDetector.DetectActors(actorData.LogicalPosition, actorData.VisionRayLength).FirstOrDefault( f => f != actorData && f.ActorType == ActorType.Player); if (playerClose != null) { Vector2Int toFriend = playerClose.LogicalPosition - actorData.LogicalPosition; Vector2Int directionToFriend = Vector2IntUtilities.Normalized(toFriend); Vector2Int legalMove = new Vector2Int(); IEnumerable <Vector2Int> candidateMovesToFriend = Vector2IntUtilities.GetCone(directionToFriend) .Select(coneVector => coneVector - directionToFriend) .Where(fixedConeVector => fixedConeVector != actorData.LogicalPosition); IList <Vector2Int> candidateMovesShuffled = _rng.Shuffle(candidateMovesToFriend); foreach (var cand in candidateMovesShuffled) { if (!_entityDetector.DetectActors(actorData.LogicalPosition + cand).Any() && _gridInfoProvider.IsWalkable(actorData.LogicalPosition + cand)) { legalMove = cand; break; } } Vector2Int moveVector = legalMove; if (!_entityDetector.DetectActors(actorData.LogicalPosition + moveVector).Any()) { return(_actionFactory.CreateMoveAction(actorData, moveVector)); } } return(_actionFactory.CreatePassAction(actorData)); } if (Vector2IntUtilities.WalkDistance(actorData.LogicalPosition, _gameContext.PlayerActor.ActorData.LogicalPosition) < 15 && _gameContext.PlayerActor.ActorData.Health > 0 && actorData.ActorType != ActorType.Basher) { Vector2Int?farReachablePoint = GetFarReachablePoint(actorData); if (farReachablePoint.HasValue) { Vector2Int moveVector = Vector2IntUtilities.Normalized(farReachablePoint.Value - actorData.LogicalPosition); return(_actionFactory.CreateMoveAction(actorData, moveVector)); } } return(_actionFactory.CreatePassAction(actorData)); }
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); }
public void Heartbeat(ActorData actorData) { ++actorData.RoundsCount; BoundsInt lastLevelBounds = new BoundsInt(-18, -103, 0, 49, 72, 1); BoundsInt almostLastLevelBounds = new BoundsInt(-16, -101, 0, 45, 68, 1); if (actorData.ActorType == ActorType.Player && _gameContext.CurrentDungeonIndex >= _gameContext.Dungeons.Count && !almostLastLevelBounds.Contains(actorData.LogicalPosition.ToVector3Int())) { _textEffectPresenter.ShowTextEffect(actorData.LogicalPosition, "Almost free!", Color.yellow); } if (actorData.ActorType == ActorType.Player && _gameContext.CurrentDungeonIndex >= _gameContext.Dungeons.Count && !lastLevelBounds.Contains(actorData.LogicalPosition.ToVector3Int())) { var finisher = _uiConfig.GameFinisher; finisher.gameObject.SetActive(true); finisher.Initialize(actorData); } //if (actorData.Health < actorData.MaxHealth) // ++actorData.Health; IEnumerable <ActorData> enemiesNearby = _entityDetector.DetectActors(actorData.LogicalPosition, 2) .Where(a => a.Team != actorData.Team); if (enemiesNearby.Any(a => Vector2IntUtilities.IsOneStep(a.LogicalPosition, actorData.LogicalPosition))) { actorData.IsInCloseCombat = true; } else { actorData.IsInCloseCombat = false; } actorData.HasLittleSpace = _playerSpaceResolver.ResolveIfPlayerHasLittleSpace(actorData); int maxSwords = _maxSwordCalculator.Calculate(actorData); actorData.MaxSwords = maxSwords; if (actorData.Swords > maxSwords) { actorData.Swords = maxSwords; } if (actorData.Swords < maxSwords) { if (actorData.WeaponWeld.WeaponDefinition.RecoveryTime == RecoveryTime.ThreePerSeven) { int roundNumber = actorData.RoundsCount % 21; if (new[] { 0, 3, 5, 8, 10, 13, 15, 18, 20 }.Contains(roundNumber)) { ++actorData.Swords; } } else if (actorData.WeaponWeld.WeaponDefinition.RecoveryTime == RecoveryTime.OnePerTwo && actorData.RoundsCount % 2 == 0) { ++actorData.Swords; } else if (actorData.WeaponWeld.WeaponDefinition.RecoveryTime == RecoveryTime.ThreePerFive) { int roundNumber = actorData.RoundsCount % 15; if (new[] { 0, 2, 5, 7, 10, 12 }.Contains(roundNumber)) { ++actorData.Swords; } } } if (actorData.Entity.transform.GetComponentInChildren <SwordsIndicator>() == null /*inactive*/) { } else { actorData.Entity.transform.GetComponentInChildren <SwordsIndicator>().UpdateActiveSwords(actorData.Swords); // kind of ugly workaround, but seems to help } if (actorData.ControlledByPlayer) { if (actorData.Xp >= _gameConfig.XpForLevels[actorData.Level + 1]) { ++actorData.Level; _uiConfig.AdvanceManager.gameObject.SetActive(true); GameObject.Find("PlayerLevelIndicator").GetComponent <Text>().text = "Player level: " + actorData.Level; } } }