Exemple #1
0
        private void LoadItem(XElement element, Item parent)
        {
            var     itemPrefab = FindItemPrefab(element);
            Vector2?position   = GetCargoSpawnPosition(itemPrefab, out Submarine cargoRoomSub);

            if (!position.HasValue)
            {
                return;
            }
            var item = new Item(itemPrefab, position.Value, cargoRoomSub);

            item.FindHull();
            startingItems.Add(item);
            if (parent?.GetComponent <ItemContainer>() is ItemContainer itemContainer)
            {
                parentInventoryIDs.Add(item, parent.ID);
                parentItemContainerIndices.Add(item, (byte)parent.GetComponentIndex(itemContainer));
                parent.Combine(item, user: null);
            }
            foreach (XElement subElement in element.Elements())
            {
                int amount = subElement.GetAttributeInt("amount", 1);
                for (int i = 0; i < amount; i++)
                {
                    LoadItem(subElement, item);
                }
            }
        }
        private void LoadItemAsChild(XElement element, Item parent)
        {
            string itemName = element.GetAttributeString("name", "");

            ItemPrefab itemPrefab = MapEntityPrefab.Find(itemName) as ItemPrefab;

            if (itemPrefab == null)
            {
                DebugConsole.ThrowError("Couldn't spawn item for cargo mission: item prefab \"" + element.Name.ToString() + "\" not found");
                return;
            }

            WayPoint cargoSpawnPos = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub, true);

            if (cargoSpawnPos == null)
            {
                DebugConsole.ThrowError("Couldn't spawn items for cargo mission, cargo spawnpoint not found");
                return;
            }

            var cargoRoom = cargoSpawnPos.CurrentHull;

            if (cargoRoom == null)
            {
                DebugConsole.ThrowError("A waypoint marked as Cargo must be placed inside a room!");
                return;
            }

            Vector2 position = new Vector2(
                cargoSpawnPos.Position.X + Rand.Range(-20.0f, 20.0f, Rand.RandSync.Server),
                cargoRoom.Rect.Y - cargoRoom.Rect.Height + itemPrefab.Size.Y / 2);

            var item = new Item(itemPrefab, position, cargoRoom.Submarine);

            item.FindHull();


            items.Add(item);

            if (parent != null)
            {
                parent.Combine(item);
            }

            foreach (XElement subElement in element.Elements())
            {
                int amount = subElement.GetAttributeInt("amount", 1);
                for (int i = 0; i < amount; i++)
                {
                    LoadItemAsChild(subElement, item);
                }
            }
        }
