Example #1
0
        private void CreateChests(Room[] rooms)
        {
            var defaultDropTable  = _schemeService.GetScheme <DropTableScheme>("default");
            var survivalDropTable = _schemeService.GetScheme <DropTableScheme>("survival");

            foreach (var room in rooms)
            {
                var absNodeIndex  = room.Nodes.Count();
                var containerNode = room.Nodes[absNodeIndex / 2];
                var container     = new DropTablePropChest(containerNode,
                                                           new[] { defaultDropTable, survivalDropTable },
                                                           _dropResolver);
                _propContainerManager.Add(container);
            }
        }
        /// <summary>
        /// Создать сундуки в секторе.
        /// </summary>
        /// <param name="map">Карта сектора. Нужна для определения доступного места для сундука.</param>
        /// <param name="sectorSubScheme">Схема сектора. По сути - настройки для размещения сундуков.</param>
        /// <param name="regions">Регионы, в которых возможно размещение сундуков.</param>
        public void CreateChests(ISectorMap map, ISectorSubScheme sectorSubScheme, IEnumerable <MapRegion> regions)
        {
            var dropTables   = GetDropTables(sectorSubScheme);
            var chestCounter = sectorSubScheme.TotalChestCount;

            //TODO В схемах хранить уже приведённое значение пропорции.
            var countChestRatioNormal = 1f / sectorSubScheme.RegionChestCountRatio;

            foreach (var region in regions)
            {
                var maxChestCountRaw = region.Nodes.Count() * countChestRatioNormal;
                var maxChestCount    = (int)Math.Max(maxChestCountRaw, 1);
                var rolledCount      = _chestGeneratorRandomSource.RollChestCount(maxChestCount);

                var availableNodes = from node in region.Nodes
                                     where !map.Transitions.Keys.Contains(node)
                                     select node;
                var openNodes = new List <IMapNode>(availableNodes);
                for (var i = 0; i < rolledCount; i++)
                {
                    // Выбрать из коллекции доступных узлов
                    var rollIndex     = _chestGeneratorRandomSource.RollNodeIndex(openNodes.Count);
                    var containerNode = MapRegionHelper.FindNonBlockedNode(openNodes[rollIndex], map, openNodes);
                    if (containerNode == null)
                    {
                        // в этом случае будет сгенерировано на один сундук меньше.
                        // узел, с которого не удаётся найти подходящий узел, удаляем,
                        // чтобы больше его не анализировать, т.к. всё равно будет такой же исход.
                        openNodes.Remove(openNodes[rollIndex]);
                        continue;
                    }

                    openNodes.Remove(containerNode);
                    var container = new DropTablePropChest(containerNode,
                                                           dropTables,
                                                           _dropResolver);
                    _propContainerManager.Add(container);

                    chestCounter--;

                    if (chestCounter <= 0)
                    {
                        // лимит сундуков в секторе исчерпан.
                        break;
                    }
                }
            }
        }
Example #3
0
        private void ActorState_Dead(object sender, EventArgs e)
        {
            var actor = _actorManager.Items.Single(x => x.State == sender);

            Map.ReleaseNode(actor.Node, actor);
            _actorManager.Remove(actor);
            actor.State.Dead -= ActorState_Dead;

            if (actor.Person is MonsterPerson monsterPerson)
            {
                var monsterScheme = monsterPerson.Scheme;

                var dropSchemes = GetMonsterDropTables(monsterScheme);

                var loot = new DropTableLoot(actor.Node, dropSchemes, _dropResolver);

                if (loot.Content.CalcActualItems().Any())
                {
                    _propContainerManager.Add(loot);
                }
            }
        }
Example #4
0
        private void ProcessMonsterDeath(IActor actor)
        {
            if (!(actor.Person is MonsterPerson monsterPerson))
            {
                return;
            }

            var monsterScheme = monsterPerson.Scheme;

            var dropSchemes = GetMonsterDropTables(monsterScheme);

            var loot = new DropTableLoot(actor.Node, dropSchemes, _dropResolver);

            if (loot.Content.CalcActualItems().Any())
            {
                _propContainerManager.Add(loot);
            }

            if (ScoreManager != null)
            {
                ScoreManager.CountMonsterDefeat(monsterPerson);
            }
        }
