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); } } }
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)); } } } }
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; }
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); } } }