Exemple #3
0
        protected override void StartMissionSpecific(Level level)
        {
            if (items.Any())
            {
#if DEBUG
                throw new Exception($"items.Count > 0 ({items.Count})");
#else
                DebugConsole.AddWarning("Item list was not empty at the start of a nest mission. The mission instance may not have been ended correctly on previous rounds.");
                items.Clear();
#endif
            }

            if (!IsClient)
            {
                //ruin/cave/wreck items are allowed to spawn close to the sub
                float minDistance = spawnPositionType == Level.PositionType.Ruin || spawnPositionType == Level.PositionType.Cave || spawnPositionType == Level.PositionType.Wreck ?
                                    0.0f : Level.Loaded.Size.X * 0.3f;

                nestPosition = Level.Loaded.GetRandomItemPos(spawnPositionType, 100.0f, minDistance, 30.0f);
                List <GraphEdge> spawnEdges = new List <GraphEdge>();
                if (spawnPositionType == Level.PositionType.Cave)
                {
                    Level.Cave closestCave     = null;
                    float      closestCaveDist = float.PositiveInfinity;
                    foreach (var cave in Level.Loaded.Caves)
                    {
                        float dist = Vector2.DistanceSquared(nestPosition, cave.Area.Center.ToVector2());
                        if (dist < closestCaveDist)
                        {
                            closestCave     = cave;
                            closestCaveDist = dist;
                        }
                    }
                    if (closestCave != null)
                    {
                        closestCave.DisplayOnSonar = true;
                        SpawnNestObjects(level, closestCave);
#if SERVER
                        selectedCave = closestCave;
#endif
                    }
                    var nearbyCells = Level.Loaded.GetCells(nestPosition, searchDepth: 3);
                    if (nearbyCells.Any())
                    {
                        List <GraphEdge> validEdges = new List <GraphEdge>();
                        foreach (var edge in nearbyCells.SelectMany(c => c.Edges))
                        {
                            if (!edge.NextToCave || !edge.IsSolid)
                            {
                                continue;
                            }
                            if (Level.Loaded.ExtraWalls.Any(w => w.IsPointInside(edge.Center + edge.GetNormal(edge.Cell1 ?? edge.Cell2) * 100.0f)))
                            {
                                continue;
                            }
                            validEdges.Add(edge);
                        }

                        if (validEdges.Any())
                        {
                            spawnEdges.AddRange(validEdges.Where(e => MathUtils.LineSegmentToPointDistanceSquared(e.Point1.ToPoint(), e.Point2.ToPoint(), nestPosition.ToPoint()) < itemSpawnRadius * itemSpawnRadius).Distinct());
                        }
                        //no valid edges found close enough to the nest position, find the closest one
                        if (!spawnEdges.Any())
                        {
                            GraphEdge closestEdge    = null;
                            float     closestDistSqr = float.PositiveInfinity;
                            foreach (var edge in nearbyCells.SelectMany(c => c.Edges))
                            {
                                if (!edge.NextToCave || !edge.IsSolid)
                                {
                                    continue;
                                }
                                float dist = Vector2.DistanceSquared(edge.Center, nestPosition);
                                if (dist < closestDistSqr)
                                {
                                    closestEdge    = edge;
                                    closestDistSqr = dist;
                                }
                            }
                            if (closestEdge != null)
                            {
                                spawnEdges.Add(closestEdge);
                                itemSpawnRadius = Math.Max(itemSpawnRadius, (float)Math.Sqrt(closestDistSqr) * 1.5f);
                            }
                        }
                    }
                }

                foreach (XElement subElement in itemConfig.Elements())
                {
                    string itemIdentifier = subElement.GetAttributeString("identifier", "");
                    if (!(MapEntityPrefab.Find(null, itemIdentifier) is ItemPrefab itemPrefab))
                    {
                        DebugConsole.ThrowError("Couldn't spawn item for nest mission: item prefab \"" + itemIdentifier + "\" not found");
                        continue;
                    }

                    Vector2 spawnPos = nestPosition;
                    float   rotation = 0.0f;
                    if (spawnEdges.Any())
                    {
                        var edge = spawnEdges.GetRandom(Rand.RandSync.Server);
                        spawnPos = Vector2.Lerp(edge.Point1, edge.Point2, Rand.Range(0.1f, 0.9f, Rand.RandSync.Server));
                        Vector2 normal = Vector2.UnitY;
                        if (edge.Cell1 != null && edge.Cell1.CellType == CellType.Solid)
                        {
                            normal = edge.GetNormal(edge.Cell1);
                        }
                        else if (edge.Cell2 != null && edge.Cell2.CellType == CellType.Solid)
                        {
                            normal = edge.GetNormal(edge.Cell2);
                        }
                        spawnPos += normal * 10.0f;
                        rotation  = MathUtils.VectorToAngle(normal) - MathHelper.PiOver2;
                    }

                    var item = new Item(itemPrefab, spawnPos, null);
                    item.body.FarseerBody.BodyType = BodyType.Kinematic;
                    item.body.SetTransformIgnoreContacts(item.body.SimPosition, rotation);
                    item.FindHull();
                    items.Add(item);

                    var statusEffectElement = subElement.Element("StatusEffectOnApproach") ?? subElement.Element("statuseffectonapproach");
                    if (statusEffectElement != null)
                    {
                        statusEffectOnApproach.Add(item, StatusEffect.Load(statusEffectElement, Prefab.Identifier));
                    }
                }
            }
        }
Exemple #4
0
        public override void UpdatePlacing(Camera cam)
        {
            Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);

            if (PlayerInput.RightButtonClicked())
            {
                selected = null;
                return;
            }

            if (!ResizeHorizontal && !ResizeVertical)
            {
                if (PlayerInput.LeftButtonClicked())
                {
                    var item = new Item(new Rectangle((int)position.X, (int)position.Y, (int)sprite.size.X, (int)sprite.size.Y), this, Submarine.MainSub);
                    //constructor.Invoke(lobject);
                    item.Submarine = Submarine.MainSub;
                    item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
                    item.FindHull();

                    placePosition = Vector2.Zero;

                    // selected = null;
                    return;
                }
            }
            else
            {
                Vector2 placeSize = size;

                if (placePosition == Vector2.Zero)
                {
                    if (PlayerInput.LeftButtonHeld())
                    {
                        placePosition = position;
                    }
                }
                else
                {
                    if (ResizeHorizontal)
                    {
                        placeSize.X = Math.Max(position.X - placePosition.X, size.X);
                    }
                    if (ResizeVertical)
                    {
                        placeSize.Y = Math.Max(placePosition.Y - position.Y, size.Y);
                    }

                    if (PlayerInput.LeftButtonReleased())
                    {
                        var item = new Item(new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y), this, Submarine.MainSub);
                        placePosition = Vector2.Zero;

                        item.Submarine = Submarine.MainSub;
                        item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
                        item.FindHull();

                        //selected = null;
                        return;
                    }

                    position = placePosition;
                }
            }

            //if (PlayerInput.GetMouseState.RightButton == ButtonState.Pressed) selected = null;
        }
