Exemplo n.º 1
0
        /// <summary>
        /// Immediately attempts to perform a creature movement to a tile on the map.
        /// </summary>
        /// <param name="context">A reference to the operation context.</param>
        /// <param name="creature">The creature being moved.</param>
        /// <param name="toLocation">The tile to which the movement is being performed.</param>
        /// <param name="isTeleport">Optional. A value indicating whether the movement is considered a teleportation. Defaults to false.</param>
        /// <param name="requestorCreature">Optional. The creature that this movement is being performed in behalf of, if any.</param>
        /// <returns>True if the movement was successfully performed, false otherwise.</returns>
        /// <remarks>Changes game state, should only be performed after all pertinent validations happen.</remarks>
        private bool PerformCreatureMovement(IOperationContext context, ICreature creature, Location toLocation, bool isTeleport = false, ICreature requestorCreature = null)
        {
            if (creature == null || !(creature.ParentContainer is ITile fromTile) || !context.Map.HasTileAt(toLocation, out ITile toTile))
            {
                return(false);
            }

            var moveDirection = fromTile.Location.DirectionTo(toLocation, true);

            // Try to figure out the position in the stack of the creature.
            var fromTileStackPos = fromTile.GetIndexOfThing(creature);

            if (fromTileStackPos == byte.MaxValue)
            {
                // couldn't find this creature in this tile...
                return(false);
            }

            // Do the actual move first.
            if (!fromTile.RemoveCreature(creature))
            {
                return(false);
            }

            if (!toTile.AddCreature(creature))
            {
                // attempt to rollback state.
                if (!fromTile.RemoveCreature(creature))
                {
                    // Leaves us in a really bad spot.
                    throw new ApplicationException("Unable to rollback state after filing to move creature. Game state is altered and inconsistent now.");
                }
            }

            var toStackPosition = toTile.GetIndexOfThing(creature);

            if (toStackPosition == byte.MaxValue)
            {
                context.Logger.LogWarning("Unexpected destination stack position during creature movement, suggests that the creature is not found in the destination tile after the move.");
            }

            // Then deal with the consequences of the move.
            ((Creature)creature).Direction = moveDirection;
            ((Creature)creature).LastMovementCostModifier = (fromTile.Location - toLocation).Z != 0 ? 2 : moveDirection.IsDiagonal() ? 3 : 1;

            this.ExhaustionInfo[ExhaustionFlag.Movement] = creature.CalculateStepDuration(fromTile);

            this.SendNotification(
                context,
                new CreatureMovedNotification(
                    context.Map.FindPlayersThatCanSee(fromTile.Location, toLocation),
                    context.Map,
                    creature,
                    fromTile.Location,
                    fromTileStackPos,
                    toTile.Location,
                    toStackPosition,
                    isTeleport));

            return(true);
        }