示例#1
0
        /// <summary>
        /// Calculate a circular list of <see cref="GridPosition"/>s around
        /// the passed <see cref="center"/> with a passed radius. The returned
        /// list is sorted by distance from <see cref="center"/>
        /// </summary>
        /// <param name="radius">Radius of circle (in grid units)</param>
        /// <param name="center">Center of circle in world space</param>
        /// <param name="length">Length of grid squares</param>
        /// <returns></returns>
        public static List <GridPosition> GetTilePositionsFromRadius(int radius, Vector2 center, int length)
        {
            int xPos = Mathf.RoundToInt(center.x / length);
            int zPos = Mathf.RoundToInt(center.y / length);
            SortedList <float, GridPosition> result = new SortedList <float, GridPosition>(25);

            for (var zCircle = -radius; zCircle <= radius; zCircle++)
            {
                for (var xCircle = -radius; xCircle <= radius; xCircle++)
                {
                    if (xCircle * xCircle + zCircle * zCircle < radius * radius)
                    {
                        var newPos   = new GridPosition(xPos + xCircle, zPos + zCircle);
                        var distance = newPos.Distance(new GridPosition(xPos, zPos));

                        while (result.ContainsKey(distance))
                        {
                            distance++;
                        }
                        result.Add(distance, newPos);
                    }
                }
            }

            var normResult = new List <GridPosition>(result.Count);

            normResult.AddRange(result.Values);

            return(normResult);
        }
        /// <summary>
        /// Gets the grid square preview color based on which LOD
        /// level it falls within.
        /// </summary>
        /// <returns></returns>
        private Color GetLodPreviewColor(GridPosition position)
        {
            if (Generator == null || Generator.Lod == null)
            {
                return(Color.white);
            }

            bool    isCenter00 = !Application.isPlaying && Application.isEditor || Generator.TrackedObject == null;
            Vector3 worldXYZ   = isCenter00 ? Vector3.zero : Generator.TrackedObject.transform.position;
            Vector3 worldXZ    = new Vector2(worldXYZ.x, worldXYZ.z);

            var lod        = Generator.Lod;
            var tileLength = Generator.Length;
            var lvlType    = lod.GetLevelTypeForRadius((int)position.Distance(new GridPosition(worldXZ, tileLength)));

            switch (lvlType)
            {
            case LodData.LodLevelType.High:
                return(Color.green);

            case LodData.LodLevelType.Medium:
                return(Color.yellow);

            case LodData.LodLevelType.Low:
                return(Color.red);
            }

            return(Color.white);
        }
示例#3
0
    protected virtual void Update()
    {
        if (_endTurn)
        {
            _endTurn = false;
            BlockUI  = true;
            StartCoroutine(FinishTurn());
        }

        foreach (var livingEntity in Entities.OfType <LivingEntity>())
        {
            if (_selectedEntity == null ||
                livingEntity.Side == PlayerSide ||
                BlockUI)
            {
                livingEntity.UI.EnableTargetMarker(false);
                livingEntity.UI.EnableBoardMarker(false);
            }
            else
            {
                var range = GridPosition.Distance(_selectedEntity.Position, livingEntity.Position);
                livingEntity.UI.EnableTargetMarker(_selectedEntity.CanAttack && range <= _selectedEntity.Weapon.Range);
                livingEntity.UI.EnableBoardMarker(_selectedEntity.CanBoard && range == 1);
            }
        }

        if (_selectedEntity != null && _selectedEntity.CanMove && !BlockUI)
        {
            var obstacles = new HashSet <GridPosition>(Entities
                                                       .Where(entity => entity.IsObstacle(PlayerSide))
                                                       .Select(entity => entity.Position));
            var entities     = new HashSet <GridPosition>(Entities.Select(entity => entity.Position));
            var destinations = _astar.GetDestinations(_selectedEntity.Position, obstacles, entities, _selectedEntity.MovementRange);

            var markers = new Queue <GameObject>(_destinationMarkers);
            _destinationMarkers.Clear();

            foreach (var destination in destinations)
            {
                var marker = markers.Any() ? markers.Dequeue() : Instantiate(DestinationMarkerPrefab);
                if (marker != null)
                {
                    marker.transform.position = GridPosition.ToVector3(destination);
                    marker.transform.SetParent(transform);
                    _destinationMarkers.Add(marker);
                }
            }
            while (markers.Any())
            {
                Destroy(markers.Dequeue());
            }
        }
        else
        {
            foreach (var destinationMarker in _destinationMarkers)
            {
                Destroy(destinationMarker);
            }
        }
    }