Example #5
0
        /// <summary>
        /// Создать сундуки в секторе.
        /// </summary>
        /// <param name="map">Карта сектора. Нужна для определения доступного места для сундука.</param>
        /// <param name="sectorSubScheme">Схема сектора. По сути - настройки для размещения сундуков.</param>
        /// <param name="regions">Регионы, в которых возможно размещение сундуков.</param>
        public void CreateChests(ISectorMap map, ISectorSubScheme sectorSubScheme, IEnumerable <MapRegion> regions)
        {
            var trashDropTables    = GetTrashDropTables(sectorSubScheme);
            var treasuresDropTable = GetTreasuresDropTable();
            var chestCounter       = sectorSubScheme.TotalChestCount;

            //TODO В схемах хранить уже приведённое значение пропорции.
            var countChestRatioNormal = 1f / sectorSubScheme.RegionChestCountRatio;

            foreach (var region in regions)
            {
                var maxChestCountRaw = region.Nodes.Count() * countChestRatioNormal;
                var maxChestCount    = (int)Math.Max(maxChestCountRaw, 1);

                if (region.Nodes.Count() <= 1)
                {
                    // Для регионов, где только один узел,
                    // не создаём сундуки, иначе проход может быть загорожен.
                    // Актуально для фабрики карт на основе клеточного автомата,
                    // потому что он может генерить регионы из одного узла.

                    //TODO Попробовать проверять соседей узла.
                    // Возможно, одноклеточный регион находится в конце тупика.
                    // Тогда в нём можно разместить сундук.
                    // Критерий доступности такого региона - у узла только одни сосед.
                    continue;
                }

                var rolledCount = _chestGeneratorRandomSource.RollChestCount(maxChestCount);

                var availableNodes = from node in region.Nodes
                                     where !map.Transitions.Keys.Contains(node)
                                     where map.IsPositionAvailableForContainer(node)
                                     select node;

                var openNodes = new List <IMapNode>(availableNodes);
                for (var i = 0; i < rolledCount; i++)
                {
                    var containerPurpose = _chestGeneratorRandomSource.RollPurpose();

                    // Выбрать из коллекции доступных узлов
                    var rollIndex     = _chestGeneratorRandomSource.RollNodeIndex(openNodes.Count);
                    var containerNode = MapRegionHelper.FindNonBlockedNode(openNodes[rollIndex], map, openNodes);
                    if (containerNode == null)
                    {
                        // в этом случае будет сгенерировано на один сундук меньше.
                        // узел, с которого не удаётся найти подходящий узел, удаляем,
                        // чтобы больше его не анализировать, т.к. всё равно будет такой же исход.
                        openNodes.Remove(openNodes[rollIndex]);
                        continue;
                    }

                    // Проверка, что сундук не перегораживает проход.
                    var isValid = CheckMap(map, (HexNode)containerNode);
                    if (!isValid)
                    {
                        // в этом случае будет сгенерировано на один сундук меньше.
                        // узел, с которого не удаётся найти подходящий узел, удаляем,
                        // чтобы больше его не анализировать, т.к. всё равно будет такой же исход.
                        openNodes.Remove(openNodes[rollIndex]);
                        continue;
                    }

                    openNodes.Remove(containerNode);

                    IPropContainer container;
                    switch (containerPurpose)
                    {
                    case PropContainerPurpose.Trash:
                        container = new DropTablePropChest(containerNode, trashDropTables, _dropResolver)
                        {
                            Purpose = PropContainerPurpose.Trash
                        };
                        break;

                    case PropContainerPurpose.Treasures:
                        container = new DropTablePropChest(containerNode, treasuresDropTable, _dropResolver)
                        {
                            Purpose = PropContainerPurpose.Treasures
                        };
                        break;

                    default:
                        throw new InvalidOperationException($"Не корректное назначение {containerPurpose}.");
                    }
                    _propContainerManager.Add(container);

                    chestCounter--;

                    if (chestCounter <= 0)
                    {
                        // лимит сундуков в секторе исчерпан.
                        break;
                    }
                }
            }
        }