示例#1
0
        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
            }
        }
示例#2
0
        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;
            }
        }
示例#3
0
        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;
        }
示例#4
0
        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;
                    }
                }
            }
        }
示例#5
0
        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;
            }
        }
示例#6
0
        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;
                }
            }
        }
示例#7
0
        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;
                    }
                }
            }
        }
示例#8
0
        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
                }
            }
        }
示例#9
0
        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);
        }
示例#10
0
        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();
        }
示例#11
0
        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);
                }
            }
        }