示例#4
0
 // Token: 0x06003788 RID: 14216 RVA: 0x000F9B94 File Offset: 0x000F7D94
 public void Start(BattleActor actor0, BattleActor actor1, ConfigDataSkillInfo heroSkillInfo0, ConfigDataSkillInfo heroSkillInfo1, int randomSeed)
 {
     if (!BJLuaObjHelper.IsSkipLuaHotfix && this.TryInitHotFix("") && this.m_StartBattleActorBattleActorConfigDataSkillInfoConfigDataSkillInfoInt32_hotfix != null)
     {
         this.m_StartBattleActorBattleActorConfigDataSkillInfoConfigDataSkillInfoInt32_hotfix.call(new object[]
         {
             this,
             actor0,
             actor1,
             heroSkillInfo0,
             heroSkillInfo1,
             randomSeed
         });
         return;
     }
     BJLuaObjHelper.IsSkipLuaHotfix = false;
     this.Clear();
     this.m_randomNumber.SetSeed(randomSeed);
     this.m_startCountdown     = Combat.MillisecondToFrame1(this.ConfigDataLoader.UtilityGetConfigableConst(ConfigableConstId.ConfigableConstId_Combat_StartDelay) + 250) + 1;
     this.m_state              = CombatState.Ready;
     this.m_isPaused           = false;
     this.m_combatGridDistance = GridPosition.Distance(actor0.Position, actor1.Position);
     this.SetupTeam(0, actor0, heroSkillInfo0);
     this.SetupTeam(1, actor1, heroSkillInfo1);
     foreach (CombatTeam combatTeam in this.m_teams)
     {
         combatTeam.EnterCombat();
     }
 }
示例#5
0
 // Token: 0x06003A34 RID: 14900 RVA: 0x00109EA8 File Offset: 0x001080A8
 public int GetGoalHeuristic(Pathfinder pathfinder)
 {
     if (!BJLuaObjHelper.IsSkipLuaHotfix && this.TryInitHotFix("") && this.m_GetGoalHeuristicPathfinder_hotfix != null)
     {
         return(Convert.ToInt32(this.m_GetGoalHeuristicPathfinder_hotfix.call(new object[]
         {
             this,
             pathfinder
         })));
     }
     BJLuaObjHelper.IsSkipLuaHotfix = false;
     return(GridPosition.Distance(pathfinder.GoalNode.m_position, this.m_position));
 }
示例#6
0
    private static LivingEntity GetNearestEnemy(Entity self, IEnumerable <LivingEntity> enemies)
    {
        int          minDistance = int.MaxValue;
        LivingEntity closest     = null;

        foreach (var enemy in enemies)
        {
            var distance = GridPosition.Distance(self.Position, enemy.Position);
            if (distance < minDistance)
            {
                minDistance = distance;
                closest     = enemy;
            }
        }

        return(closest);
    }
        /// <summary>
        /// Gets the LOD level for this tile based off of its <see cref="GridPosition"/>'s
        /// distance from the tracked object. If no tracked object is specified, the level
        /// is determined by the <see cref="GridPosition"/>'s distance from [0, 0]. The returned
        /// LOD level may not be equal to this Tile's <see cref="LodLevel"/> as it could have changed
        /// since initialization.
        /// </summary>
        /// <returns>LOD level</returns>
        private LodData.LodLevel GetLodLevel()           //todo change to reflect description
        {
            GameObject tracked = Config.Generator.TrackedObject;

            if (tracked == null)
            {
                int radius = (int)GridPosition.Distance(new GridPosition(0, 0));
                return(Config.Generator.Lod.GetLevelForRadius(radius));
            }
            else
            {
                float        length  = Config.Generator.Length;
                Vector2      worldXZ = new Vector2(tracked.transform.position.x, tracked.transform.position.z);
                GridPosition gp      = new GridPosition(worldXZ, length);

                int radius = (int)gp.Distance(GridPosition);
                return(Config.Generator.Lod.GetLevelForRadius(radius));
            }
        }