Exemple #5
0
        public override void UpdatePlacing(Camera cam)
        {
            Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);

            if (PlayerInput.SecondaryMouseButtonClicked())
            {
                selected = null;
                return;
            }

            var potentialContainer = MapEntity.GetPotentialContainer(position);

            if (!ResizeHorizontal && !ResizeVertical)
            {
                if (PlayerInput.PrimaryMouseButtonClicked())
                {
                    var item = new Item(new Rectangle((int)position.X, (int)position.Y, (int)(sprite.size.X * Scale), (int)(sprite.size.Y * Scale)), this, Submarine.MainSub)
                    {
                        Submarine = Submarine.MainSub
                    };
                    item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
                    item.FindHull();
                    item.Submarine = Submarine.MainSub;

                    if (PlayerInput.IsShiftDown())
                    {
                        if (potentialContainer?.OwnInventory?.TryPutItem(item, Character.Controlled) ?? false)
                        {
                            SoundPlayer.PlayUISound(GUISoundType.PickItem);
                        }
                    }

                    SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List <MapEntity> {
                        item
                    }, false));

                    placePosition = Vector2.Zero;
                    return;
                }
            }
            else
            {
                Vector2 placeSize = size * Scale;

                if (placePosition == Vector2.Zero)
                {
                    if (PlayerInput.PrimaryMouseButtonHeld())
                    {
                        placePosition = position;
                    }
                }
                else
                {
                    if (ResizeHorizontal)
                    {
                        placeSize.X = Math.Max(position.X - placePosition.X, size.X);
                    }
                    if (ResizeVertical)
                    {
                        placeSize.Y = Math.Max(placePosition.Y - position.Y, size.Y);
                    }

                    if (PlayerInput.PrimaryMouseButtonReleased())
                    {
                        var item = new Item(new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y), this, Submarine.MainSub);
                        placePosition = Vector2.Zero;

                        item.Submarine = Submarine.MainSub;
                        item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
                        item.FindHull();

                        //selected = null;
                        return;
                    }

                    position = placePosition;
                }
            }

            if (potentialContainer != null)
            {
                potentialContainer.IsHighlighted = true;
            }


            //if (PlayerInput.GetMouseState.RightButton == ButtonState.Pressed) selected = null;
        }
        public override void Start(Level level)
        {
#if SERVER
            originalInventoryID = Entity.NullEntityID;
#endif
            item = null;
            if (!IsClient)
            {
                //ruin/wreck items are allowed to spawn close to the sub
                float minDistance = spawnPositionType == Level.PositionType.Ruin || spawnPositionType == Level.PositionType.Wreck ?
                                    0.0f : Level.Loaded.Size.X * 0.3f;
                Vector2 position = Level.Loaded.GetRandomItemPos(spawnPositionType, 100.0f, minDistance, 30.0f);

                if (!string.IsNullOrEmpty(existingItemTag))
                {
                    var suitableItems = Item.ItemList.Where(it => it.HasTag(existingItemTag));
                    switch (spawnPositionType)
                    {
                    case Level.PositionType.Cave:
                    case Level.PositionType.MainPath:
                        item = suitableItems.FirstOrDefault(it => Vector2.DistanceSquared(it.WorldPosition, position) < 1000.0f);
                        break;

                    case Level.PositionType.Ruin:
                        item = suitableItems.FirstOrDefault(it => it.ParentRuin != null && it.ParentRuin.Area.Contains(position));
                        break;

                    case Level.PositionType.Wreck:
                        foreach (Item it in suitableItems)
                        {
                            if (it.Submarine == null || it.Submarine.Info.Type != SubmarineType.Wreck)
                            {
                                continue;
                            }
                            Rectangle worldBorders = it.Submarine.Borders;
                            worldBorders.Location += it.Submarine.WorldPosition.ToPoint();
                            if (Submarine.RectContains(worldBorders, it.WorldPosition))
                            {
                                item = it;
#if SERVER
                                usedExistingItem = true;
#endif
                                break;
                            }
                        }
                        break;
                    }
                }

                if (item == null)
                {
                    item = new Item(itemPrefab, position, null);
                    item.body.FarseerBody.BodyType = BodyType.Kinematic;
                    item.FindHull();
                }

                for (int i = 0; i < statusEffects.Count; i++)
                {
                    List <StatusEffect> effectList = statusEffects[i];
                    if (effectList.Count == 0)
                    {
                        continue;
                    }
                    int effectIndex    = Rand.Int(effectList.Count);
                    var selectedEffect = effectList[effectIndex];
                    item.ApplyStatusEffect(selectedEffect, selectedEffect.type, deltaTime: 1.0f, worldPosition: item.Position);
#if SERVER
                    executedEffectIndices.Add(new Pair <int, int>(i, effectIndex));
#endif
                }

                //try to find a container and place the item inside it
                if (!string.IsNullOrEmpty(containerTag) && item.ParentInventory == null)
                {
                    foreach (Item it in Item.ItemList)
                    {
                        if (!it.HasTag(containerTag))
                        {
                            continue;
                        }
                        if (it.NonInteractable)
                        {
                            continue;
                        }
                        switch (spawnPositionType)
                        {
                        case Level.PositionType.Cave:
                        case Level.PositionType.MainPath:
                            if (it.Submarine != null || it.ParentRuin != null)
                            {
                                continue;
                            }
                            break;

                        case Level.PositionType.Ruin:
                            if (it.ParentRuin == null)
                            {
                                continue;
                            }
                            break;

                        case Level.PositionType.Wreck:
                            if (it.Submarine == null || it.Submarine.Info.Type != SubmarineType.Wreck)
                            {
                                continue;
                            }
                            break;
                        }
                        var itemContainer = it.GetComponent <Items.Components.ItemContainer>();
                        if (itemContainer == null)
                        {
                            continue;
                        }
                        if (itemContainer.Combine(item, user: null))
                        {
#if SERVER
                            originalInventoryID        = it.ID;
                            originalItemContainerIndex = (byte)it.GetComponentIndex(itemContainer);
#endif
                            break;
                        } // Placement successful
                    }
                }
            }
        }
        private void LoadItemAsChild(XElement element, Item parent)
        {
            ItemPrefab itemPrefab;

            if (element.Attribute("name") != null)
            {
                DebugConsole.ThrowError("Error in cargo mission \"" + Name + "\" - use item identifiers instead of names to configure the items.");
                string itemName = element.GetAttributeString("name", "");
                itemPrefab = MapEntityPrefab.Find(itemName) as ItemPrefab;
                if (itemPrefab == null)
                {
                    DebugConsole.ThrowError("Couldn't spawn item for cargo mission: item prefab \"" + itemName + "\" not found");
                    return;
                }
            }
            else
            {
                string itemIdentifier = element.GetAttributeString("identifier", "");
                itemPrefab = MapEntityPrefab.Find(null, itemIdentifier) as ItemPrefab;
                if (itemPrefab == null)
                {
                    DebugConsole.ThrowError("Couldn't spawn item for cargo mission: item prefab \"" + itemIdentifier + "\" not found");
                    return;
                }
            }

            if (itemPrefab == null)
            {
                DebugConsole.ThrowError("Couldn't spawn item for cargo mission: item prefab \"" + element.Name.ToString() + "\" not found");
                return;
            }

            WayPoint cargoSpawnPos = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub, useSyncedRand: true);

            if (cargoSpawnPos == null)
            {
                DebugConsole.ThrowError("Couldn't spawn items for cargo mission, cargo spawnpoint not found");
                return;
            }

            var cargoRoom = cargoSpawnPos.CurrentHull;

            if (cargoRoom == null)
            {
                DebugConsole.ThrowError("A waypoint marked as Cargo must be placed inside a room!");
                return;
            }

            Vector2 position = new Vector2(
                cargoSpawnPos.Position.X + Rand.Range(-20.0f, 20.0f, Rand.RandSync.Server),
                cargoRoom.Rect.Y - cargoRoom.Rect.Height + itemPrefab.Size.Y / 2);

            var item = new Item(itemPrefab, position, cargoRoom.Submarine)
            {
                SpawnedInOutpost = true
            };

            item.FindHull();
            items.Add(item);

            if (parent != null && parent.GetComponent <ItemContainer>() != null)
            {
                parentInventoryIDs.Add(item, parent.ID);
                parentItemContainerIndices.Add(item, (byte)parent.GetComponentIndex(parent.GetComponent <ItemContainer>()));
                parent.Combine(item, user: null);
            }

            foreach (XElement subElement in element.Elements())
            {
                int amount = subElement.GetAttributeInt("amount", 1);
                for (int i = 0; i < amount; i++)
                {
                    LoadItemAsChild(subElement, item);
                }
            }
        }