Exemple #1
0
        /**
         * Displays the danger map on the "DangerMap" TileMap. Sums the probable (get to that in a moment) damage the player would
         * take from being on the given square on their next turn.
         *
         * "Danger" is kind of tricky, because the possible danger can be influenced by enemy movement. For example, a railgun shot
         * can be intercepted by a scout, rendering all tiles in its path 'safe', but we have no idea if the scout will or won't move
         * onto that square. Our current rule is "You can never get hit on a safe square, but can sometimes avoid getting hit on a
         * dangerous square." So, we stop a projectile path if it would hit a satellite, but don't stop if it would hit a cruiser,
         * even if the cruiser wouldn't have time to move, because it might be destroyed by another projectile and then let the
         * projectile pass.
         *
         * While you could theoretically simulate to the maximum possible fidelity, such that you don't paint it if the cruiser has
         * HP than it could possibly take in a round and do if it doesn't, that doesn't seem worth it.
         */
        public void UpdateAllTiles(EncounterState state)
        {
            var pathEntities               = GetTree().GetNodesInGroup(PathAIComponent.ENTITY_GROUP);
            var timeToNextPlayerMove       = state.Player.GetComponent <SpeedComponent>().Speed;
            var positionsToPotentialDamage = new Dictionary <EncounterPosition, int>();

            // Fill the TileMap as appropriate & tally positionsToPotentialDamage
            this.Clear();
            // TODO: We don't actually need to update every entity, every time, since we only need to set the cell when the projectile itself moves
            foreach (Entity pathEntity in pathEntities)
            {
                int attackerPower   = GetAttackerPower(pathEntity);
                var dangerPositions = CalcDangerPositions(pathEntity, timeToNextPlayerMove);

                RotateSpriteTowardsDestination(pathEntity, dangerPositions);
                foreach (EncounterPosition dangerPosition in dangerPositions.Where(p => state.FoVCache.IsVisible(p)))
                {
                    // If we have a fully immobile, invincible entity at the position we stop the path - otherwise we still draw it.
                    var blockingEntity = state.BlockingEntityAtPosition(dangerPosition.X, dangerPosition.Y);
                    if (blockingEntity != null &&
                        blockingEntity.GetComponent <ActionTimeComponent>() == null &&
                        blockingEntity.GetComponent <DefenderComponent>() != null &&
                        blockingEntity.GetComponent <DefenderComponent>().IsInvincible)
                    {
                        break;
                    }

                    if (positionsToPotentialDamage.ContainsKey(dangerPosition))
                    {
                        positionsToPotentialDamage[dangerPosition] += attackerPower;
                    }
                    else
                    {
                        positionsToPotentialDamage[dangerPosition] = attackerPower;
                    }
                    this.SetCell(dangerPosition.X, dangerPosition.Y, 0);
                }
            }

            // Draw the damage numbers
            // If all this creation/deletion is a significant source of slowdown you can make an object pool, max size FoW area tiles
            foreach (var damageLabel in this._damageLabels)
            {
                this.RemoveChild(damageLabel);
                damageLabel.QueueFree();
            }
            _damageLabels.Clear();
            foreach (var pair in positionsToPotentialDamage)
            {
                var label = CreateLabel(pair.Value, pair.Key);
                this._damageLabels.Add(label);
                this.AddChild(label);
            }

            this.HighlightEnemies(state, timeToNextPlayerMove);
        }