示例#8
0
    public void Interact(GridPosition gridPosition)
    {
        if (_selectedEntity == null)
        {
            return;
        }

        var clickedEntity = Entities.FirstOrDefault(entity => entity.Position == gridPosition);

        if (clickedEntity == null)
        {
            if (_selectedEntity.CanMove)
            {
                var obstacles = Entities
                                .Where(entity => entity.IsObstacle(PlayerSide))
                                .Select(entity => entity.Position)
                                .ToList();
                var path = _astar.Calculate(_selectedEntity.Position, gridPosition, obstacles);

                if (path != null && path.Count <= _selectedEntity.MovementRange + 1)
                {
                    BlockUI = true;
                    StartCoroutine(Move(_selectedEntity, path));
                }
            }
        }
        else
        {
            if (_selectedEntity.CanAttack)
            {
                var target = clickedEntity as LivingEntity;
                if (target != null && target.Side != PlayerSide)
                {
                    var range = GridPosition.Distance(_selectedEntity.Position, target.Position);
                    if (range <= _selectedEntity.Weapon.Range)
                    {
                        BlockUI = true;
                        StartCoroutine(Attack(_selectedEntity, target));
                    }
                }
            }
        }
    }
    public IEnumerator Attack(LivingEntity target, float salvoFlightTime)
    {
        var range = GridPosition.Distance(Position, target.Position);

        if (!CanAttack)
        {
            throw new InvalidOperationException($"The entity '{this}' cannot attack.");
        }
        if (range > Weapon.Range)
        {
            throw new InvalidOperationException($"The target '{target}' is out of range.");
        }

        CanAttack = false;
        UI.EnableCanFireMarker(CanAttack);

        if (target.Weapon != null &&
            range <= target.Weapon.Range &&
            Random.Range(0, 10) >= 7)
        {
            yield return(FireSalvo(target, this, salvoFlightTime));

            if (IsAlive)
            {
                yield return(FireSalvo(this, target, salvoFlightTime));
            }
        }
        else
        {
            yield return(FireSalvo(this, target, salvoFlightTime));

            if (target.IsAlive &&
                target.Weapon != null &&
                range <= target.Weapon.Range)
            {
                yield return(FireSalvo(target, this, salvoFlightTime));
            }
        }
    }
示例#10
0
    public void FindAStarPathBetween(Vector3 startPosition, Vector3 endPosition)       //has to be seperate!!
    {
        if (GridMap.isBusy)
        {
            Debug.Log("isbusy"); return;
        }
        GridMap.isBusy = true;

        var currentTime = DateTime.Now;

        //ScanGridMap(); need a better solution!

        GridPosition start = GetGridPosition(startPosition);
        GridPosition end   = GetGridPosition(endPosition);

        Dictionary <GridPosition, Node> closedNodes = new Dictionary <GridPosition, Node>();
        Dictionary <GridPosition, Node> openNodes   = new Dictionary <GridPosition, Node>();
        Dictionary <GridPosition, Node> allNodes    = new Dictionary <GridPosition, Node>();

        Node startNode = new Node();

        startNode.Fcost = end.Distance(start);

        startNode.Gcost = 0f;

        allNodes.Add(start, startNode);
        openNodes.Add(start, startNode);


        while (openNodes.Count > 0)
        {
            if ((DateTime.Now - currentTime).Milliseconds > maxPathFindTime)
            {
                break;
            }

            KeyValuePair <GridPosition, Node> best = openNodes.Aggregate((a, b) => a.Value.Fcost < b.Value.Fcost ? a : b); //find cheapest node
            openNodes.Remove(best.Key);
            closedNodes.Add(best.Key, best.Value);                                                                         //add node to move to to closed list

            //AssertIfEndGridIsFoundAndBackTrack!!
            if (best.Key.Equals(end))
            {
                Debug.Log("found end!");
                List <Vector3> path     = new List <Vector3>();
                Node           bestNode = best.Value;

                path.Add(endPosition);

                //backtrack!
                while (bestNode != null && !bestNode.parentGridPosition.Equals(GridPosition.Zero))
                {
                    path.Insert(0, GetWorldPosition(bestNode.parentGridPosition));
                    bestNode = allNodes[bestNode.parentGridPosition];

                    if (drawOverlay)
                    {
                        GameObject gcOverlay = (GameObject)GameObject.Instantiate(gridCellOverlay, GetWorldPosition(bestNode.parentGridPosition), Quaternion.identity);
                        gcOverlay.GetComponentInChildren <SpriteRenderer>().color = Color.red;
                        gcOverlay.transform.parent = GameObject.Find("Paths").transform;
                        overlay.Add(gcOverlay);
                    }
                }
                Debug.Log("took : " + (DateTime.Now - currentTime).Milliseconds + "ms to generate a path!");
                DispatchMessage("OnPathFound", path);

                GridMap.isBusy = false;
            }

            //LoopThroughWalkablewNeighBours
            foreach (GridPosition gridPosition in GetNeighbours(best.Key).Where(gc => GetCell(gc).walkable))
            {
                Node alreadyExistingNode;
                if (closedNodes.TryGetValue(gridPosition, out alreadyExistingNode))
                {
                    continue;
                }

                float tenativeGcost = best.Value.Gcost + 1;

                Node currentNode;
                if (!openNodes.TryGetValue(gridPosition, out currentNode))                  //AddNodeToOpenAndAllIfNotAlreadyAdded
                {
                    currentNode = new Node();
                    allNodes.Add(gridPosition, currentNode);
                    openNodes.Add(gridPosition, currentNode);
                }

                if (tenativeGcost < currentNode.Gcost)                  //AssertIfNodeGCostIsLowerThanTenativeGCost
                {
                    currentNode.Gcost = tenativeGcost;
                    currentNode.parentGridPosition = best.Key;
                    currentNode.Fcost = tenativeGcost + gridPosition.Distance(end);
                }
            }
        }
        GridMap.isBusy = false;
    }
