public void RespawnCharacters() { var server = networkMember as GameServer; if (server == null) { return; } var respawnSub = respawnShuttle != null ? respawnShuttle : Submarine.MainSub; var clients = GetClientsToRespawn(); foreach (Client c in clients) { //all characters are in Team 1 in game modes/missions with only one team. //if at some point we add a game mode with multiple teams where respawning is possible, this needs to be reworked c.TeamID = 1; if (c.CharacterInfo == null) { c.CharacterInfo = new CharacterInfo(Character.HumanConfigFile, c.Name); } } List <CharacterInfo> characterInfos = clients.Select(c => c.CharacterInfo).ToList(); if (server.Character != null && server.Character.IsDead) { characterInfos.Add(server.CharacterInfo); } server.AssignJobs(clients, server.Character != null && server.Character.IsDead); foreach (Client c in clients) { c.CharacterInfo.Job = new Job(c.AssignedJob); } //the spawnpoints where the characters will spawn var shuttleSpawnPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, respawnSub); //the spawnpoints where they would spawn if they were spawned inside the main sub //(in order to give them appropriate ID card tags) var mainSubSpawnPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub); ItemPrefab divingSuitPrefab = MapEntityPrefab.Find("Diving Suit") as ItemPrefab; ItemPrefab oxyPrefab = MapEntityPrefab.Find("Oxygen Tank") as ItemPrefab; ItemPrefab scooterPrefab = MapEntityPrefab.Find("Underwater Scooter") as ItemPrefab; ItemPrefab batteryPrefab = MapEntityPrefab.Find("Battery Cell") as ItemPrefab; var cargoSp = WayPoint.WayPointList.Find(wp => wp.Submarine == respawnSub && wp.SpawnType == SpawnType.Cargo); for (int i = 0; i < characterInfos.Count; i++) { bool myCharacter = false; #if CLIENT myCharacter = i >= clients.Count; #endif var character = Character.Create(characterInfos[i], shuttleSpawnPoints[i].WorldPosition, !myCharacter, false); character.TeamID = 1; #if CLIENT if (myCharacter) { server.Character = character; Character.Controlled = character; GameMain.LightManager.LosEnabled = true; GameServer.Log(string.Format("Respawning {0} (host) as {1}", character.Name, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning); } else { #endif clients[i].Character = character; GameServer.Log(string.Format("Respawning {0} ({1}) as {2}", clients[i].Name, clients[i].Connection?.RemoteEndPoint?.Address, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning); #if CLIENT } #endif Vector2 pos = cargoSp == null ? character.Position : cargoSp.Position; if (divingSuitPrefab != null && oxyPrefab != null) { var divingSuit = new Item(divingSuitPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(divingSuit, false); respawnItems.Add(divingSuit); var oxyTank = new Item(oxyPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(oxyTank, false); divingSuit.Combine(oxyTank); respawnItems.Add(oxyTank); } if (scooterPrefab != null && batteryPrefab != null) { var scooter = new Item(scooterPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(scooter, false); var battery = new Item(batteryPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(battery, false); scooter.Combine(battery); respawnItems.Add(scooter); respawnItems.Add(battery); } //give the character the items they would've gotten if they had spawned in the main sub character.GiveJobItems(mainSubSpawnPoints[i]); //add the ID card tags they should've gotten when spawning in the shuttle foreach (Item item in character.Inventory.Items) { if (item == null || item.Prefab.Name != "ID Card") { continue; } foreach (string s in shuttleSpawnPoints[i].IdCardTags) { item.AddTag(s); } if (!string.IsNullOrWhiteSpace(shuttleSpawnPoints[i].IdCardDesc)) { item.Description = shuttleSpawnPoints[i].IdCardDesc; } } #if CLIENT GameMain.GameSession.CrewManager.AddCharacter(character); #endif } }
private void CreateHulls() { var hullRects = new Rectangle[] { item.WorldRect, DockingTarget.item.WorldRect }; var subs = new Submarine[] { item.Submarine, DockingTarget.item.Submarine }; bodies = new Body[4]; if (DockingTarget.Door != null) { CreateDoorBody(); } if (Door != null) { DockingTarget.CreateDoorBody(); } if (IsHorizontal) { if (hullRects[0].Center.X > hullRects[1].Center.X) { hullRects = new Rectangle[] { DockingTarget.item.WorldRect, item.WorldRect }; subs = new Submarine[] { DockingTarget.item.Submarine, item.Submarine }; } hullRects[0] = new Rectangle(hullRects[0].Center.X, hullRects[0].Y, ((int)DockedDistance / 2), hullRects[0].Height); hullRects[1] = new Rectangle(hullRects[1].Center.X - ((int)DockedDistance / 2), hullRects[1].Y, ((int)DockedDistance / 2), hullRects[1].Height); //expand hulls if needed, so there's no empty space between the sub's hulls and docking port hulls int leftSubRightSide = int.MinValue, rightSubLeftSide = int.MaxValue; foreach (Hull hull in Hull.hullList) { for (int i = 0; i < 2; i++) { if (hull.Submarine != subs[i]) { continue; } if (hull.WorldRect.Y < hullRects[i].Y - hullRects[i].Height) { continue; } if (hull.WorldRect.Y - hull.WorldRect.Height > hullRects[i].Y) { continue; } if (i == 0) //left hull { leftSubRightSide = Math.Max(hull.WorldRect.Right, leftSubRightSide); } else //upper hull { rightSubLeftSide = Math.Min(hull.WorldRect.X, rightSubLeftSide); } } } if (leftSubRightSide == int.MinValue || rightSubLeftSide == int.MaxValue) { DebugConsole.NewMessage("Creating hulls between docking ports failed. Could not find a hull next to the docking port."); return; } //expand left hull to the rightmost hull of the sub at the left side //(unless the difference is more than 100 units - if the distance is very large //there's something wrong with the positioning of the docking ports or submarine hulls) int leftHullDiff = (hullRects[0].X - leftSubRightSide) + 5; if (leftHullDiff > 0) { if (leftHullDiff > 100) { DebugConsole.NewMessage("Creating hulls between docking ports failed. The leftmost docking port seems to be very far from any hulls in the left-side submarine."); return; } else { hullRects[0].X -= leftHullDiff; hullRects[0].Width += leftHullDiff; } } int rightHullDiff = (rightSubLeftSide - hullRects[1].Right) + 5; if (rightHullDiff > 0) { if (rightHullDiff > 100) { DebugConsole.NewMessage("Creating hulls between docking ports failed. The rightmost docking port seems to be very far from any hulls in the right-side submarine."); return; } else { hullRects[1].Width += rightHullDiff; } } for (int i = 0; i < 2; i++) { hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition)); hulls[i] = new Hull(MapEntityPrefab.Find(null, "hull"), hullRects[i], subs[i]); hulls[i].AddToGrid(subs[i]); hulls[i].FreeID(); for (int j = 0; j < 2; j++) { bodies[i + j * 2] = GameMain.World.CreateEdge( ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X, hullRects[i].Y - hullRects[i].Height * j)), ConvertUnits.ToSimUnits(new Vector2(hullRects[i].Right, hullRects[i].Y - hullRects[i].Height * j))); } } if (rightHullDiff <= 100 && hulls[0].Submarine != null) { outsideBlocker = hulls[0].Submarine.PhysicsBody.FarseerBody.CreateRectangle( ConvertUnits.ToSimUnits(hullRects[0].Width + hullRects[1].Width), ConvertUnits.ToSimUnits(hullRects[0].Height), density: 0.0f, offset: ConvertUnits.ToSimUnits(new Vector2(hullRects[0].Right, hullRects[0].Y - hullRects[0].Height / 2) - hulls[0].Submarine.HiddenSubPosition)); outsideBlocker.UserData = this; } gap = new Gap(new Rectangle(hullRects[0].Right - 2, hullRects[0].Y, 4, hullRects[0].Height), true, subs[0]); } else { if (hullRects[0].Center.Y > hullRects[1].Center.Y) { hullRects = new Rectangle[] { DockingTarget.item.WorldRect, item.WorldRect }; subs = new Submarine[] { DockingTarget.item.Submarine, item.Submarine }; } hullRects[0] = new Rectangle(hullRects[0].X, hullRects[0].Y + (int)(-hullRects[0].Height + DockedDistance) / 2, hullRects[0].Width, ((int)DockedDistance / 2)); hullRects[1] = new Rectangle(hullRects[1].X, hullRects[1].Y - hullRects[1].Height / 2, hullRects[1].Width, ((int)DockedDistance / 2)); //expand hulls if needed, so there's no empty space between the sub's hulls and docking port hulls int upperSubBottom = int.MaxValue, lowerSubTop = int.MinValue; foreach (Hull hull in Hull.hullList) { for (int i = 0; i < 2; i++) { if (hull.Submarine != subs[i]) { continue; } if (hull.WorldRect.Right < hullRects[i].X) { continue; } if (hull.WorldRect.X > hullRects[i].Right) { continue; } if (i == 0) //lower hull { lowerSubTop = Math.Max(hull.WorldRect.Y, lowerSubTop); } else //upper hull { upperSubBottom = Math.Min(hull.WorldRect.Y - hull.WorldRect.Height, upperSubBottom); } } } if (upperSubBottom == int.MaxValue || lowerSubTop == int.MinValue) { DebugConsole.NewMessage("Creating hulls between docking ports failed. Could not find a hull next to the docking port."); return; } //expand lower hull to the topmost hull of the lower sub //(unless the difference is more than 100 units - if the distance is very large //there's something wrong with the positioning of the docking ports or submarine hulls) int lowerHullDiff = ((hullRects[0].Y - hullRects[0].Height) - lowerSubTop) + 5; if (lowerHullDiff > 0) { if (lowerHullDiff > 100) { DebugConsole.NewMessage("Creating hulls between docking ports failed. The lower docking port seems to be very far from any hulls in the lower submarine."); return; } else { hullRects[0].Height += lowerHullDiff; } } int upperHullDiff = (upperSubBottom - hullRects[1].Y) + 5; if (upperHullDiff > 0) { if (upperHullDiff > 100) { DebugConsole.NewMessage("Creating hulls between docking ports failed. The upper docking port seems to be very far from any hulls in the upper submarine."); return; } else { hullRects[1].Y += upperHullDiff; hullRects[1].Height += upperHullDiff; } } //difference between the edges of the hulls (to avoid a gap between the hulls) //0 is lower int midHullDiff = ((hullRects[1].Y - hullRects[1].Height) - hullRects[0].Y) + 2; if (midHullDiff > 100) { DebugConsole.NewMessage("Creating hulls between docking ports failed. The upper hull seems to be very far from the lower hull."); return; } else if (midHullDiff > 0) { hullRects[0].Height += midHullDiff / 2 + 1; hullRects[1].Y -= midHullDiff / 2 + 1; hullRects[1].Height += midHullDiff / 2 + 1; } for (int i = 0; i < 2; i++) { hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition)); hulls[i] = new Hull(MapEntityPrefab.Find(null, "hull"), hullRects[i], subs[i]); hulls[i].AddToGrid(subs[i]); hulls[i].FreeID(); for (int j = 0; j < 2; j++) { bodies[i + j * 2] = GameMain.World.CreateEdge( ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X + hullRects[i].Width * j, hullRects[i].Y)), ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X + hullRects[i].Width * j, hullRects[i].Y - hullRects[i].Height))); } } if (midHullDiff <= 100 && hulls[0].Submarine != null) { outsideBlocker = hulls[0].Submarine.PhysicsBody.FarseerBody.CreateRectangle( ConvertUnits.ToSimUnits(hullRects[0].Width), ConvertUnits.ToSimUnits(hullRects[0].Height + hullRects[1].Height), density: 0.0f, offset: ConvertUnits.ToSimUnits(new Vector2(hullRects[0].Center.X, hullRects[0].Y) - hulls[0].Submarine.HiddenSubPosition)); outsideBlocker.UserData = this; } gap = new Gap(new Rectangle(hullRects[0].X, hullRects[0].Y + 2, hullRects[0].Width, 4), false, subs[0]); } LinkHullsToGaps(); hulls[0].ShouldBeSaved = false; hulls[1].ShouldBeSaved = false; item.linkedTo.Add(hulls[0]); item.linkedTo.Add(hulls[1]); gap.FreeID(); gap.DisableHullRechecks = true; gap.ShouldBeSaved = false; item.linkedTo.Add(gap); foreach (Body body in bodies) { if (body == null) { continue; } body.BodyType = BodyType.Static; body.Friction = 0.5f; body.CollisionCategories = Physics.CollisionWall; } }
public override void Update(float deltaTime, Camera cam) { MoveInputQueue(); if (inputContainer == null || inputContainer.Inventory.Items.All(i => i == null)) { SetActive(false); return; } hasPower = voltage >= minVoltage; if (!hasPower) { return; } var repairable = item.GetComponent <Repairable>(); if (repairable != null) { repairable.LastActiveTime = (float)Timing.TotalTime + 10.0f; } ApplyStatusEffects(ActionType.OnActive, deltaTime, null); if (powerConsumption == 0.0f) { voltage = 1.0f; } progressTimer += deltaTime * voltage; Voltage -= deltaTime * 10.0f; var targetItem = inputContainer.Inventory.Items.LastOrDefault(i => i != null); if (targetItem == null) { return; } float deconstructTime = targetItem.Prefab.DeconstructItems.Any() ? targetItem.Prefab.DeconstructTime : 1.0f; progressState = Math.Min(progressTimer / deconstructTime, 1.0f); if (progressTimer > deconstructTime) { foreach (DeconstructItem deconstructProduct in targetItem.Prefab.DeconstructItems) { float percentageHealth = targetItem.Condition / targetItem.Prefab.Health; if (percentageHealth <= deconstructProduct.MinCondition || percentageHealth > deconstructProduct.MaxCondition) { continue; } if (!(MapEntityPrefab.Find(null, deconstructProduct.ItemIdentifier) is ItemPrefab itemPrefab)) { DebugConsole.ThrowError("Tried to deconstruct item \"" + targetItem.Name + "\" but couldn't find item prefab \"" + deconstructProduct.ItemIdentifier + "\"!"); continue; } float condition = deconstructProduct.CopyCondition ? percentageHealth * itemPrefab.Health : itemPrefab.Health * deconstructProduct.OutCondition; //container full, drop the items outside the deconstructor if (outputContainer.Inventory.Items.All(i => i != null)) { Entity.Spawner.AddToSpawnQueue(itemPrefab, item.Position, item.Submarine, condition); } else { Entity.Spawner.AddToSpawnQueue(itemPrefab, outputContainer.Inventory, condition); } } if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer) { if (targetItem.Prefab.DeconstructItems.Any()) { //drop all items that are inside the deconstructed item foreach (ItemContainer ic in targetItem.GetComponents <ItemContainer>()) { if (ic?.Inventory?.Items == null) { continue; } foreach (Item containedItem in ic.Inventory.Items) { containedItem?.Drop(dropper: null, createNetworkEvent: true); } } inputContainer.Inventory.RemoveItem(targetItem); Entity.Spawner.AddToRemoveQueue(targetItem); MoveInputQueue(); PutItemsToLinkedContainer(); } else { if (outputContainer.Inventory.Items.All(i => i != null)) { targetItem.Drop(dropper: null); } else { outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true); } } #if SERVER item.CreateServerEvent(this); #endif progressTimer = 0.0f; progressState = 0.0f; } } voltage -= deltaTime * 10.0f; }
partial void RespawnCharactersProjSpecific() { var respawnSub = RespawnShuttle ?? Submarine.MainSub; var clients = GetClientsToRespawn(); foreach (Client c in clients) { //all characters are in Team 1 in game modes/missions with only one team. //if at some point we add a game mode with multiple teams where respawning is possible, this needs to be reworked c.TeamID = Character.TeamType.Team1; if (c.CharacterInfo == null) { c.CharacterInfo = new CharacterInfo(Character.HumanConfigFile, c.Name); } } List <CharacterInfo> characterInfos = clients.Select(c => c.CharacterInfo).ToList(); var botsToSpawn = GetBotsToRespawn(); characterInfos.AddRange(botsToSpawn); GameMain.Server.AssignJobs(clients); foreach (Client c in clients) { c.CharacterInfo.Job = new Job(c.AssignedJob); } //the spawnpoints where the characters will spawn var shuttleSpawnPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, respawnSub); //the spawnpoints where they would spawn if they were spawned inside the main sub //(in order to give them appropriate ID card tags) var mainSubSpawnPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub); ItemPrefab divingSuitPrefab = MapEntityPrefab.Find(null, "divingsuit") as ItemPrefab; ItemPrefab oxyPrefab = MapEntityPrefab.Find(null, "oxygentank") as ItemPrefab; ItemPrefab scooterPrefab = MapEntityPrefab.Find(null, "underwaterscooter") as ItemPrefab; ItemPrefab batteryPrefab = MapEntityPrefab.Find(null, "batterycell") as ItemPrefab; var cargoSp = WayPoint.WayPointList.Find(wp => wp.Submarine == respawnSub && wp.SpawnType == SpawnType.Cargo); for (int i = 0; i < characterInfos.Count; i++) { bool bot = i >= clients.Count; var character = Character.Create(characterInfos[i], shuttleSpawnPoints[i].WorldPosition, characterInfos[i].Name, !bot, bot); character.TeamID = Character.TeamType.Team1; if (bot) { GameServer.Log(string.Format("Respawning bot {0} as {1}", character.Info.Name, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning); } else { //tell the respawning client they're no longer a traitor if (GameMain.Server.TraitorManager != null && clients[i].Character != null) { if (GameMain.Server.TraitorManager.TraitorList.Any(t => t.Character == clients[i].Character)) { GameMain.Server.SendDirectChatMessage(TextManager.Get("traitorrespawnmessage"), clients[i], ChatMessageType.MessageBox); } } clients[i].Character = character; character.OwnerClientIP = clients[i].Connection.RemoteEndPoint.Address.ToString(); character.OwnerClientName = clients[i].Name; GameServer.Log(string.Format("Respawning {0} ({1}) as {2}", clients[i].Name, clients[i].Connection?.RemoteEndPoint?.Address, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning); } if (divingSuitPrefab != null && oxyPrefab != null && RespawnShuttle != null) { Vector2 pos = cargoSp == null ? character.Position : cargoSp.Position; if (divingSuitPrefab != null && oxyPrefab != null) { var divingSuit = new Item(divingSuitPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(divingSuit, false); respawnItems.Add(divingSuit); var oxyTank = new Item(oxyPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(oxyTank, false); divingSuit.Combine(oxyTank); respawnItems.Add(oxyTank); } if (scooterPrefab != null && batteryPrefab != null) { var scooter = new Item(scooterPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(scooter, false); var battery = new Item(batteryPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(battery, false); scooter.Combine(battery); respawnItems.Add(scooter); respawnItems.Add(battery); } } //give the character the items they would've gotten if they had spawned in the main sub character.GiveJobItems(mainSubSpawnPoints[i]); //add the ID card tags they should've gotten when spawning in the shuttle foreach (Item item in character.Inventory.Items) { if (item == null || item.Prefab.Identifier != "idcard") { continue; } foreach (string s in shuttleSpawnPoints[i].IdCardTags) { item.AddTag(s); } if (!string.IsNullOrWhiteSpace(shuttleSpawnPoints[i].IdCardDesc)) { item.Description = shuttleSpawnPoints[i].IdCardDesc; } } } }
private void CreateHull() { var hullRects = new Rectangle[] { item.WorldRect, dockingTarget.item.WorldRect }; var subs = new Submarine[] { item.Submarine, dockingTarget.item.Submarine }; bodies = new Body[4]; if (dockingTarget.door != null) { CreateDoorBody(); } if (door != null) { dockingTarget.CreateDoorBody(); } if (IsHorizontal) { if (hullRects[0].Center.X > hullRects[1].Center.X) { hullRects = new Rectangle[] { dockingTarget.item.WorldRect, item.WorldRect }; subs = new Submarine[] { dockingTarget.item.Submarine, item.Submarine }; } hullRects[0] = new Rectangle(hullRects[0].Center.X, hullRects[0].Y, ((int)DockedDistance / 2), hullRects[0].Height); hullRects[1] = new Rectangle(hullRects[1].Center.X - ((int)DockedDistance / 2), hullRects[1].Y, ((int)DockedDistance / 2), hullRects[1].Height); for (int i = 0; i < 2; i++) { hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition)); hulls[i] = new Hull(MapEntityPrefab.Find("Hull"), hullRects[i], subs[i]); hulls[i].AddToGrid(subs[i]); hulls[i].FreeID(); for (int j = 0; j < 2; j++) { bodies[i + j * 2] = BodyFactory.CreateEdge(GameMain.World, ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X, hullRects[i].Y - hullRects[i].Height * j)), ConvertUnits.ToSimUnits(new Vector2(hullRects[i].Right, hullRects[i].Y - hullRects[i].Height * j))); } } gap = new Gap(new Rectangle(hullRects[0].Right - 2, hullRects[0].Y, 4, hullRects[0].Height), true, subs[0]); } else { if (hullRects[0].Center.Y > hullRects[1].Center.Y) { hullRects = new Rectangle[] { dockingTarget.item.WorldRect, item.WorldRect }; subs = new Submarine[] { dockingTarget.item.Submarine, item.Submarine }; } hullRects[0] = new Rectangle(hullRects[0].X, hullRects[0].Y + (int)(-hullRects[0].Height + DockedDistance) / 2, hullRects[0].Width, ((int)DockedDistance / 2)); hullRects[1] = new Rectangle(hullRects[1].X, hullRects[1].Y - hullRects[1].Height / 2, hullRects[1].Width, ((int)DockedDistance / 2)); for (int i = 0; i < 2; i++) { hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition)); hulls[i] = new Hull(MapEntityPrefab.Find("Hull"), hullRects[i], subs[i]); hulls[i].AddToGrid(subs[i]); hulls[i].FreeID(); } gap = new Gap(new Rectangle(hullRects[0].X, hullRects[0].Y + 2, hullRects[0].Width, 4), false, subs[0]); } LinkHullsToGap(); hulls[0].ShouldBeSaved = false; hulls[1].ShouldBeSaved = false; item.linkedTo.Add(hulls[0]); item.linkedTo.Add(hulls[1]); gap.FreeID(); gap.DisableHullRechecks = true; gap.ShouldBeSaved = false; item.linkedTo.Add(gap); foreach (Body body in bodies) { if (body == null) { continue; } body.BodyType = BodyType.Static; body.Friction = 0.5f; body.CollisionCategories = Physics.CollisionWall; } }
public FabricableItem(XElement element) { string name = element.GetAttributeString("name", ""); TargetItem = MapEntityPrefab.Find(name) as ItemPrefab; if (TargetItem == null) { return; } RequiredSkills = new List <Skill>(); RequiredTime = element.GetAttributeFloat("requiredtime", 1.0f); OutCondition = element.GetAttributeFloat("outcondition", 1.0f); RequiredItems = new List <Tuple <ItemPrefab, int, float, bool> >(); //Backwards compatibility for string lists string[] requiredItemNames = element.GetAttributeString("requireditems", "").Split(','); foreach (string requiredItemName in requiredItemNames) { if (string.IsNullOrWhiteSpace(requiredItemName)) { continue; } ItemPrefab requiredItem = MapEntityPrefab.Find(requiredItemName.Trim()) as ItemPrefab; if (requiredItem == null) { DebugConsole.ThrowError("Error in fabricable item " + name + "! Required item \"" + requiredItemName + "\" not found."); continue; } var existing = RequiredItems.Find(r => r.Item1 == requiredItem); if (existing == null) { RequiredItems.Add(new Tuple <ItemPrefab, int, float, bool>(requiredItem, 1, 1.0f, false)); } else { RequiredItems.Remove(existing); RequiredItems.Add(new Tuple <ItemPrefab, int, float, bool>(requiredItem, existing.Item2 + 1, 1.0f, false)); } } foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "requiredskill": RequiredSkills.Add(new Skill( subElement.GetAttributeString("name", ""), subElement.GetAttributeInt("level", 0))); break; case "item": //New system allowing for setting minimal item condition string requiredItemName = subElement.GetAttributeString("name", ""); float minCondition = subElement.GetAttributeFloat("mincondition", 1.0f); //Substract mincondition from required item's condition or delete it regardless? bool useCondition = subElement.GetAttributeBool("usecondition", true); int count = subElement.GetAttributeInt("count", 1); if (string.IsNullOrWhiteSpace(requiredItemName)) { continue; } ItemPrefab requiredItem = MapEntityPrefab.Find(requiredItemName.Trim()) as ItemPrefab; if (requiredItem == null) { DebugConsole.ThrowError("Error in fabricable item " + name + "! Required item \"" + requiredItemName + "\" not found."); continue; } var existing = RequiredItems.Find(r => r.Item1 == requiredItem); if (existing == null) { RequiredItems.Add(new Tuple <ItemPrefab, int, float, bool>(requiredItem, count, minCondition, useCondition)); } else { RequiredItems.Remove(existing); RequiredItems.Add(new Tuple <ItemPrefab, int, float, bool>(requiredItem, existing.Item2 + count, minCondition, useCondition)); } break; } } }
partial void RespawnCharactersProjSpecific() { var respawnSub = RespawnShuttle ?? Submarine.MainSub; MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign; var clients = GetClientsToRespawn().ToList(); foreach (Client c in clients) { //get rid of the existing character c.Character?.DespawnNow(); var matchingData = campaign?.GetClientCharacterData(c); if (matchingData != null && !matchingData.HasSpawned) { c.CharacterInfo = matchingData.CharacterInfo; } //all characters are in Team 1 in game modes/missions with only one team. //if at some point we add a game mode with multiple teams where respawning is possible, this needs to be reworked c.TeamID = CharacterTeamType.Team1; if (c.CharacterInfo == null) { c.CharacterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, c.Name); } } List <CharacterInfo> characterInfos = clients.Select(c => c.CharacterInfo).ToList(); //bots don't respawn in the campaign if (campaign == null) { var botsToSpawn = GetBotsToRespawn(); characterInfos.AddRange(botsToSpawn); } GameMain.Server.AssignJobs(clients); foreach (Client c in clients) { if (campaign?.GetClientCharacterData(c) == null || c.CharacterInfo.Job == null) { c.CharacterInfo.Job = new Job(c.AssignedJob.First, c.AssignedJob.Second); } } //the spawnpoints where the characters will spawn var shuttleSpawnPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, respawnSub); //the spawnpoints where they would spawn if they were spawned inside the main sub //(in order to give them appropriate ID card tags) var mainSubSpawnPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub); ItemPrefab divingSuitPrefab = MapEntityPrefab.Find(null, "divingsuit") as ItemPrefab; ItemPrefab oxyPrefab = MapEntityPrefab.Find(null, "oxygentank") as ItemPrefab; ItemPrefab scooterPrefab = MapEntityPrefab.Find(null, "underwaterscooter") as ItemPrefab; ItemPrefab batteryPrefab = MapEntityPrefab.Find(null, "batterycell") as ItemPrefab; var cargoSp = WayPoint.WayPointList.Find(wp => wp.Submarine == respawnSub && wp.SpawnType == SpawnType.Cargo); for (int i = 0; i < characterInfos.Count; i++) { bool bot = i >= clients.Count; characterInfos[i].CurrentOrder = null; characterInfos[i].CurrentOrderOption = null; var character = Character.Create(characterInfos[i], shuttleSpawnPoints[i].WorldPosition, characterInfos[i].Name, isRemotePlayer: !bot, hasAi: bot); character.TeamID = CharacterTeamType.Team1; if (bot) { GameServer.Log(string.Format("Respawning bot {0} as {1}", character.Info.Name, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning); } else { //tell the respawning client they're no longer a traitor if (GameMain.Server.TraitorManager?.Traitors != null && clients[i].Character != null) { if (GameMain.Server.TraitorManager.Traitors.Any(t => t.Character == clients[i].Character)) { GameMain.Server.SendDirectChatMessage(TextManager.FormatServerMessage("TraitorRespawnMessage"), clients[i], ChatMessageType.ServerMessageBox); } } clients[i].Character = character; character.OwnerClientEndPoint = clients[i].Connection.EndPointString; character.OwnerClientName = clients[i].Name; GameServer.Log(string.Format("Respawning {0} ({1}) as {2}", GameServer.ClientLogName(clients[i]), clients[i].Connection?.EndPointString, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning); } if (divingSuitPrefab != null && oxyPrefab != null && RespawnShuttle != null) { Vector2 pos = cargoSp == null ? character.Position : cargoSp.Position; if (divingSuitPrefab != null && oxyPrefab != null) { var divingSuit = new Item(divingSuitPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(divingSuit, false); respawnItems.Add(divingSuit); var oxyTank = new Item(oxyPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(oxyTank, false); divingSuit.Combine(oxyTank, user: null); respawnItems.Add(oxyTank); } if (scooterPrefab != null && batteryPrefab != null) { var scooter = new Item(scooterPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(scooter, false); var battery = new Item(batteryPrefab, pos, respawnSub); Spawner.CreateNetworkEvent(battery, false); scooter.Combine(battery, user: null); respawnItems.Add(scooter); respawnItems.Add(battery); } } var characterData = campaign?.GetClientCharacterData(clients[i]); if (characterData == null || characterData.HasSpawned) { //give the character the items they would've gotten if they had spawned in the main sub character.GiveJobItems(mainSubSpawnPoints[i]); if (campaign != null) { characterData = campaign.SetClientCharacterData(clients[i]); characterData.HasSpawned = true; } } else { characterData.SpawnInventoryItems(character, character.Inventory); characterData.ApplyHealthData(character.Info, character); character.GiveIdCardTags(mainSubSpawnPoints[i]); characterData.HasSpawned = true; } //add the ID card tags they should've gotten when spawning in the shuttle foreach (Item item in character.Inventory.AllItems.Distinct()) { if (item.Prefab.Identifier != "idcard") { continue; } foreach (string s in shuttleSpawnPoints[i].IdCardTags) { item.AddTag(s); } if (!string.IsNullOrWhiteSpace(shuttleSpawnPoints[i].IdCardDesc)) { item.Description = shuttleSpawnPoints[i].IdCardDesc; } } } }
public override void Update(float deltaTime, Camera cam) { if (container == null || container.Inventory.Items.All(i => i == null)) { SetActive(false); return; } if (voltage < minVoltage) { return; } ApplyStatusEffects(ActionType.OnActive, deltaTime, null); if (powerConsumption == 0.0f) { voltage = 1.0f; } progressTimer += deltaTime * voltage; Voltage -= deltaTime * 10.0f; var targetItem = container.Inventory.Items.FirstOrDefault(i => i != null); #if CLIENT progressBar.BarSize = Math.Min(progressTimer / targetItem.Prefab.DeconstructTime, 1.0f); #endif if (progressTimer > targetItem.Prefab.DeconstructTime) { var containers = item.GetComponents <ItemContainer>(); if (containers.Count < 2) { DebugConsole.ThrowError("Error in Deconstructor.Update: Deconstructors must have two ItemContainer components!"); return; } foreach (DeconstructItem deconstructProduct in targetItem.Prefab.DeconstructItems) { float percentageHealth = targetItem.Condition / targetItem.Prefab.Health; if (percentageHealth <= deconstructProduct.MinCondition || percentageHealth > deconstructProduct.MaxCondition) { continue; } var itemPrefab = MapEntityPrefab.Find(deconstructProduct.ItemPrefabName) as ItemPrefab; if (itemPrefab == null) { DebugConsole.ThrowError("Tried to deconstruct item \"" + targetItem.Name + "\" but couldn't find item prefab \"" + deconstructProduct + "\"!"); continue; } //container full, drop the items outside the deconstructor if (containers[1].Inventory.Items.All(i => i != null)) { Entity.Spawner.AddToSpawnQueue(itemPrefab, item.Position, item.Submarine, itemPrefab.Health * deconstructProduct.OutCondition); } else { Entity.Spawner.AddToSpawnQueue(itemPrefab, containers[1].Inventory, itemPrefab.Health * deconstructProduct.OutCondition); } } container.Inventory.RemoveItem(targetItem); Entity.Spawner.AddToRemoveQueue(targetItem); if (container.Inventory.Items.Any(i => i != null)) { progressTimer = 0.0f; #if CLIENT progressBar.BarSize = 0.0f; #endif } } }
private List <RuinShape> GenerateStructures(List <VoronoiCell> caveCells) { List <RuinShape> shapes = new List <RuinShape>(rooms); shapes.AddRange(corridors); foreach (RuinShape leaf in shapes) { RuinStructureType wallType = RuinStructureType.Wall; if (!(leaf is BTRoom)) { wallType = RuinStructureType.CorridorWall; } //rooms further from the entrance are more likely to have hard-to-break walls else if (Rand.Range(0.0f, leaf.DistanceFromEntrance, Rand.RandSync.Server) > 1.5f) { wallType = RuinStructureType.HeavyWall; } //generate walls -------------------------------------------------------------- foreach (Line wall in leaf.Walls) { var structurePrefab = RuinStructure.GetRandom(wallType, leaf.GetLineAlignment(wall)); if (structurePrefab == null) { continue; } float radius = (wall.A.X == wall.B.X) ? (structurePrefab.Prefab as StructurePrefab).Size.X * 0.5f : (structurePrefab.Prefab as StructurePrefab).Size.Y * 0.5f; Rectangle rect = new Rectangle( (int)(wall.A.X - radius), (int)(wall.B.Y + radius), (int)((wall.B.X - wall.A.X) + radius * 2.0f), (int)((wall.B.Y - wall.A.Y) + radius * 2.0f)); //cut a section off from both ends of a horizontal wall to get nicer looking corners if (wall.A.Y == wall.B.Y) { rect.Inflate(-32, 0); if (rect.Width < Submarine.GridSize.X) { continue; } } var structure = new Structure(rect, structurePrefab.Prefab as StructurePrefab, null); structure.MoveWithLevel = true; structure.SetCollisionCategory(Physics.CollisionLevel); } //generate backgrounds -------------------------------------------------------------- var background = RuinStructure.GetRandom(RuinStructureType.Back, Alignment.Center); if (background == null) { continue; } Rectangle backgroundRect = new Rectangle(leaf.Rect.X, leaf.Rect.Y + leaf.Rect.Height, leaf.Rect.Width, leaf.Rect.Height); new Structure(backgroundRect, (background.Prefab as StructurePrefab), null).MoveWithLevel = true; var submarineBlocker = BodyFactory.CreateRectangle(GameMain.World, ConvertUnits.ToSimUnits(leaf.Rect.Width), ConvertUnits.ToSimUnits(leaf.Rect.Height), 1, ConvertUnits.ToSimUnits(leaf.Center)); submarineBlocker.IsStatic = true; submarineBlocker.CollisionCategories = Physics.CollisionWall; submarineBlocker.CollidesWith = Physics.CollisionWall; } List <RuinShape> doorlessRooms = new List <RuinShape>(shapes); //generate doors & sensors that close them ------------------------------------------------------------- var sensorPrefab = MapEntityPrefab.Find("Alien Motion Sensor") as ItemPrefab; var wirePrefab = MapEntityPrefab.Find("Wire") as ItemPrefab; foreach (Corridor corridor in corridors) { var doorPrefab = RuinStructure.GetRandom(corridor.IsHorizontal ? RuinStructureType.Door : RuinStructureType.Hatch, Alignment.Center); if (doorPrefab == null) { continue; } //find all walls that are parallel to the corridor var suitableWalls = corridor.IsHorizontal ? corridor.Walls.FindAll(c => c.A.Y == c.B.Y) : corridor.Walls.FindAll(c => c.A.X == c.B.X); if (!suitableWalls.Any()) { continue; } doorlessRooms.Remove(corridor); Vector2 doorPos = corridor.Center; //choose a random wall to place the door next to var wall = suitableWalls[Rand.Int(suitableWalls.Count, Rand.RandSync.Server)]; if (corridor.IsHorizontal) { doorPos.X = (wall.A.X + wall.B.X) / 2.0f; } else { doorPos.Y = (wall.A.Y + wall.B.Y) / 2.0f; } var door = new Item(doorPrefab.Prefab as ItemPrefab, doorPos, null); door.MoveWithLevel = true; door.GetComponent <Items.Components.Door>().IsOpen = Rand.Range(0.0f, 1.0f, Rand.RandSync.Server) < 0.8f; if (sensorPrefab == null || wirePrefab == null) { continue; } var sensorRoom = corridor.ConnectedRooms.FirstOrDefault(r => r != null && rooms.Contains(r)); if (sensorRoom == null) { continue; } var sensor = new Item(sensorPrefab, new Vector2( Rand.Range(sensorRoom.Rect.X, sensorRoom.Rect.Right, Rand.RandSync.Server), Rand.Range(sensorRoom.Rect.Y, sensorRoom.Rect.Bottom, Rand.RandSync.Server)), null); sensor.MoveWithLevel = true; var wire = new Item(wirePrefab, sensorRoom.Center, null).GetComponent <Items.Components.Wire>(); wire.Item.MoveWithLevel = false; var conn1 = door.Connections.Find(c => c.Name == "set_state"); conn1.AddLink(0, wire); wire.Connect(conn1, false); var conn2 = sensor.Connections.Find(c => c.Name == "state_out"); conn2.AddLink(0, wire); wire.Connect(conn2, false); } //generate props -------------------------------------------------------------- for (int i = 0; i < shapes.Count * 2; i++) { Alignment[] alignments = new Alignment[] { Alignment.Top, Alignment.Bottom, Alignment.Right, Alignment.Left, Alignment.Center }; var prop = RuinStructure.GetRandom(RuinStructureType.Prop, alignments[Rand.Int(alignments.Length, Rand.RandSync.Server)]); if (prop == null) { continue; } Vector2 size = (prop.Prefab is StructurePrefab) ? ((StructurePrefab)prop.Prefab).Size : Vector2.Zero; //if the prop is placed at the center of the room, we have to use a room without a door (because they're also placed at the center) var shape = prop.Alignment.HasFlag(Alignment.Center) ? doorlessRooms[Rand.Int(doorlessRooms.Count, Rand.RandSync.Server)] : shapes[Rand.Int(shapes.Count, Rand.RandSync.Server)]; Vector2 position = shape.Rect.Center.ToVector2(); if (prop.Alignment.HasFlag(Alignment.Top)) { position = new Vector2(Rand.Range(shape.Rect.X + size.X, shape.Rect.Right - size.X, Rand.RandSync.Server), shape.Rect.Bottom - 64); } else if (prop.Alignment.HasFlag(Alignment.Bottom)) { position = new Vector2(Rand.Range(shape.Rect.X + size.X, shape.Rect.Right - size.X, Rand.RandSync.Server), shape.Rect.Top + 64); } else if (prop.Alignment.HasFlag(Alignment.Right)) { position = new Vector2(shape.Rect.Right - 64, Rand.Range(shape.Rect.Y + size.X, shape.Rect.Bottom - size.Y, Rand.RandSync.Server)); } else if (prop.Alignment.HasFlag(Alignment.Left)) { position = new Vector2(shape.Rect.X + 64, Rand.Range(shape.Rect.Y + size.X, shape.Rect.Bottom - size.Y, Rand.RandSync.Server)); } if (prop.Prefab is ItemPrefab) { var item = new Item((ItemPrefab)prop.Prefab, position, null); item.MoveWithLevel = true; } else { new Structure(new Rectangle( (int)(position.X - size.X / 2.0f), (int)(position.Y + size.Y / 2.0f), (int)size.X, (int)size.Y), prop.Prefab as StructurePrefab, null).MoveWithLevel = true; } } return(shapes); }
public override void OnItemLoaded() { base.OnItemLoaded(); if (Signals == null) { Signals = new string[RequiredSignalCount]; for (int i = 0; i < RequiredSignalCount; i++) { Signals[i] = string.Empty; } } else if (Signals.Length != RequiredSignalCount) { string[] newSignals = new string[RequiredSignalCount]; if (Signals.Length < RequiredSignalCount) { Signals.CopyTo(newSignals, 0); for (int i = Signals.Length; i < RequiredSignalCount; i++) { newSignals[i] = string.Empty; } } else { for (int i = 0; i < RequiredSignalCount; i++) { newSignals[i] = Signals[i]; } } Signals = newSignals; } ActivatingItemPrefabs.Clear(); if (!string.IsNullOrEmpty(ActivatingItems)) { foreach (var activatingItem in ActivatingItems.Split(',')) { if (MapEntityPrefab.Find(null, identifier: activatingItem, showErrorMessages: false) is ItemPrefab prefab) { ActivatingItemPrefabs.Add(prefab); } else { ItemPrefab.Prefabs.Where(p => p.Tags.Any(t => t.Equals(activatingItem, StringComparison.OrdinalIgnoreCase))) .ForEach(p => ActivatingItemPrefabs.Add(p)); } } if (ActivatingItemPrefabs.None()) { DebugConsole.ThrowError($"Error in item \"{item.Name}\": no activating item prefabs found with identifiers or tags \"{ActivatingItems}\""); } } var containers = item.GetComponents <ItemContainer>().ToList(); if (containers.Count != 1) { DebugConsole.ThrowError($"Error in item \"{item.Name}\": the ButtonTerminal component requires exactly one ItemContainer component!"); return; } Container = containers[0]; OnItemLoadedProjSpecific(); }
private void ProcessItem(Item targetItem, IEnumerable <Item> inputItems, List <DeconstructItem> validDeconstructItems, bool allowRemove = true) { // In multiplayer, the server handles the deconstruction into new items if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; } if (user != null && !user.Removed) { var abilityTargetItem = new AbilityItem(targetItem); user.CheckTalents(AbilityEffectType.OnItemDeconstructed, abilityTargetItem); } if (targetItem.Prefab.RandomDeconstructionOutput) { int amount = targetItem.Prefab.RandomDeconstructionOutputAmount; List <int> deconstructItemIndexes = new List <int>(); for (int i = 0; i < validDeconstructItems.Count; i++) { deconstructItemIndexes.Add(i); } List <float> commonness = validDeconstructItems.Select(i => i.Commonness).ToList(); List <DeconstructItem> products = new List <DeconstructItem>(); for (int i = 0; i < amount; i++) { if (deconstructItemIndexes.Count < 1) { break; } var itemIndex = ToolBox.SelectWeightedRandom(deconstructItemIndexes, commonness, Rand.RandSync.Unsynced); products.Add(validDeconstructItems[itemIndex]); var removeIndex = deconstructItemIndexes.IndexOf(itemIndex); deconstructItemIndexes.RemoveAt(removeIndex); commonness.RemoveAt(removeIndex); } foreach (DeconstructItem deconstructProduct in products) { CreateDeconstructProduct(deconstructProduct, inputItems); } } else { foreach (DeconstructItem deconstructProduct in validDeconstructItems) { CreateDeconstructProduct(deconstructProduct, inputItems); } } void CreateDeconstructProduct(DeconstructItem deconstructProduct, IEnumerable <Item> inputItems) { float percentageHealth = targetItem.Condition / targetItem.MaxCondition; if (percentageHealth < deconstructProduct.MinCondition || percentageHealth > deconstructProduct.MaxCondition) { return; } if (!(MapEntityPrefab.Find(null, deconstructProduct.ItemIdentifier) is ItemPrefab itemPrefab)) { DebugConsole.ThrowError("Tried to deconstruct item \"" + targetItem.Name + "\" but couldn't find item prefab \"" + deconstructProduct.ItemIdentifier + "\"!"); return; } float condition = deconstructProduct.CopyCondition ? percentageHealth * itemPrefab.Health : itemPrefab.Health * Rand.Range(deconstructProduct.OutConditionMin, deconstructProduct.OutConditionMax); if (DeconstructItemsSimultaneously && deconstructProduct.RequiredOtherItem.Length > 0) { foreach (Item otherItem in inputItems) { if (targetItem == otherItem) { continue; } if (deconstructProduct.RequiredOtherItem.Any(r => otherItem.HasTag(r) || r.Equals(otherItem.Prefab.Identifier, StringComparison.OrdinalIgnoreCase))) { user.CheckTalents(AbilityEffectType.OnGeneticMaterialCombinedOrRefined); foreach (Character character in Character.GetFriendlyCrew(user)) { character.CheckTalents(AbilityEffectType.OnCrewGeneticMaterialCombinedOrRefined); } var geneticMaterial1 = targetItem.GetComponent <GeneticMaterial>(); var geneticMaterial2 = otherItem.GetComponent <GeneticMaterial>(); if (geneticMaterial1 != null && geneticMaterial2 != null) { if (geneticMaterial1.Combine(geneticMaterial2, user)) { inputContainer.Inventory.RemoveItem(otherItem); OutputContainer.Inventory.RemoveItem(otherItem); Entity.Spawner.AddToRemoveQueue(otherItem); } allowRemove = false; return; } inputContainer.Inventory.RemoveItem(otherItem); OutputContainer.Inventory.RemoveItem(otherItem); Entity.Spawner.AddToRemoveQueue(otherItem); } } } int amount = 1; if (user != null && !user.Removed) { var itemsCreated = new AbilityValueItem(amount, targetItem.Prefab); user.CheckTalents(AbilityEffectType.OnItemDeconstructedMaterial, itemsCreated); amount = (int)itemsCreated.Value; // used to spawn items directly into the deconstructor var itemContainer = new AbilityItemPrefabItem(item, targetItem.Prefab); user.CheckTalents(AbilityEffectType.OnItemDeconstructedInventory, itemContainer); } for (int i = 0; i < amount; i++) { Entity.Spawner.AddToSpawnQueue(itemPrefab, outputContainer.Inventory, condition, onSpawned: (Item spawnedItem) => { for (int i = 0; i < outputContainer.Capacity; i++) { var containedItem = outputContainer.Inventory.GetItemAt(i); if (containedItem?.Combine(spawnedItem, null) ?? false) { break; } } PutItemsToLinkedContainer(); }); } } if (targetItem.AllowDeconstruct && allowRemove) { //drop all items that are inside the deconstructed item foreach (ItemContainer ic in targetItem.GetComponents <ItemContainer>()) { if (ic?.Inventory == null || ic.RemoveContainedItemsOnDeconstruct) { continue; } ic.Inventory.AllItemsMod.ForEach(containedItem => outputContainer.Inventory.TryPutItem(containedItem, user: null)); } inputContainer.Inventory.RemoveItem(targetItem); Entity.Spawner.AddToRemoveQueue(targetItem); MoveInputQueue(); PutItemsToLinkedContainer(); } else { if (!outputContainer.Inventory.CanBePut(targetItem) || (Entity.Spawner?.IsInRemoveQueue(targetItem) ?? false)) { targetItem.Drop(dropper: null); } else { outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true); } } }