示例#11
0
 private static float GetCost(GridPosition start, GridPosition goal)
 {
     return(GridPosition.Distance(start, goal));
 }
示例#12
0
 private static float HeuristicCostEstimate([NotNull] Node start, [NotNull] Node goal)
 {
     return(GridPosition.Distance(start.Position, goal.Position));
 }
示例#13
0
    protected override void Execute(List <InputEntity> entities)
    {
        if (!_contexts.input.isPointerHolding)
        {
            return;
        }

        var position = _contexts.input.pointerHoldingPosition.value.ToGridPosition();

        var horizontalBounded = position.x >= 0 && position.x < _contexts.config.mapSize.value.x;
        var verticalBounded   = position.y >= 0 && position.y < _contexts.config.mapSize.value.y;

        if (horizontalBounded && verticalBounded)
        {
            var entityUnderPointer = _contexts.game.GetEntityWithPosition(position);

            if (entityUnderPointer == null)
            {
                return;
            }

            if (entityUnderPointer.isBlock)
            {
                return;
            }

            if (entityUnderPointer.isSelected)
            {
                return;
            }

            var lastSelectedId = _contexts.gameState.lastSelected.value;
            if (lastSelectedId == -1)
            {
                entityUnderPointer.isSelected = true;
                entityUnderPointer.ReplaceSelectionId(0);

                _contexts.gameState.ReplaceLastSelected(entityUnderPointer.id.value);
                _contexts.gameState.ReplaceMaxSelectedElement(0);
            }
            else
            {
                var lastSelected = _contexts.game.GetEntityWithId(lastSelectedId);
                if (lastSelected.hasElementType && entityUnderPointer.hasElementType)
                {
                    if (lastSelected.elementType.value == entityUnderPointer.elementType.value)
                    {
                        if (GridPosition.Distance(lastSelected.position.value, entityUnderPointer.position.value) <
                            1.25f)
                        {
                            var selectionId = _contexts.gameState.maxSelectedElement.value;
                            selectionId++;

                            entityUnderPointer.isSelected = true;
                            entityUnderPointer.ReplaceSelectionId(selectionId);

                            _contexts.gameState.ReplaceLastSelected(entityUnderPointer.id.value);
                            _contexts.gameState.ReplaceMaxSelectedElement(selectionId);
                        }
                    }
                }
            }
        }
    }
示例#14
0
    public IEnumerator CalculateTurn(List <Entity> entities, Astar astar, Side side, float movementSpeed, float salvoFlightTime)
    {
        var ownEntities = entities.OfType <LivingEntity>().Where(entity => entity.Side == side).ToList();
        var enemyShips  = entities.OfType <LivingEntity>().Where(entity => entity.Side != side).ToList();

        foreach (var own in ownEntities)
        {
            if (!own.CanAttack)
            {
                continue;
            }

            var  blackList = new List <LivingEntity>();
            bool selectNewEnemy;
            do
            {
                selectNewEnemy = false;
                var enemy = GetNearestEnemy(own, enemyShips.Except(blackList));

                if (GridPosition.Distance(own.Position, enemy.Position) <= own.Weapon.Range)
                {
                    yield return(own.Attack(enemy, salvoFlightTime));
                }
                else
                {
                    var obstacles = entities
                                    .Except(ownEntities)
                                    .Where(entity => entity != enemy)
                                    .Select(entity => entity.Position)
                                    .ToList();

                    var destinations = GetDestinations(enemy.Position, own.Weapon.Range)
                                       .Except(entities.Select(entity => entity.Position))
                                       .Distinct();

                    IList <GridPosition> shortestPath = null;
                    foreach (var destination in destinations)
                    {
                        var path = astar.Calculate(own.Position, destination, obstacles);
                        if (shortestPath == null || path.Count < shortestPath.Count)
                        {
                            shortestPath = path;
                        }
                    }

                    if (shortestPath != null)
                    {
                        var path = shortestPath.Count > own.MovementRange + 2
                            ? shortestPath.Take(own.MovementRange + 1).ToList()
                            : shortestPath;
                        yield return(own.Move(path, movementSpeed));

                        if (GridPosition.Distance(own.Position, enemy.Position) <= own.Weapon.Range)
                        {
                            yield return(own.Attack(enemy, salvoFlightTime));
                        }
                    }
                    else
                    {
                        blackList.Add(enemy);
                        selectNewEnemy = true;
                    }
                }
            } while (selectNewEnemy && blackList.Count < enemyShips.Count);
        }
    }