Пример #1
0
        public override XElement Save(XElement parentElement)
        {
            if (Submarine == null)
            {
                string errorMsg = "Error - tried to save a hull that's not a part of any submarine.\n" + Environment.StackTrace;
                DebugConsole.ThrowError(errorMsg);
                GameAnalyticsManager.AddErrorEventOnce("Hull.Save:WorldHull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                return(null);
            }

            XElement element = new XElement("Hull");

            element.Add
            (
                new XAttribute("ID", ID),
                new XAttribute("rect",
                               (int)(rect.X - Submarine.HiddenSubPosition.X) + "," +
                               (int)(rect.Y - Submarine.HiddenSubPosition.Y) + "," +
                               rect.Width + "," + rect.Height),
                new XAttribute("water", waterVolume)
            );

            if (linkedTo != null && linkedTo.Count > 0)
            {
                var saveableLinked = linkedTo.Where(l => l.ShouldBeSaved && !l.Removed).ToList();
                element.Add(new XAttribute("linked", string.Join(",", saveableLinked.Select(l => l.ID.ToString()))));
            }

            if (OriginalAmbientLight != null)
            {
                element.Add(new XAttribute("originalambientlight", XMLExtensions.ColorToString(OriginalAmbientLight.Value)));
            }

            SerializableProperty.SerializeProperties(this, element);
            parentElement.Add(element);
            return(element);
        }
Пример #2
0
        public void CreateServerEvent <T>(T ic) where T : ItemComponent, IServerSerializable
        {
            if (GameMain.Server == null)
            {
                return;
            }

            if (!ItemList.Contains(this))
            {
                string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.";
                DebugConsole.ThrowError(errorMsg);
                GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                return;
            }

            int index = components.IndexOf(ic);

            if (index == -1)
            {
                return;
            }

            GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ComponentState, index });
        }
Пример #3
0
        private bool IsValidValue(Vector2 value, string valueName, float?minValue = null, float?maxValue = null)
        {
            if (!MathUtils.IsValid(value) ||
                (minValue.HasValue && (value.X < minValue.Value || value.Y < minValue.Value)) ||
                (maxValue.HasValue && (value.X > maxValue.Value || value.Y > maxValue)))
            {
                string userData = UserData == null ? "null" : UserData.ToString();
                string errorMsg =
                    "Attempted to apply invalid " + valueName +
                    " to a physics body (userdata: " + userData +
                    "), value: " + value + "\n" + Environment.StackTrace;

                if (GameSettings.VerboseLogging)
                {
                    DebugConsole.ThrowError(errorMsg);
                }
                GameAnalyticsManager.AddErrorEventOnce(
                    "PhysicsBody.SetPosition:InvalidPosition" + userData,
                    GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                    errorMsg);
                return(false);
            }
            return(true);
        }
Пример #4
0
        public void SelectMission(int missionIndex)
        {
            if (SelectedConnection == null)
            {
                return;
            }
            if (CurrentLocation == null)
            {
                string errorMsg = "Failed to select a mission (current location not set).";
                DebugConsole.ThrowError(errorMsg);
                GameAnalyticsManager.AddErrorEventOnce("Map.SelectMission:CurrentLocationNotSet", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                return;
            }
            CurrentLocation.SelectedMissionIndex = missionIndex;

            //the destination must be the same as the destination of the mission
            if (CurrentLocation.SelectedMission != null &&
                CurrentLocation.SelectedMission.Locations[1] != SelectedLocation)
            {
                SelectLocation(CurrentLocation.SelectedMission.Locations[1]);
            }

            OnMissionSelected?.Invoke(SelectedConnection, CurrentLocation.SelectedMission);
        }
Пример #5
0
        public bool IsValidValue(float value, string valueName, float minValue = float.MinValue, float maxValue = float.MaxValue)
        {
            if (!MathUtils.IsValid(value) || value < minValue || value > maxValue)
            {
                string userData = UserData == null ? "null" : UserData.ToString();
                string errorMsg =
                    "Attempted to apply invalid " + valueName +
                    " to a physics body (userdata: " + userData +
                    "), value: " + value;
                if (GameMain.NetworkMember != null)
                {
                    errorMsg += GameMain.NetworkMember.IsClient ? " Playing as a client." : " Hosting a server.";
                }
                errorMsg += "\n" + Environment.StackTrace;

                if (GameSettings.VerboseLogging) DebugConsole.ThrowError(errorMsg);
                GameAnalyticsManager.AddErrorEventOnce(
                    "PhysicsBody.SetPosition:InvalidPosition" + userData,
                    GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                    errorMsg);
                return false;
            }
            return true;
        }
Пример #6
0
        public virtual void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
        {
            switch (type)
            {
            case ServerNetObject.ENTITY_POSITION:
                bool facingRight = AnimController.Dir > 0.0f;

                lastRecvPositionUpdateTime = (float)Lidgren.Network.NetTime.Now;

                AnimController.Frozen = false;
                Enabled = true;

                UInt16 networkUpdateID = 0;
                if (msg.ReadBoolean())
                {
                    networkUpdateID = msg.ReadUInt16();
                }
                else
                {
                    bool aimInput = msg.ReadBoolean();
                    keys[(int)InputType.Aim].Held = aimInput;
                    keys[(int)InputType.Aim].SetState(false, aimInput);

                    bool shootInput = msg.ReadBoolean();
                    keys[(int)InputType.Shoot].Held = shootInput;
                    keys[(int)InputType.Shoot].SetState(false, shootInput);

                    bool useInput = msg.ReadBoolean();
                    keys[(int)InputType.Use].Held = useInput;
                    keys[(int)InputType.Use].SetState(false, useInput);

                    if (AnimController is HumanoidAnimController)
                    {
                        bool crouching = msg.ReadBoolean();
                        keys[(int)InputType.Crouch].Held = crouching;
                        keys[(int)InputType.Crouch].SetState(false, crouching);
                    }

                    bool attackInput = msg.ReadBoolean();
                    keys[(int)InputType.Attack].Held = attackInput;
                    keys[(int)InputType.Attack].SetState(false, attackInput);

                    double aimAngle = msg.ReadUInt16() / 65535.0 * 2.0 * Math.PI;
                    cursorPosition = AimRefPosition + new Vector2((float)Math.Cos(aimAngle), (float)Math.Sin(aimAngle)) * 500.0f;
                    TransformCursorPos();

                    bool ragdollInput = msg.ReadBoolean();
                    keys[(int)InputType.Ragdoll].Held = ragdollInput;
                    keys[(int)InputType.Ragdoll].SetState(false, ragdollInput);

                    facingRight = msg.ReadBoolean();
                }

                bool      entitySelected    = msg.ReadBoolean();
                Character selectedCharacter = null;
                Item      selectedItem      = null;

                AnimController.Animation animation = AnimController.Animation.None;
                if (entitySelected)
                {
                    ushort characterID = msg.ReadUInt16();
                    ushort itemID      = msg.ReadUInt16();
                    selectedCharacter = FindEntityByID(characterID) as Character;
                    selectedItem      = FindEntityByID(itemID) as Item;
                    if (characterID != NullEntityID)
                    {
                        bool doingCpr = msg.ReadBoolean();
                        if (doingCpr && SelectedCharacter != null)
                        {
                            animation = AnimController.Animation.CPR;
                        }
                    }
                }

                Vector2 pos = new Vector2(
                    msg.ReadSingle(),
                    msg.ReadSingle());
                float   MaxVel         = NetConfig.MaxPhysicsBodyVelocity;
                Vector2 linearVelocity = new Vector2(
                    msg.ReadRangedSingle(-MaxVel, MaxVel, 12),
                    msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
                linearVelocity = NetConfig.Quantize(linearVelocity, -MaxVel, MaxVel, 12);

                bool  fixedRotation   = msg.ReadBoolean();
                float?rotation        = null;
                float?angularVelocity = null;
                if (!fixedRotation)
                {
                    rotation = msg.ReadSingle();
                    float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;
                    angularVelocity = msg.ReadRangedSingle(-MaxAngularVel, MaxAngularVel, 8);
                    angularVelocity = NetConfig.Quantize(angularVelocity.Value, -MaxAngularVel, MaxAngularVel, 8);
                }

                bool readStatus = msg.ReadBoolean();
                if (readStatus)
                {
                    ReadStatus(msg);
                    (AIController as EnemyAIController)?.PetBehavior?.ClientRead(msg);
                }

                msg.ReadPadBits();

                int index = 0;
                if (GameMain.Client.Character == this && CanMove)
                {
                    var posInfo = new CharacterStateInfo(
                        pos, rotation,
                        networkUpdateID,
                        facingRight ? Direction.Right : Direction.Left,
                        selectedCharacter, selectedItem, animation);

                    while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
                    {
                        index++;
                    }
                    memState.Insert(index, posInfo);
                }
                else
                {
                    var posInfo = new CharacterStateInfo(
                        pos, rotation,
                        linearVelocity, angularVelocity,
                        sendingTime, facingRight ? Direction.Right : Direction.Left,
                        selectedCharacter, selectedItem, animation);

                    while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp)
                    {
                        index++;
                    }
                    memState.Insert(index, posInfo);
                }

                break;

            case ServerNetObject.ENTITY_EVENT:

                int eventType = msg.ReadRangedInteger(0, 5);
                switch (eventType)
                {
                case 0:         //NetEntityEvent.Type.InventoryState
                    if (Inventory == null)
                    {
                        string errorMsg = "Received an inventory update message for an entity with no inventory (" + Name + ", removed: " + Removed + ")";
                        DebugConsole.ThrowError(errorMsg);
                        GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ClientRead:NoInventory" + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);

                        //read anyway to prevent messing up reading the rest of the message
                        UInt16 lastEventID = msg.ReadUInt16();
                        byte   itemCount   = msg.ReadByte();
                        for (int i = 0; i < itemCount; i++)
                        {
                            msg.ReadUInt16();
                        }
                    }
                    else
                    {
                        Inventory.ClientRead(type, msg, sendingTime);
                    }
                    break;

                case 1:         //NetEntityEvent.Type.Control
                    byte ownerID = msg.ReadByte();
                    ResetNetState();
                    if (ownerID == GameMain.Client.ID)
                    {
                        if (controlled != null)
                        {
                            LastNetworkUpdateID = controlled.LastNetworkUpdateID;
                        }

                        if (!IsDead)
                        {
                            Controlled = this;
                        }
                        IsRemotePlayer                   = false;
                        GameMain.Client.HasSpawned       = true;
                        GameMain.Client.Character        = this;
                        GameMain.LightManager.LosEnabled = true;
                    }
                    else
                    {
                        if (controlled == this)
                        {
                            Controlled     = null;
                            IsRemotePlayer = ownerID > 0;
                        }
                    }
                    break;

                case 2:         //NetEntityEvent.Type.Status
                    ReadStatus(msg);
                    break;

                case 3:         //NetEntityEvent.Type.UpdateSkills
                    int skillCount = msg.ReadByte();
                    for (int i = 0; i < skillCount; i++)
                    {
                        string skillIdentifier = msg.ReadString();
                        float  skillLevel      = msg.ReadSingle();
                        info?.SetSkillLevel(skillIdentifier, skillLevel, WorldPosition + Vector2.UnitY * 150.0f);
                    }
                    break;

                case 4:         //NetEntityEvent.Type.ExecuteAttack
                    int    attackLimbIndex = msg.ReadByte();
                    UInt16 targetEntityID  = msg.ReadUInt16();
                    int    targetLimbIndex = msg.ReadByte();

                    //255 = entity already removed, no need to do anything
                    if (attackLimbIndex == 255 || Removed)
                    {
                        break;
                    }

                    if (attackLimbIndex >= AnimController.Limbs.Length)
                    {
                        DebugConsole.ThrowError($"Received invalid ExecuteAttack message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})");
                        break;
                    }
                    Limb attackLimb = AnimController.Limbs[attackLimbIndex];
                    Limb targetLimb = null;
                    if (!(FindEntityByID(targetEntityID) is IDamageable targetEntity))
                    {
                        DebugConsole.ThrowError($"Received invalid ExecuteAttack message. Target entity not found (ID {targetEntityID})");
                        break;
                    }
                    if (targetEntity is Character targetCharacter)
                    {
                        if (targetLimbIndex >= targetCharacter.AnimController.Limbs.Length)
                        {
                            DebugConsole.ThrowError($"Received invalid ExecuteAttack message. Target limb index out of bounds (target character: {targetCharacter.Name}, limb index: {targetLimbIndex}, limb count: {targetCharacter.AnimController.Limbs.Length})");
                            break;
                        }
                        targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex];
                    }
                    if (attackLimb?.attack != null)
                    {
                        attackLimb.ExecuteAttack(targetEntity, targetLimb, out _);
                    }
                    break;

                case 5:         //NetEntityEvent.Type.AssignCampaignInteraction
                    byte campaignInteractionType = msg.ReadByte();
                    (GameMain.GameSession?.GameMode as CampaignMode)?.AssignNPCMenuInteraction(this, (CampaignMode.InteractionType)campaignInteractionType);
                    break;
                }
                msg.ReadPadBits();
                break;
            }
        }
Пример #7
0
        public void SaveNewPlayerConfig()
        {
            XDocument doc = new XDocument();

            UnsavedSettings = false;

            if (doc.Root == null)
            {
                doc.Add(new XElement("config"));
            }

            doc.Root.Add(
                new XAttribute("language", TextManager.Language),
                new XAttribute("masterserverurl", MasterServerUrl),
                new XAttribute("autocheckupdates", AutoCheckUpdates),
                new XAttribute("musicvolume", musicVolume),
                new XAttribute("soundvolume", soundVolume),
                new XAttribute("verboselogging", VerboseLogging),
                new XAttribute("savedebugconsolelogs", SaveDebugConsoleLogs),
                new XAttribute("enablesplashscreen", EnableSplashScreen),
                new XAttribute("usesteammatchmaking", useSteamMatchmaking),
                new XAttribute("quickstartsub", QuickStartSubmarineName),
                new XAttribute("requiresteamauthentication", requireSteamAuthentication),
                new XAttribute("autoupdateworkshopitems", AutoUpdateWorkshopItems),
                new XAttribute("pauseonfocuslost", PauseOnFocusLost),
                new XAttribute("aimassistamount", aimAssistAmount),
                new XAttribute("enablemouselook", EnableMouseLook),
                new XAttribute("chatopen", ChatOpen),
                new XAttribute("crewmenuopen", CrewMenuOpen),
                new XAttribute("campaigndisclaimershown", CampaignDisclaimerShown),
                new XAttribute("editordisclaimershown", EditorDisclaimerShown));

            if (!string.IsNullOrEmpty(overrideSaveFolder))
            {
                doc.Root.Add(new XAttribute("overridesavefolder", overrideSaveFolder));
            }
            if (!string.IsNullOrEmpty(overrideMultiplayerSaveFolder))
            {
                doc.Root.Add(new XAttribute("overridemultiplayersavefolder", overrideMultiplayerSaveFolder));
            }

            if (!ShowUserStatisticsPrompt)
            {
                doc.Root.Add(new XAttribute("senduserstatistics", sendUserStatistics));
            }

            XElement gMode = doc.Root.Element("graphicsmode");

            if (gMode == null)
            {
                gMode = new XElement("graphicsmode");
                doc.Root.Add(gMode);
            }

            if (GraphicsWidth == 0 || GraphicsHeight == 0)
            {
                gMode.ReplaceAttributes(new XAttribute("displaymode", windowMode));
            }
            else
            {
                gMode.ReplaceAttributes(
                    new XAttribute("width", GraphicsWidth),
                    new XAttribute("height", GraphicsHeight),
                    new XAttribute("vsync", VSyncEnabled),
                    new XAttribute("displaymode", windowMode));
            }

            XElement audio = doc.Root.Element("audio");

            if (audio == null)
            {
                audio = new XElement("audio");
                doc.Root.Add(audio);
            }
            audio.ReplaceAttributes(
                new XAttribute("musicvolume", musicVolume),
                new XAttribute("soundvolume", soundVolume),
                new XAttribute("voicechatvolume", voiceChatVolume),
                new XAttribute("microphonevolume", microphoneVolume),
                new XAttribute("muteonfocuslost", MuteOnFocusLost),
                new XAttribute("usedirectionalvoicechat", UseDirectionalVoiceChat),
                new XAttribute("voicesetting", VoiceSetting),
                new XAttribute("voicecapturedevice", VoiceCaptureDevice ?? ""),
                new XAttribute("noisegatethreshold", NoiseGateThreshold));

            XElement gSettings = doc.Root.Element("graphicssettings");

            if (gSettings == null)
            {
                gSettings = new XElement("graphicssettings");
                doc.Root.Add(gSettings);
            }

            gSettings.ReplaceAttributes(
                new XAttribute("particlelimit", ParticleLimit),
                new XAttribute("lightmapscale", LightMapScale),
                new XAttribute("specularity", SpecularityEnabled),
                new XAttribute("chromaticaberration", ChromaticAberrationEnabled),
                new XAttribute("losmode", LosMode),
                new XAttribute("hudscale", HUDScale),
                new XAttribute("inventoryscale", InventoryScale));

            foreach (ContentPackage contentPackage in SelectedContentPackages)
            {
                doc.Root.Add(new XElement("contentpackage",
                                          new XAttribute("path", contentPackage.Path)));
            }

            var keyMappingElement = new XElement("keymapping");

            doc.Root.Add(keyMappingElement);
            for (int i = 0; i < keyMapping.Length; i++)
            {
                if (keyMapping[i].MouseButton == null)
                {
                    keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].Key));
                }
                else
                {
                    keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].MouseButton));
                }
            }

            var gameplay       = new XElement("gameplay");
            var jobPreferences = new XElement("jobpreferences");

            foreach (string jobName in JobPreferences)
            {
                jobPreferences.Add(new XElement("job", new XAttribute("identifier", jobName)));
            }
            gameplay.Add(jobPreferences);
            doc.Root.Add(gameplay);

            var playerElement = new XElement("player",
                                             new XAttribute("name", defaultPlayerName ?? ""),
                                             new XAttribute("headindex", CharacterHeadIndex),
                                             new XAttribute("gender", CharacterGender),
                                             new XAttribute("race", CharacterRace),
                                             new XAttribute("hairindex", CharacterHairIndex),
                                             new XAttribute("beardindex", CharacterBeardIndex),
                                             new XAttribute("moustacheindex", CharacterMoustacheIndex),
                                             new XAttribute("faceattachmentindex", CharacterFaceAttachmentIndex));

            doc.Root.Add(playerElement);

#if CLIENT
            if (Tutorial.Tutorials != null)
            {
                foreach (Tutorial tutorial in Tutorial.Tutorials)
                {
                    if (tutorial.Completed && !CompletedTutorialNames.Contains(tutorial.Identifier))
                    {
                        CompletedTutorialNames.Add(tutorial.Identifier);
                    }
                }
            }
#endif
            var tutorialElement = new XElement("tutorials");
            foreach (string tutorialName in CompletedTutorialNames)
            {
                tutorialElement.Add(new XElement("Tutorial", new XAttribute("name", tutorialName)));
            }
            doc.Root.Add(tutorialElement);

            XmlWriterSettings settings = new XmlWriterSettings
            {
                Indent              = true,
                OmitXmlDeclaration  = true,
                NewLineOnAttributes = true
            };

            try
            {
                using (var writer = XmlWriter.Create(playerSavePath, settings))
                {
                    doc.WriteTo(writer);
                    writer.Flush();
                }
            }
            catch (Exception e)
            {
                DebugConsole.ThrowError("Saving game settings failed.", e);
                GameAnalyticsManager.AddErrorEventOnce("GameSettings.Save:SaveFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                                                       "Saving game settings failed.\n" + e.Message + "\n" + e.StackTrace);
            }
        }
Пример #8
0
        private void SaveNewDefaultConfig()
        {
            XDocument doc = new XDocument();

            if (doc.Root == null)
            {
                doc.Add(new XElement("config"));
            }

            doc.Root.Add(
                new XAttribute("language", TextManager.Language),
                new XAttribute("masterserverurl", MasterServerUrl),
                new XAttribute("autocheckupdates", AutoCheckUpdates),
                new XAttribute("musicvolume", musicVolume),
                new XAttribute("soundvolume", soundVolume),
                new XAttribute("microphonevolume", microphoneVolume),
                new XAttribute("voicechatvolume", voiceChatVolume),
                new XAttribute("verboselogging", VerboseLogging),
                new XAttribute("savedebugconsolelogs", SaveDebugConsoleLogs),
                new XAttribute("enablesplashscreen", EnableSplashScreen),
                new XAttribute("usesteammatchmaking", useSteamMatchmaking),
                new XAttribute("quickstartsub", QuickStartSubmarineName),
                new XAttribute("requiresteamauthentication", requireSteamAuthentication),
                new XAttribute("aimassistamount", aimAssistAmount));

            if (!ShowUserStatisticsPrompt)
            {
                doc.Root.Add(new XAttribute("senduserstatistics", sendUserStatistics));
            }

            if (WasGameUpdated)
            {
                doc.Root.Add(new XAttribute("wasgameupdated", true));
            }

            XElement gMode = doc.Root.Element("graphicsmode");

            if (gMode == null)
            {
                gMode = new XElement("graphicsmode");
                doc.Root.Add(gMode);
            }
            if (GraphicsWidth == 0 || GraphicsHeight == 0)
            {
                gMode.ReplaceAttributes(new XAttribute("displaymode", windowMode));
            }
            else
            {
                gMode.ReplaceAttributes(
                    new XAttribute("width", GraphicsWidth),
                    new XAttribute("height", GraphicsHeight),
                    new XAttribute("vsync", VSyncEnabled),
                    new XAttribute("displaymode", windowMode));
            }

            XElement gSettings = doc.Root.Element("graphicssettings");

            if (gSettings == null)
            {
                gSettings = new XElement("graphicssettings");
                doc.Root.Add(gSettings);
            }

            gSettings.ReplaceAttributes(
                new XAttribute("particlelimit", ParticleLimit),
                new XAttribute("lightmapscale", LightMapScale),
                new XAttribute("specularity", SpecularityEnabled),
                new XAttribute("chromaticaberration", ChromaticAberrationEnabled),
                new XAttribute("losmode", LosMode),
                new XAttribute("hudscale", HUDScale),
                new XAttribute("inventoryscale", InventoryScale));

            foreach (ContentPackage contentPackage in SelectedContentPackages)
            {
                if (contentPackage.Path.Contains(vanillaContentPackagePath))
                {
                    doc.Root.Add(new XElement("contentpackage", new XAttribute("path", contentPackage.Path)));
                    break;
                }
            }

            var keyMappingElement = new XElement("keymapping");

            doc.Root.Add(keyMappingElement);
            for (int i = 0; i < keyMapping.Length; i++)
            {
                if (keyMapping[i].MouseButton == null)
                {
                    keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].Key));
                }
                else
                {
                    keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].MouseButton));
                }
            }

            var gameplay       = new XElement("gameplay");
            var jobPreferences = new XElement("jobpreferences");

            foreach (string jobName in JobPreferences)
            {
                jobPreferences.Add(new XElement("job", new XAttribute("identifier", jobName)));
            }
            gameplay.Add(jobPreferences);
            doc.Root.Add(gameplay);

            var playerElement = new XElement("player",
                                             new XAttribute("name", defaultPlayerName ?? ""),
                                             new XAttribute("headindex", CharacterHeadIndex),
                                             new XAttribute("gender", CharacterGender),
                                             new XAttribute("race", CharacterRace),
                                             new XAttribute("hairindex", CharacterHairIndex),
                                             new XAttribute("beardindex", CharacterBeardIndex),
                                             new XAttribute("moustacheindex", CharacterMoustacheIndex),
                                             new XAttribute("faceattachmentindex", CharacterFaceAttachmentIndex));

            doc.Root.Add(playerElement);

            XmlWriterSettings settings = new XmlWriterSettings
            {
                Indent              = true,
                OmitXmlDeclaration  = true,
                NewLineOnAttributes = true
            };

            try
            {
                using (var writer = XmlWriter.Create(savePath, settings))
                {
                    doc.WriteTo(writer);
                    writer.Flush();
                }
            }
            catch (Exception e)
            {
                DebugConsole.ThrowError("Saving game settings failed.", e);
                GameAnalyticsManager.AddErrorEventOnce("GameSettings.Save:SaveFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                                                       "Saving game settings failed.\n" + e.Message + "\n" + e.StackTrace);
            }
        }
Пример #9
0
        public override void Update(float deltaTime, Camera cam)
        {
            flowForce = Vector2.Zero;

            outsideColliderRaycastTimer -= deltaTime;

            if (open == 0.0f || linkedTo.Count == 0)
            {
                lerpedFlowForce = Vector2.Zero;
                return;
            }

            Hull hull1 = (Hull)linkedTo[0];
            Hull hull2 = linkedTo.Count < 2 ? null : (Hull)linkedTo[1];

            if (hull1 == hull2)
            {
                return;
            }

            UpdateOxygen(hull1, hull2);

            if (linkedTo.Count == 1)
            {
                //gap leading from a room to outside
                UpdateRoomToOut(deltaTime, hull1);
            }
            else if (linkedTo.Count == 2)
            {
                //gap leading from a room to another
                UpdateRoomToRoom(deltaTime, hull1, hull2);
            }

            flowForce.X     = MathHelper.Clamp(flowForce.X, -MaxFlowForce, MaxFlowForce);
            flowForce.Y     = MathHelper.Clamp(flowForce.Y, -MaxFlowForce, MaxFlowForce);
            lerpedFlowForce = Vector2.Lerp(lerpedFlowForce, flowForce, deltaTime * 5.0f);

            EmitParticles(deltaTime);

            if (flowTargetHull != null && lerpedFlowForce.LengthSquared() > 0.0001f)
            {
                foreach (Character character in Character.CharacterList)
                {
                    if (character.CurrentHull == null)
                    {
                        continue;
                    }
                    if (character.CurrentHull != linkedTo[0] as Hull &&
                        (linkedTo.Count < 2 || character.CurrentHull != linkedTo[1] as Hull))
                    {
                        continue;
                    }

                    foreach (Limb limb in character.AnimController.Limbs)
                    {
                        if (!limb.inWater)
                        {
                            continue;
                        }

                        float dist = Vector2.Distance(limb.WorldPosition, WorldPosition);
                        if (dist > lerpedFlowForce.Length())
                        {
                            continue;
                        }

                        Vector2 force = lerpedFlowForce / (float)Math.Max(Math.Sqrt(dist), 20.0f) * 0.025f;

                        //vertical gaps only apply forces if the character is roughly above/below the gap
                        if (!IsHorizontal)
                        {
                            float xDist = Math.Abs(limb.WorldPosition.X - WorldPosition.X);
                            if (xDist > rect.Width || rect.Width == 0)
                            {
                                break;
                            }

                            force *= 1.0f - xDist / rect.Width;
                        }

                        if (!MathUtils.IsValid(force))
                        {
                            string errorMsg = "Attempted to apply invalid flow force to the character \"" + character.Name +
                                              "\", gap pos: " + WorldPosition +
                                              ", limb pos: " + limb.WorldPosition +
                                              ", flowforce: " + flowForce + ", lerpedFlowForce:" + lerpedFlowForce +
                                              ", dist: " + dist;

                            DebugConsole.Log(errorMsg);
                            GameAnalyticsManager.AddErrorEventOnce("Gap.Update:InvalidFlowForce:" + character.Name,
                                                                   GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                                                                   errorMsg);
                            continue;
                        }
                        character.AnimController.Collider.ApplyForce(force * limb.body.Mass, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
                    }
                }
            }
        }
Пример #10
0
        void UpdateDying(float deltaTime)
        {
            if (deathAnimDuration <= 0.0f)
            {
                return;
            }

            float noise        = (PerlinNoise.GetPerlin(WalkPos * 0.002f, WalkPos * 0.003f) - 0.5f) * 5.0f;
            float animStrength = (1.0f - deathAnimTimer / deathAnimDuration);

            Limb head = GetLimb(LimbType.Head);

            if (head != null && head.IsSevered)
            {
                return;
            }
            Limb tail = GetLimb(LimbType.Tail);

            if (head != null && !head.IsSevered)
            {
                head.body.ApplyTorque((float)(Math.Sqrt(head.Mass) * Dir * (Math.Sin(WalkPos) + noise)) * 30.0f * animStrength);
            }
            if (tail != null && !tail.IsSevered)
            {
                tail.body.ApplyTorque((float)(Math.Sqrt(tail.Mass) * -Dir * (Math.Sin(WalkPos) + noise)) * 30.0f * animStrength);
            }

            WalkPos += deltaTime * 10.0f * animStrength;

            Vector2 centerOfMass = GetCenterOfMass();

            foreach (Limb limb in Limbs)
            {
                if (limb.IsSevered)
                {
                    continue;
                }
#if CLIENT
                if (limb.LightSource != null)
                {
                    limb.LightSource.Color = Color.Lerp(limb.InitialLightSourceColor, Color.TransparentBlack, deathAnimTimer / deathAnimDuration);
                    if (limb.InitialLightSpriteAlpha.HasValue)
                    {
                        limb.LightSource.OverrideLightSpriteAlpha = MathHelper.Lerp(limb.InitialLightSpriteAlpha.Value, 0.0f, deathAnimTimer / deathAnimDuration);
                    }
                }
#endif
                if (limb.type == LimbType.Head || limb.type == LimbType.Tail || limb.IsSevered || !limb.body.Enabled)
                {
                    continue;
                }
                if (limb.Mass <= 0.0f)
                {
                    string errorMsg = "Creature death animation error: invalid limb mass on character \"" + character.SpeciesName + "\" (type: " + limb.type + ", mass: " + limb.Mass + ")";
                    DebugConsole.ThrowError(errorMsg);
                    GameAnalyticsManager.AddErrorEventOnce("FishAnimController.UpdateDying:InvalidMass" + character.ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                    deathAnimTimer = deathAnimDuration;
                    return;
                }

                Vector2 diff = (centerOfMass - limb.SimPosition);
                if (!MathUtils.IsValid(diff))
                {
                    string errorMsg = "Creature death animation error: invalid diff (center of mass: " + centerOfMass + ", limb position: " + limb.SimPosition + ")";
                    DebugConsole.ThrowError(errorMsg);
                    GameAnalyticsManager.AddErrorEventOnce("FishAnimController.UpdateDying:InvalidDiff" + character.ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                    deathAnimTimer = deathAnimDuration;
                    return;
                }

                limb.body.ApplyForce(diff * (float)(Math.Sin(WalkPos) * Math.Sqrt(limb.Mass)) * 30.0f * animStrength, maxVelocity: 10.0f);
            }
        }
Пример #11
0
        public GUIFrame CreateSummaryFrame(string endMessage)
        {
            bool singleplayer = GameMain.NetworkMember == null;
            bool gameOver     = gameSession.CrewManager.GetCharacters().All(c => c.IsDead || c.IsUnconscious);
            bool progress     = Submarine.MainSub.AtEndPosition;

            if (!singleplayer)
            {
                SoundPlayer.OverrideMusicType     = gameOver ? "crewdead" : "endround";
                SoundPlayer.OverrideMusicDuration = 18.0f;
            }

            GUIFrame frame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker");

            int      width = 760, height = 500;
            GUIFrame innerFrame  = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.5f), frame.RectTransform, Anchor.Center, minSize: new Point(width, height)));
            var      paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), innerFrame.RectTransform, Anchor.Center))
            {
                Stretch         = true,
                RelativeSpacing = 0.03f
            };

            GUIListBox infoTextBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.7f), paddedFrame.RectTransform))
            {
                Spacing = (int)(5 * GUI.Scale)
            };

            //spacing
            new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), infoTextBox.Content.RectTransform), style: null);

            string summaryText = TextManager.GetWithVariables(gameOver ? "RoundSummaryGameOver" :
                                                              (progress ? "RoundSummaryProgress" : "RoundSummaryReturn"), new string[2] {
                "[sub]", "[location]"
            },
                                                              new string[2] {
                Submarine.MainSub.Name, progress ? GameMain.GameSession.EndLocation.Name : GameMain.GameSession.StartLocation.Name
            });

            var infoText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
                                            summaryText, wrap: true);

            GUIComponent endText = null;

            if (!string.IsNullOrWhiteSpace(endMessage))
            {
                endText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
                                           TextManager.GetServerMessage(endMessage), wrap: true);
            }

            //don't show the mission info if the mission was not completed and there's no localized "mission failed" text available
            if (GameMain.GameSession.Mission != null)
            {
                string message = GameMain.GameSession.Mission.Completed ? GameMain.GameSession.Mission.SuccessMessage : GameMain.GameSession.Mission.FailureMessage;
                if (!string.IsNullOrEmpty(message))
                {
                    //spacing
                    var spacingTransform = new RectTransform(new Vector2(1.0f, 0.1f), infoTextBox.Content.RectTransform);

                    new GUIFrame(spacingTransform, style: null);

                    new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
                                     TextManager.AddPunctuation(':', TextManager.Get("Mission"), GameMain.GameSession.Mission.Name),
                                     font: GUI.LargeFont);

                    var missionInfo = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
                                                       message, wrap: true);

                    if (GameMain.GameSession.Mission.Completed && singleplayer)
                    {
                        var missionReward = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoTextBox.Content.RectTransform),
                                                             TextManager.GetWithVariable("MissionReward", "[reward]", GameMain.GameSession.Mission.Reward.ToString()));
                    }
                }
            }

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform),
                             TextManager.Get("RoundSummaryCrewStatus"), font: GUI.LargeFont);

            GUIListBox characterListBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.4f), paddedFrame.RectTransform, minSize: new Point(0, 75)), isHorizontal: true);

            foreach (CharacterInfo characterInfo in gameSession.CrewManager.GetCharacterInfos())
            {
                if (GameMain.GameSession.Mission is CombatMission &&
                    characterInfo.TeamID != GameMain.GameSession.WinningTeam)
                {
                    continue;
                }

                var characterFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f, 1.0f), characterListBox.Content.RectTransform, minSize: new Point(170, 0)))
                {
                    CanBeFocused = false,
                    Stretch      = true
                };

                characterInfo.CreateCharacterFrame(characterFrame,
                                                   characterInfo.Job != null ? (characterInfo.Name + '\n' + "(" + characterInfo.Job.Name + ")") : characterInfo.Name, null);

                string statusText  = TextManager.Get("StatusOK");
                Color  statusColor = Color.DarkGreen;

                Character character = characterInfo.Character;
                if (character == null || character.IsDead)
                {
                    if (characterInfo.CauseOfDeath == null)
                    {
                        statusText = TextManager.Get("CauseOfDeathDescription.Unknown");
                    }
                    else if (characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction && characterInfo.CauseOfDeath.Affliction == null)
                    {
                        string errorMsg = "Character \"" + character.Name + "\" had an invalid cause of death (the type of the cause of death was Affliction, but affliction was not specified).";
                        DebugConsole.ThrowError(errorMsg);
                        GameAnalyticsManager.AddErrorEventOnce("RoundSummary:InvalidCauseOfDeath", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                        statusText = TextManager.Get("CauseOfDeathDescription.Unknown");
                    }
                    else
                    {
                        statusText = characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction ?
                                     characterInfo.CauseOfDeath.Affliction.CauseOfDeathDescription :
                                     TextManager.Get("CauseOfDeathDescription." + characterInfo.CauseOfDeath.Type.ToString());
                    }
                    statusColor = Color.DarkRed;
                }
                else
                {
                    if (character.IsUnconscious)
                    {
                        statusText  = TextManager.Get("Unconscious");
                        statusColor = Color.DarkOrange;
                    }
                    else if (character.Vitality / character.MaxVitality < 0.8f)
                    {
                        statusText  = TextManager.Get("Injured");
                        statusColor = Color.DarkOrange;
                    }
                }

                var textHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), characterFrame.RectTransform, Anchor.BottomCenter), style: "InnerGlow", color: statusColor);
                new GUITextBlock(new RectTransform(Vector2.One, textHolder.RectTransform, Anchor.Center),
                                 statusText, Color.White,
                                 textAlignment: Alignment.Center,
                                 wrap: true, font: GUI.SmallFont, style: null);
            }

            new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedFrame.RectTransform), isHorizontal: true, childAnchor: Anchor.BottomRight)
            {
                RelativeSpacing = 0.05f,
                UserData        = "buttonarea"
            };

            paddedFrame.Recalculate();
            foreach (GUIComponent child in infoTextBox.Content.Children)
            {
                child.CanBeFocused = false;
                if (child is GUITextBlock textBlock)
                {
                    textBlock.CalculateHeightFromText();
                }
            }

            return(frame);
        }
Пример #12
0
        public override bool TryPutItem(Item item, int index, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true, bool ignoreCondition = false)
        {
            if (index < 0 || index >= slots.Length)
            {
                string errorMsg = "CharacterInventory.TryPutItem failed: index was out of range(" + index + ").\n" + Environment.StackTrace.CleanupStackTrace();
                GameAnalyticsManager.AddErrorEventOnce("CharacterInventory.TryPutItem:IndexOutOfRange", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                return(false);
            }
#if CLIENT
            if (PersonalSlots.HasFlag(SlotTypes[index]))
            {
                hidePersonalSlots = false;
            }
#endif
            //there's already an item in the slot
            if (slots[index].Any())
            {
                if (slots[index].Contains(item))
                {
                    return(false);
                }
                return(base.TryPutItem(item, index, allowSwapping, allowCombine, user, createNetworkEvent, ignoreCondition));
            }

            if (SlotTypes[index] == InvSlotType.Any)
            {
                if (!item.GetComponents <Pickable>().Any(p => p.AllowedSlots.Contains(InvSlotType.Any)))
                {
                    return(false);
                }
                if (slots[index].Any())
                {
                    return(slots[index].Contains(item));
                }
                PutItem(item, index, user, true, createNetworkEvent);
                return(true);
            }

            InvSlotType placeToSlots = InvSlotType.None;

            bool slotsFree = true;
            foreach (Pickable pickable in item.GetComponents <Pickable>())
            {
                foreach (InvSlotType allowedSlot in pickable.AllowedSlots)
                {
                    if (!allowedSlot.HasFlag(SlotTypes[index]))
                    {
                        continue;
                    }
    #if CLIENT
                    if (PersonalSlots.HasFlag(allowedSlot))
                    {
                        hidePersonalSlots = false;
                    }
    #endif
                    for (int i = 0; i < capacity; i++)
                    {
                        if (allowedSlot.HasFlag(SlotTypes[i]) && slots[i].Any() && !slots[i].Contains(item))
                        {
                            slotsFree = false;
                            break;
                        }
                        placeToSlots = allowedSlot;
                    }
                }
            }

            if (!slotsFree)
            {
                return(false);
            }

            return(TryPutItem(item, user, new List <InvSlotType>()
            {
                placeToSlots
            }, createNetworkEvent, ignoreCondition));
        }
Пример #13
0
        public static VertexPositionTexture[] GenerateWallShapes(List <VoronoiCell> cells, Level level)
        {
            float outWardThickness = 30.0f;

            List <VertexPositionTexture> verticeList = new List <VertexPositionTexture>();

            foreach (VoronoiCell cell in cells)
            {
                CompareCCW compare = new CompareCCW(cell.Center);
                foreach (GraphEdge edge in cell.Edges)
                {
                    if (edge.Cell1 != null && edge.Cell1.Body == null && edge.Cell1.CellType != CellType.Empty)
                    {
                        edge.Cell1 = null;
                    }
                    if (edge.Cell2 != null && edge.Cell2.Body == null && edge.Cell2.CellType != CellType.Empty)
                    {
                        edge.Cell2 = null;
                    }

                    if (compare.Compare(edge.Point1, edge.Point2) == -1)
                    {
                        var temp = edge.Point1;
                        edge.Point1 = edge.Point2;
                        edge.Point2 = temp;
                    }
                }
            }

            foreach (VoronoiCell cell in cells)
            {
                foreach (GraphEdge edge in cell.Edges)
                {
                    if (!edge.IsSolid)
                    {
                        continue;
                    }

                    GraphEdge leftEdge  = cell.Edges.Find(e => e != edge && (edge.Point1 == e.Point1 || edge.Point1 == e.Point2));
                    GraphEdge rightEdge = cell.Edges.Find(e => e != edge && (edge.Point2 == e.Point1 || edge.Point2 == e.Point2));

                    Vector2 leftNormal = Vector2.Zero, rightNormal = Vector2.Zero;

                    float inwardThickness1 = 100;
                    float inwardThickness2 = 100;
                    if (leftEdge != null && !leftEdge.IsSolid)
                    {
                        leftNormal = edge.Point1 == leftEdge.Point1 ?
                                     Vector2.Normalize(leftEdge.Point2 - leftEdge.Point1) :
                                     Vector2.Normalize(leftEdge.Point1 - leftEdge.Point2);
                        inwardThickness1 = Vector2.Distance(leftEdge.Point1, leftEdge.Point2) / 2;
                    }
                    else
                    {
                        leftNormal       = Vector2.Normalize(cell.Center - edge.Point1);
                        inwardThickness1 = Vector2.Distance(edge.Point1, cell.Center) / 2;
                    }

                    if (!MathUtils.IsValid(leftNormal))
                    {
#if DEBUG
                        DebugConsole.ThrowError("Invalid left normal");
#endif
                        GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidLeftNormal:" + level.Seed,
                                                               GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
                                                               "Invalid left normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + leftNormal + ", seed: " + level.Seed + ")");

                        if (cell.Body != null)
                        {
                            GameMain.World.RemoveBody(cell.Body);
                            cell.Body = null;
                        }
                        leftNormal = Vector2.UnitX;
                        break;
                    }

                    if (rightEdge != null && !rightEdge.IsSolid)
                    {
                        rightNormal = edge.Point2 == rightEdge.Point1 ?
                                      Vector2.Normalize(rightEdge.Point2 - rightEdge.Point1) :
                                      Vector2.Normalize(rightEdge.Point1 - rightEdge.Point2);
                        inwardThickness2 = Vector2.Distance(rightEdge.Point1, rightEdge.Point2) / 2;
                    }
                    else
                    {
                        rightNormal      = Vector2.Normalize(cell.Center - edge.Point2);
                        inwardThickness2 = Vector2.Distance(edge.Point2, cell.Center) / 2;
                    }

                    if (!MathUtils.IsValid(rightNormal))
                    {
#if DEBUG
                        DebugConsole.ThrowError("Invalid right normal");
#endif
                        GameAnalyticsManager.AddErrorEventOnce("CaveGenerator.GenerateWallShapes:InvalidRightNormal:" + level.Seed,
                                                               GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
                                                               "Invalid right normal (leftedge: " + leftEdge + ", rightedge: " + rightEdge + ", normal: " + rightNormal + ", seed: " + level.Seed + ")");

                        if (cell.Body != null)
                        {
                            GameMain.World.RemoveBody(cell.Body);
                            cell.Body = null;
                        }
                        rightNormal = Vector2.UnitX;
                        break;
                    }

                    float point1UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point1 - cell.Center));
                    float point2UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point2 - cell.Center));
                    //handle wrapping around 0/360
                    if (point1UV - point2UV > MathHelper.Pi)
                    {
                        point2UV += MathHelper.TwoPi;
                    }
                    //the texture wraps around the cell 4 times
                    //TODO: define the uv scale in level generation parameters?
                    point1UV = point1UV / MathHelper.TwoPi * 4;
                    point2UV = point2UV / MathHelper.TwoPi * 4;

                    for (int i = 0; i < 2; i++)
                    {
                        Vector2[] verts = new Vector2[3];
                        VertexPositionTexture[] vertPos = new VertexPositionTexture[3];

                        if (i == 0)
                        {
                            verts[0] = edge.Point1 - leftNormal * outWardThickness;
                            verts[1] = edge.Point2 - rightNormal * outWardThickness;
                            verts[2] = edge.Point1 + leftNormal * inwardThickness1;

                            vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), new Vector2(point1UV, 0.0f));
                            vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), new Vector2(point2UV, 0.0f));
                            vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(point1UV, 0.5f));
                        }
                        else
                        {
                            verts[0] = edge.Point1 + leftNormal * inwardThickness1;
                            verts[1] = edge.Point2 - rightNormal * outWardThickness;
                            verts[2] = edge.Point2 + rightNormal * inwardThickness2;

                            vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], 0.0f), new Vector2(point1UV, 0.5f));
                            vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], 0.0f), new Vector2(point2UV, 0.0f));
                            vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], 0.0f), new Vector2(point2UV, 0.5f));
                        }
                        verticeList.AddRange(vertPos);
                    }
                }
            }

            return(verticeList.ToArray());
        }
Пример #14
0
        private void CreateCharacterElement(CharacterInfo characterInfo, GUIListBox listBox)
        {
            GUIFrame frame = new GUIFrame(new RectTransform(new Point(listBox.Content.Rect.Width, GUI.IntScale(45)), listBox.Content.RectTransform), style: "ListBoxElement")
            {
                CanBeFocused = false,
                UserData     = characterInfo,
                Color        = (Character.Controlled?.Info == characterInfo) ? TabMenu.OwnCharacterBGColor : Color.Transparent
            };

            var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), frame.RectTransform, Anchor.Center), isHorizontal: true)
            {
                AbsoluteSpacing = 2,
                Stretch         = true
            };

            new GUICustomComponent(new RectTransform(new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform, Anchor.Center), onDraw: (sb, component) => characterInfo.DrawJobIcon(sb, component.Rect))
            {
                ToolTip       = characterInfo.Job.Name ?? "",
                HoverColor    = Color.White,
                SelectedColor = Color.White
            };

            GUITextBlock characterNameBlock = new GUITextBlock(new RectTransform(new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
                                                               ToolBox.LimitString(characterInfo.Name, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: characterInfo.Job.Prefab.UIColor);

            string statusText  = TextManager.Get("StatusOK");
            Color  statusColor = GUI.Style.Green;

            Character character = characterInfo.Character;

            if (character == null || character.IsDead)
            {
                if (character == null && characterInfo.IsNewHire)
                {
                    statusText  = TextManager.Get("CampaignCrew.NewHire");
                    statusColor = GUI.Style.Blue;
                }
                else if (characterInfo.CauseOfDeath == null)
                {
                    statusText  = TextManager.Get("CauseOfDeathDescription.Unknown");
                    statusColor = Color.DarkRed;
                }
                else if (characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction && characterInfo.CauseOfDeath.Affliction == null)
                {
                    string errorMsg = "Character \"" + characterInfo.Name + "\" had an invalid cause of death (the type of the cause of death was Affliction, but affliction was not specified).";
                    DebugConsole.ThrowError(errorMsg);
                    GameAnalyticsManager.AddErrorEventOnce("RoundSummary:InvalidCauseOfDeath", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                    statusText  = TextManager.Get("CauseOfDeathDescription.Unknown");
                    statusColor = GUI.Style.Red;
                }
                else
                {
                    statusText = characterInfo.CauseOfDeath.Type == CauseOfDeathType.Affliction ?
                                 characterInfo.CauseOfDeath.Affliction.CauseOfDeathDescription :
                                 TextManager.Get("CauseOfDeathDescription." + characterInfo.CauseOfDeath.Type.ToString());
                    statusColor = Color.DarkRed;
                }
            }
            else
            {
                if (character.IsUnconscious)
                {
                    statusText  = TextManager.Get("Unconscious");
                    statusColor = Color.DarkOrange;
                }
                else if (character.Vitality / character.MaxVitality < 0.8f)
                {
                    statusText  = TextManager.Get("Injured");
                    statusColor = Color.DarkOrange;
                }
            }

            GUITextBlock statusBlock = new GUITextBlock(new RectTransform(new Point(statusColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
                                                        ToolBox.LimitString(statusText, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: statusColor);
        }
Пример #15
0
        private void ApplyImpact(float impact, Vector2 direction, Vector2 impactPos, bool applyDamage = true)
        {
            if (impact < MinCollisionImpact)
            {
                return;
            }

            Vector2 impulse = direction * impact * 0.5f;

            impulse = impulse.ClampLength(MaxCollisionImpact);

            if (!MathUtils.IsValid(impulse))
            {
                string errorMsg =
                    "Invalid impulse in SubmarineBody.ApplyImpact: " + impulse +
                    ". Direction: " + direction + ", body position: " + Body.SimPosition + ", impact: " + impact + ".";
                if (GameMain.NetworkMember != null)
                {
                    errorMsg += GameMain.NetworkMember.IsClient ? " Playing as a client." : " Hosting a server.";
                }
                if (GameSettings.VerboseLogging)
                {
                    DebugConsole.ThrowError(errorMsg);
                }
                GameAnalyticsManager.AddErrorEventOnce(
                    "SubmarineBody.ApplyImpact:InvalidImpulse",
                    GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                    errorMsg);
                return;
            }

#if CLIENT
            if (Character.Controlled != null && Character.Controlled.Submarine == submarine && Character.Controlled.KnockbackCooldownTimer <= 0.0f)
            {
                GameMain.GameScreen.Cam.Shake = Math.Max(impact * 10.0f, GameMain.GameScreen.Cam.Shake);
                if (submarine.Info.Type == SubmarineType.Player && !submarine.DockedTo.Any(s => s.Info.Type != SubmarineType.Player))
                {
                    float angularVelocity =
                        (impactPos.X - Body.SimPosition.X) / ConvertUnits.ToSimUnits(submarine.Borders.Width / 2) * impulse.Y
                        - (impactPos.Y - Body.SimPosition.Y) / ConvertUnits.ToSimUnits(submarine.Borders.Height / 2) * impulse.X;
                    GameMain.GameScreen.Cam.AngularVelocity = MathHelper.Clamp(angularVelocity * 0.1f, -1.0f, 1.0f);
                }
            }
#endif

            foreach (Character c in Character.CharacterList)
            {
                if (c.Submarine != submarine)
                {
                    continue;
                }
                if (c.KnockbackCooldownTimer > 0.0f)
                {
                    continue;
                }

                c.KnockbackCooldownTimer = Character.KnockbackCooldown;

                foreach (Limb limb in c.AnimController.Limbs)
                {
                    if (limb.IsSevered)
                    {
                        continue;
                    }
                    limb.body.ApplyLinearImpulse(limb.Mass * impulse, 10.0f);
                }

                bool holdingOntoSomething = false;
                if (c.SelectedConstruction != null)
                {
                    holdingOntoSomething =
                        c.SelectedConstruction.GetComponent <Ladder>() != null ||
                        (c.SelectedConstruction.GetComponent <Controller>()?.LimbPositions.Any() ?? false);
                }

                if (!holdingOntoSomething)
                {
                    c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse, 10.0f);
                    //stun for up to 2 second if the impact equal or higher to the maximum impact
                    if (impact >= MaxCollisionImpact)
                    {
                        c.AddDamage(impactPos, AfflictionPrefab.ImpactDamage.Instantiate(3.0f).ToEnumerable(), stun: Math.Min(impulse.Length() * 0.2f, 2.0f), playSound: true);
                    }
                }
            }

            foreach (Item item in Item.ItemList)
            {
                if (item.Submarine != submarine || item.CurrentHull == null || item.body == null || !item.body.Enabled)
                {
                    continue;
                }

                item.body.ApplyLinearImpulse(item.body.Mass * impulse, 10.0f);
                item.PositionUpdateInterval = 0.0f;
            }

            float dmg = applyDamage ? impact * ImpactDamageMultiplier : 0.0f;
            var   damagedStructures = Explosion.RangedStructureDamage(
                ConvertUnits.ToDisplayUnits(impactPos),
                impact * 50.0f,
                dmg, dmg);

#if CLIENT
            PlayDamageSounds(damagedStructures, impactPos, impact, "StructureBlunt");
#endif
        }
Пример #16
0
        public void CreateSettingsFrame(Tab selectedTab = Tab.Graphics)
        {
            settingsFrame = new GUIFrame(new RectTransform(new Vector2(0.8f, 0.8f), GUI.Canvas, Anchor.Center));

            var settingsFramePadding = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), settingsFrame.RectTransform, Anchor.TopCenter)
            {
                RelativeOffset = new Vector2(0.0f, 0.05f)
            })
            {
                RelativeSpacing = 0.01f, IsHorizontal = true
            };

            /// General tab --------------------------------------------------------------

            var leftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 1.0f), settingsFramePadding.RectTransform, Anchor.TopLeft));

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftPanel.RectTransform),
                             TextManager.Get("Settings"), textAlignment: Alignment.TopLeft, font: GUI.LargeFont);

            var generalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), leftPanel.RectTransform, Anchor.TopLeft));

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), generalLayoutGroup.RectTransform), TextManager.Get("ContentPackages"));
            var contentPackageList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.75f), generalLayoutGroup.RectTransform))
            {
                CanBeFocused     = false,
                ScrollBarVisible = true
            };

            foreach (ContentPackage contentPackage in ContentPackage.List)
            {
                var tickBox = new GUITickBox(new RectTransform(new Point(32, 32), contentPackageList.Content.RectTransform), contentPackage.Name)
                {
                    UserData   = contentPackage,
                    OnSelected = SelectContentPackage,
                    Selected   = SelectedContentPackages.Contains(contentPackage)
                };
                if (!contentPackage.IsCompatible())
                {
                    tickBox.TextColor = Color.Red;
                    tickBox.Enabled   = false;
                    tickBox.ToolTip   = TextManager.Get(contentPackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage")
                                        .Replace("[packagename]", contentPackage.Name)
                                        .Replace("[packageversion]", contentPackage.GameVersion.ToString())
                                        .Replace("[gameversion]", GameMain.Version.ToString());
                }
                else if (contentPackage.CorePackage && !contentPackage.ContainsRequiredCorePackageFiles(out List <ContentType> missingContentTypes))
                {
                    tickBox.TextColor = Color.Red;
                    tickBox.Enabled   = false;
                    tickBox.ToolTip   = TextManager.Get("ContentPackageMissingCoreFiles")
                                        .Replace("[packagename]", contentPackage.Name)
                                        .Replace("[missingfiletypes]", string.Join(", ", missingContentTypes));
                }
            }

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.045f), generalLayoutGroup.RectTransform), TextManager.Get("Language"));
            var languageDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.045f), generalLayoutGroup.RectTransform));

            foreach (string language in TextManager.AvailableLanguages)
            {
                languageDD.AddItem(TextManager.Get("Language." + language), language);
            }
            languageDD.SelectItem(TextManager.Language);
            languageDD.OnSelected = (guiComponent, obj) =>
            {
                string newLanguage = obj as string;
                if (newLanguage == Language)
                {
                    return(true);
                }

                UnsavedSettings = true;
                Language        = newLanguage;

                new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("RestartRequiredLanguage"));

                return(true);
            };

            var rightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.99f - leftPanel.RectTransform.RelativeSize.X, 0.95f),
                                                                  settingsFramePadding.RectTransform, Anchor.TopLeft));

            var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), rightPanel.RectTransform, Anchor.TopCenter), isHorizontal: true);

            var paddedFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 1.0f), rightPanel.RectTransform, Anchor.Center), style: null);


            tabs       = new GUIFrame[Enum.GetValues(typeof(Tab)).Length];
            tabButtons = new GUIButton[tabs.Length];
            foreach (Tab tab in Enum.GetValues(typeof(Tab)))
            {
                tabs[(int)tab] = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.91f), paddedFrame.RectTransform), style: "InnerFrame")
                {
                    UserData = tab
                };
                tabButtons[(int)tab] = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), tabButtonHolder.RectTransform),
                                                     TextManager.Get("SettingsTab." + tab.ToString()), style: "GUITabButton")
                {
                    UserData  = tab,
                    OnClicked = (bt, userdata) => { SelectTab((Tab)userdata); return(true); }
                };
            }

            var buttonArea = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.08f), paddedFrame.RectTransform, Anchor.BottomCenter), style: null);

            /// Graphics tab --------------------------------------------------------------

            var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.TopLeft)
            {
                RelativeOffset = new Vector2(0.025f, 0.02f)
            })
            {
                RelativeSpacing = 0.01f
            };
            var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.TopRight)
            {
                RelativeOffset = new Vector2(0.025f, 0.02f)
            })
            {
                RelativeSpacing = 0.01f
            };

            var supportedDisplayModes = new List <DisplayMode>();

            foreach (DisplayMode mode in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes)
            {
                if (supportedDisplayModes.Any(m => m.Width == mode.Width && m.Height == mode.Height))
                {
                    continue;
                }
#if OSX
                // Monogame currently doesn't support retina displays
                // so we need to disable resolutions above the viewport size.

                // In a bundled .app you just disable HiDPI in the info.plist
                // but that's probably not gonna happen.
                if (mode.Width > GameMain.Instance.GraphicsDevice.DisplayMode.Width || mode.Height > GameMain.Instance.GraphicsDevice.DisplayMode.Height)
                {
                    continue;
                }
#endif
                supportedDisplayModes.Add(mode);
            }

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("Resolution"));
            var resolutionDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), elementCount: supportedDisplayModes.Count)
            {
                OnSelected = SelectResolution,
#if OSX
                ButtonEnabled = GameMain.Config.WindowMode == WindowMode.Windowed
#endif
            };

            foreach (DisplayMode mode in supportedDisplayModes)
            {
                if (mode.Width < MinSupportedResolution.X || mode.Height < MinSupportedResolution.Y)
                {
                    continue;
                }
                resolutionDD.AddItem(mode.Width + "x" + mode.Height, mode);
                if (GraphicsWidth == mode.Width && GraphicsHeight == mode.Height)
                {
                    resolutionDD.SelectItem(mode);
                }
            }

            if (resolutionDD.SelectedItemData == null)
            {
                resolutionDD.SelectItem(GraphicsAdapter.DefaultAdapter.SupportedDisplayModes.Last());
            }

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform), TextManager.Get("DisplayMode"));
            var displayModeDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform));

            displayModeDD.AddItem(TextManager.Get("Fullscreen"), WindowMode.Fullscreen);
            displayModeDD.AddItem(TextManager.Get("Windowed"), WindowMode.Windowed);
#if (!OSX)
            displayModeDD.AddItem(TextManager.Get("BorderlessWindowed"), WindowMode.BorderlessWindowed);
            displayModeDD.SelectItem(GameMain.Config.WindowMode);
#else
            // Fullscreen option will just set itself to borderless on macOS.
            if (GameMain.Config.WindowMode == WindowMode.BorderlessWindowed)
            {
                displayModeDD.SelectItem(WindowMode.Fullscreen);
            }
            else
            {
                displayModeDD.SelectItem(GameMain.Config.WindowMode);
            }
#endif
            displayModeDD.OnSelected = (guiComponent, obj) =>
            {
                UnsavedSettings            = true;
                GameMain.Config.WindowMode = (WindowMode)guiComponent.UserData;
#if OSX
                resolutionDD.ButtonEnabled = GameMain.Config.WindowMode == WindowMode.Windowed;
#endif
                return(true);
            };

            GUITickBox vsyncTickBox = new GUITickBox(new RectTransform(new Point(32, 32), leftColumn.RectTransform), TextManager.Get("EnableVSync"))
            {
                ToolTip    = TextManager.Get("EnableVSyncToolTip"),
                OnSelected = (GUITickBox box) =>
                {
                    VSyncEnabled = box.Selected;
                    GameMain.GraphicsDeviceManager.SynchronizeWithVerticalRetrace = VSyncEnabled;
                    GameMain.GraphicsDeviceManager.ApplyChanges();
                    UnsavedSettings = true;

                    return(true);
                },
                Selected = VSyncEnabled
            };

            GUITextBlock particleLimitText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("ParticleLimit"));
            GUIScrollBar particleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform),
                                                              barSize: 0.1f)
            {
                UserData  = particleLimitText,
                BarScroll = (ParticleLimit - 200) / 1300.0f,
                OnMoved   = (scrollBar, scroll) =>
                {
                    ChangeSliderText(scrollBar, scroll);
                    ParticleLimit = 200 + (int)(scroll * 1300.0f);
                    return(true);
                },
                Step = 0.1f
            };
            particleScrollBar.OnMoved(particleScrollBar, particleScrollBar.BarScroll);

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LosEffect"));
            var losModeDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform));
            losModeDD.AddItem(TextManager.Get("LosModeNone"), LosMode.None);
            losModeDD.AddItem(TextManager.Get("LosModeTransparent"), LosMode.Transparent);
            losModeDD.AddItem(TextManager.Get("LosModeOpaque"), LosMode.Opaque);
            losModeDD.SelectItem(GameMain.Config.LosMode);
            losModeDD.OnSelected = (guiComponent, obj) =>
            {
                UnsavedSettings         = true;
                GameMain.Config.LosMode = (LosMode)guiComponent.UserData;
                //don't allow changing los mode when playing as a client
                if (GameMain.Client == null)
                {
                    GameMain.LightManager.LosMode = GameMain.Config.LosMode;
                }
                return(true);
            };

            GUITextBlock LightText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("LightMapScale"))
            {
                ToolTip = TextManager.Get("LightMapScaleToolTip")
            };
            GUIScrollBar lightScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform),
                                                           barSize: 0.1f)
            {
                UserData  = LightText,
                ToolTip   = TextManager.Get("LightMapScaleToolTip"),
                BarScroll = MathUtils.InverseLerp(0.2f, 1.0f, LightMapScale),
                OnMoved   = (scrollBar, barScroll) =>
                {
                    ChangeSliderText(scrollBar, barScroll);
                    LightMapScale   = MathHelper.Lerp(0.2f, 1.0f, barScroll);
                    UnsavedSettings = true; return(true);
                },
                Step = 0.25f
            };
            lightScrollBar.OnMoved(lightScrollBar, lightScrollBar.BarScroll);

            new GUITickBox(new RectTransform(new Point(32, 32), rightColumn.RectTransform), TextManager.Get("SpecularLighting"))
            {
                ToolTip    = TextManager.Get("SpecularLightingToolTip"),
                Selected   = SpecularityEnabled,
                OnSelected = (tickBox) =>
                {
                    SpecularityEnabled = tickBox.Selected;
                    UnsavedSettings    = true;
                    return(true);
                }
            };

            new GUITickBox(new RectTransform(new Point(32, 32), rightColumn.RectTransform), TextManager.Get("ChromaticAberration"))
            {
                ToolTip    = TextManager.Get("ChromaticAberrationToolTip"),
                Selected   = ChromaticAberrationEnabled,
                OnSelected = (tickBox) =>
                {
                    ChromaticAberrationEnabled = tickBox.Selected;
                    UnsavedSettings            = true;
                    return(true);
                }
            };

            GUITextBlock HUDScaleText      = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("HUDScale"));
            GUIScrollBar HUDScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform),
                                                              barSize: 0.1f)
            {
                UserData  = HUDScaleText,
                BarScroll = (HUDScale - MinHUDScale) / (MaxHUDScale - MinHUDScale),
                OnMoved   = (scrollBar, scroll) =>
                {
                    ChangeSliderText(scrollBar, scroll);
                    HUDScale        = MathHelper.Lerp(MinHUDScale, MaxHUDScale, scroll);
                    UnsavedSettings = true;
                    OnHUDScaleChanged?.Invoke();
                    return(true);
                },
                Step = 0.05f
            };
            HUDScaleScrollBar.OnMoved(HUDScaleScrollBar, HUDScaleScrollBar.BarScroll);

            GUITextBlock inventoryScaleText      = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), TextManager.Get("InventoryScale"));
            GUIScrollBar inventoryScaleScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), rightColumn.RectTransform), barSize: 0.1f)
            {
                UserData  = inventoryScaleText,
                BarScroll = (InventoryScale - MinInventoryScale) / (MaxInventoryScale - MinInventoryScale),
                OnMoved   = (scrollBar, scroll) =>
                {
                    ChangeSliderText(scrollBar, scroll);
                    InventoryScale  = MathHelper.Lerp(MinInventoryScale, MaxInventoryScale, scroll);
                    UnsavedSettings = true;
                    return(true);
                },
                Step = 0.05f
            };
            inventoryScaleScrollBar.OnMoved(inventoryScaleScrollBar, inventoryScaleScrollBar.BarScroll);

            /// Audio tab ----------------------------------------------------------------

            var audioSliders = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), tabs[(int)Tab.Audio].RectTransform, Anchor.TopCenter)
            {
                RelativeOffset = new Vector2(0.0f, 0.02f)
            })
            {
                RelativeSpacing = 0.01f
            };

            GUITextBlock soundVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("SoundVolume"));
            GUIScrollBar soundScrollBar  = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform),
                                                            barSize: 0.05f)
            {
                UserData  = soundVolumeText,
                BarScroll = SoundVolume,
                OnMoved   = (scrollBar, scroll) =>
                {
                    ChangeSliderText(scrollBar, scroll);
                    SoundVolume = scroll;
                    return(true);
                },
                Step = 0.05f
            };
            soundScrollBar.OnMoved(soundScrollBar, soundScrollBar.BarScroll);

            GUITextBlock musicVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("MusicVolume"));
            GUIScrollBar musicScrollBar  = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform),
                                                            barSize: 0.05f)
            {
                UserData  = musicVolumeText,
                BarScroll = MusicVolume,
                OnMoved   = (scrollBar, scroll) =>
                {
                    ChangeSliderText(scrollBar, scroll);
                    MusicVolume = scroll;
                    return(true);
                },
                Step = 0.05f
            };
            musicScrollBar.OnMoved(musicScrollBar, musicScrollBar.BarScroll);

            GUITextBlock voiceChatVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("VoiceChatVolume"));
            GUIScrollBar voiceChatScrollBar  = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform),
                                                                barSize: 0.05f)
            {
                UserData  = voiceChatVolumeText,
                BarScroll = VoiceChatVolume,
                OnMoved   = (scrollBar, scroll) =>
                {
                    ChangeSliderText(scrollBar, scroll);
                    VoiceChatVolume = scroll;
                    return(true);
                },
                Step = 0.05f
            };
            voiceChatScrollBar.OnMoved(voiceChatScrollBar, voiceChatScrollBar.BarScroll);

            GUITickBox muteOnFocusLostBox = new GUITickBox(new RectTransform(new Point(32, 32), audioSliders.RectTransform), TextManager.Get("MuteOnFocusLost"));
            muteOnFocusLostBox.Selected   = MuteOnFocusLost;
            muteOnFocusLostBox.ToolTip    = TextManager.Get("MuteOnFocusLostToolTip");
            muteOnFocusLostBox.OnSelected = (tickBox) =>
            {
                MuteOnFocusLost = tickBox.Selected;
                UnsavedSettings = true;
                return(true);
            };

            new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("VoiceChat"));

            IList <string> deviceNames = Alc.GetString((IntPtr)null, AlcGetStringList.CaptureDeviceSpecifier);
            foreach (string name in deviceNames)
            {
                DebugConsole.NewMessage(name + " " + name.Length.ToString(), Color.Lime);
            }

            if (string.IsNullOrWhiteSpace(VoiceCaptureDevice))
            {
                VoiceCaptureDevice = deviceNames[0];
            }
#if (!OSX)
            var deviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), VoiceCaptureDevice, deviceNames.Count);
            foreach (string name in deviceNames)
            {
                deviceList.AddItem(name, name);
            }
            deviceList.OnSelected = (GUIComponent selected, object obj) =>
            {
                string name = obj as string;
                if (VoiceCaptureDevice == name)
                {
                    return(true);
                }

                VoipCapture.ChangeCaptureDevice(name);
                return(true);
            };
#else
            var suavemente = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("CurrentDevice") + ": " + VoiceCaptureDevice)
            {
                ToolTip       = TextManager.Get("CurrentDeviceToolTip.OSX"),
                TextAlignment = Alignment.CenterX
            };

            new GUIButton(new RectTransform(new Vector2(1.0f, 0.15f), audioSliders.RectTransform), TextManager.Get("RefreshDefaultDevice"))
            {
                ToolTip   = TextManager.Get("RefreshDefaultDeviceToolTip"),
                OnClicked = (bt, userdata) =>
                {
                    deviceNames = Alc.GetString((IntPtr)null, AlcGetStringList.CaptureDeviceSpecifier);
                    if (VoiceCaptureDevice == deviceNames[0])
                    {
                        return(true);
                    }

                    VoipCapture.ChangeCaptureDevice(deviceNames[0]);
                    suavemente.Text = TextManager.Get("CurrentDevice") + ": " + VoiceCaptureDevice;
                    suavemente.Flash(Color.Blue);

                    return(true);
                }
            };
#endif
            //var radioButtonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.12f), audioSliders.RectTransform));

            GUIRadioButtonGroup voiceMode = new GUIRadioButtonGroup();
            for (int i = 0; i < 3; i++)
            {
                string langStr = "VoiceMode." + ((VoiceMode)i).ToString();
                var    tick    = new GUITickBox(new RectTransform(new Point(32, 32), audioSliders.RectTransform), TextManager.Get(langStr))
                {
                    ToolTip = TextManager.Get(langStr + "ToolTip")
                };

                voiceMode.AddRadioButton((VoiceMode)i, tick);
            }

            var micVolumeText   = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("MicrophoneVolume"));
            var micVolumeSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform),
                                                   barSize: 0.05f)
            {
                UserData  = micVolumeText,
                BarScroll = (float)Math.Sqrt(MathUtils.InverseLerp(0.2f, 5.0f, MicrophoneVolume)),
                OnMoved   = (scrollBar, scroll) =>
                {
                    MicrophoneVolume = MathHelper.Lerp(0.2f, 5.0f, scroll * scroll);
                    MicrophoneVolume = (float)Math.Round(MicrophoneVolume, 1);
                    ChangeSliderText(scrollBar, MicrophoneVolume);
                    scrollBar.Step = 0.05f;
                    return(true);
                },
                Step = 0.05f
            };
            micVolumeSlider.OnMoved(micVolumeSlider, micVolumeSlider.BarScroll);


            var extraVoiceSettingsContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), audioSliders.RectTransform, Anchor.BottomCenter), style: null);

            var voiceInputContainer = new GUILayoutGroup(new RectTransform(Vector2.One, extraVoiceSettingsContainer.RectTransform, Anchor.BottomCenter));
            new GUITextBlock(new RectTransform(new Vector2(0.6f, 0.25f), voiceInputContainer.RectTransform), TextManager.Get("InputType.Voice") + ": ");
            var voiceKeyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 0.25f), voiceInputContainer.RectTransform, Anchor.TopRight),
                                             text: keyMapping[(int)InputType.Voice].ToString())
            {
                UserData = InputType.Voice
            };
            voiceKeyBox.OnSelected   += KeyBoxSelected;
            voiceKeyBox.SelectedColor = Color.Gold * 0.3f;

            var          voiceActivityGroup = new GUILayoutGroup(new RectTransform(Vector2.One, extraVoiceSettingsContainer.RectTransform));
            GUITextBlock noiseGateText      = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), voiceActivityGroup.RectTransform), TextManager.Get("NoiseGateThreshold"))
            {
                TextGetter = () =>
                {
                    return(TextManager.Get("NoiseGateThreshold") + " " + ((int)NoiseGateThreshold).ToString() + " dB");
                }
            };
            var dbMeter = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.25f), voiceActivityGroup.RectTransform), 0.0f, Color.Lime);
            dbMeter.ProgressGetter = () =>
            {
                if (VoipCapture.Instance == null)
                {
                    return(0.0f);
                }
                dbMeter.Color = VoipCapture.Instance.LastdB > NoiseGateThreshold ? Color.Lime : Color.Orange; //TODO: i'm a filthy hack
                return(((float)VoipCapture.Instance.LastdB + 100.0f) / 100.0f);
            };
            var noiseGateSlider = new GUIScrollBar(new RectTransform(Vector2.One, dbMeter.RectTransform, Anchor.Center), color: Color.White, barSize: 0.03f);
            noiseGateSlider.Frame.Visible  = false;
            noiseGateSlider.Step           = 0.01f;
            noiseGateSlider.Range          = new Vector2(-100.0f, 0.0f);
            noiseGateSlider.BarScrollValue = NoiseGateThreshold;
            noiseGateSlider.OnMoved        = (GUIScrollBar scrollBar, float barScroll) =>
            {
                NoiseGateThreshold = scrollBar.BarScrollValue;
                UnsavedSettings    = true;
                return(true);
            };

            voiceMode.OnSelect = (GUIRadioButtonGroup rbg, Enum value) =>
            {
                if (rbg.Selected != null && rbg.Selected.Equals(value))
                {
                    return;
                }
                try
                {
                    VoiceMode vMode = (VoiceMode)value;
                    VoiceSetting = vMode;
                    if (vMode == VoiceMode.Activity)
                    {
                        voiceActivityGroup.Visible = true;
                        if (GameMain.Client == null && VoipCapture.Instance == null)
                        {
                            VoipCapture.Create(GameMain.Config.VoiceCaptureDevice);
                            if (VoipCapture.Instance == null)
                            {
                                VoiceSetting = vMode = VoiceMode.Disabled;
                                voiceInputContainer.Visible = false;
                                voiceActivityGroup.Visible  = false;
                                return;
                            }
                        }
                    }
                    else
                    {
                        voiceActivityGroup.Visible = false;
                        if (GameMain.Client == null)
                        {
                            VoipCapture.Instance?.Dispose();
                        }
                    }

                    voiceInputContainer.Visible = (vMode == VoiceMode.PushToTalk);
                    UnsavedSettings             = true;
                }
                catch (Exception e)
                {
                    DebugConsole.ThrowError("Failed to set voice capture mode.", e);
                    GameAnalyticsManager.AddErrorEventOnce("SetVoiceCaptureMode", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, "Failed to set voice capture mode. " + e.Message + "\n" + e.StackTrace);
                    VoiceSetting = VoiceMode.Disabled;
                }
            };
            voiceMode.Selected = VoiceSetting;

            /// Controls tab -------------------------------------------------------------
            var controlsLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), tabs[(int)Tab.Controls].RectTransform, Anchor.TopCenter)
            {
                RelativeOffset = new Vector2(0.0f, 0.02f)
            })
            {
                RelativeSpacing = 0.01f
            };

            GUITextBlock aimAssistText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform), TextManager.Get("AimAssist"))
            {
                ToolTip = TextManager.Get("AimAssistToolTip")
            };
            GUIScrollBar aimAssistSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform),
                                                            barSize: 0.05f)
            {
                UserData  = aimAssistText,
                BarScroll = MathUtils.InverseLerp(0.0f, 5.0f, AimAssistAmount),
                ToolTip   = TextManager.Get("AimAssistToolTip"),
                OnMoved   = (scrollBar, scroll) =>
                {
                    ChangeSliderText(scrollBar, scroll);
                    AimAssistAmount = MathHelper.Lerp(0.0f, 5.0f, scroll);
                    return(true);
                },
                Step = 0.1f
            };
            aimAssistSlider.OnMoved(aimAssistSlider, aimAssistSlider.BarScroll);

            new GUITickBox(new RectTransform(new Point(32, 32), controlsLayoutGroup.RectTransform), TextManager.Get("EnableMouseLook"))
            {
                ToolTip    = TextManager.Get("EnableMouseLookToolTip"),
                Selected   = EnableMouseLook,
                OnSelected = (tickBox) =>
                {
                    EnableMouseLook = tickBox.Selected;
                    UnsavedSettings = true;
                    return(true);
                }
            };

            var inputFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.75f), controlsLayoutGroup.RectTransform), isHorizontal: true)
            {
                Stretch = true, RelativeSpacing = 0.03f
            };

            var inputColumnLeft = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), inputFrame.RectTransform))
            {
                Stretch = true, RelativeSpacing = 0.02f
            };
            var inputColumnRight = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), inputFrame.RectTransform))
            {
                Stretch = true, RelativeSpacing = 0.02f
            };

            var inputNames = Enum.GetValues(typeof(InputType));
            for (int i = 0; i < inputNames.Length; i++)
            {
                var inputContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.06f), (i <= (inputNames.Length / 2.2f) ? inputColumnLeft : inputColumnRight).RectTransform))
                {
                    Stretch = true, IsHorizontal = true, RelativeSpacing = 0.05f, Color = new Color(12, 14, 15, 215)
                };
                new GUITextBlock(new RectTransform(new Vector2(0.3f, 1.0f), inputContainer.RectTransform, Anchor.TopLeft)
                {
                    MinSize = new Point(150, 0)
                },
                                 TextManager.Get("InputType." + ((InputType)i)) + ": ", font: GUI.SmallFont)
                {
                    ForceUpperCase = true
                };
                var keyBox = new GUITextBox(new RectTransform(new Vector2(0.7f, 1.0f), inputContainer.RectTransform),
                                            text: keyMapping[i].ToString(), font: GUI.SmallFont)
                {
                    UserData = i
                };
                keyBox.OnSelected   += KeyBoxSelected;
                keyBox.SelectedColor = Color.Gold * 0.3f;
            }

            var resetControlsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.07f), controlsLayoutGroup.RectTransform), isHorizontal: true)
            {
                RelativeSpacing = 0.02f
            };

            new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), resetControlsHolder.RectTransform), TextManager.Get("SetDefaultBindings"))
            {
                ToolTip   = TextManager.Get("SetDefaultBindingsToolTip"),
                OnClicked = (button, data) =>
                {
                    ResetControls(legacy: false);
                    return(true);
                }
            };

            new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), resetControlsHolder.RectTransform), TextManager.Get("SetLegacyBindings"))
            {
                ToolTip   = TextManager.Get("SetLegacyBindingsToolTip"),
                OnClicked = (button, data) =>
                {
                    ResetControls(legacy: true);
                    return(true);
                }
            };

            //spacing
            new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), generalLayoutGroup.RectTransform), style: null);

            new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonArea.RectTransform, Anchor.BottomLeft),
                          TextManager.Get("Cancel"), style: "GUIButtonLarge")
            {
                IgnoreLayoutGroups = true,
                OnClicked          = (x, y) =>
                {
                    if (UnsavedSettings)
                    {
                        LoadPlayerConfig();
                    }
                    if (Screen.Selected == GameMain.MainMenuScreen)
                    {
                        GameMain.MainMenuScreen.ReturnToMainMenu(null, null);
                    }
                    GUI.SettingsMenuOpen = false;
                    return(true);
                }
            };

            new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonArea.RectTransform, Anchor.BottomCenter),
                          TextManager.Get("Reset"), style: "GUIButtonLarge")
            {
                IgnoreLayoutGroups = true,
                OnClicked          = (button, data) =>
                {
                    // TODO: add a prompt
                    LoadDefaultConfig();
                    CheckBindings(true);
                    RefreshItemMessages();
                    ApplySettings();
                    if (Screen.Selected == GameMain.MainMenuScreen)
                    {
                        GameMain.MainMenuScreen.ResetSettingsFrame(currentTab);
                    }
                    else
                    {
                        ResetSettingsFrame();
                        CreateSettingsFrame(currentTab);
                    }
                    return(true);
                }
            };

            applyButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), buttonArea.RectTransform, Anchor.BottomRight),
                                        TextManager.Get("ApplySettingsButton"), style: "GUIButtonLarge")
            {
                IgnoreLayoutGroups = true,
                Enabled            = false
            };
            applyButton.OnClicked = ApplyClicked;

            UnsavedSettings = false; // Reset unsaved settings to false once the UI has been created
            SelectTab(selectedTab);
        }
Пример #17
0
        public static Body GeneratePolygons(List<VoronoiCell> cells, Level level, out List<Vector2[]> renderTriangles)
        {
            renderTriangles = new List<Vector2[]>();

            List<Vector2> tempVertices = new List<Vector2>();
            List<Vector2> bodyPoints = new List<Vector2>();

            Body cellBody = new Body(GameMain.World)
            {
                SleepingAllowed = false,
                BodyType = BodyType.Static,
                CollisionCategories = Physics.CollisionLevel
            };

            for (int n = cells.Count - 1; n >= 0; n-- )
            {
                VoronoiCell cell = cells[n];
                
                bodyPoints.Clear();
                tempVertices.Clear();
                foreach (GraphEdge ge in cell.Edges)
                {
                    if (Vector2.DistanceSquared(ge.Point1, ge.Point2) < 0.01f) continue;
                    if (!tempVertices.Any(v => Vector2.DistanceSquared(ge.Point1, v) < 1.0f))
                    {
                        tempVertices.Add(ge.Point1);
                        bodyPoints.Add(ge.Point1);
                    }
                    if (!tempVertices.Any(v => Vector2.DistanceSquared(ge.Point2, v) < 1.0f))
                    {
                        tempVertices.Add(ge.Point2);
                        bodyPoints.Add(ge.Point2);
                    }
                }

                if (tempVertices.Count < 3 || bodyPoints.Count < 2)
                {
                    cells.RemoveAt(n);
                    continue;
                }

                renderTriangles.AddRange(MathUtils.TriangulateConvexHull(tempVertices, cell.Center));
                
                if (bodyPoints.Count < 2) continue;

                if (bodyPoints.Count < 3)
                {
                    foreach (Vector2 vertex in tempVertices)
                    {
                        if (bodyPoints.Contains(vertex)) continue;
                        bodyPoints.Add(vertex);
                        break;
                    }
                }

                for (int i = 0; i < bodyPoints.Count; i++)
                {
                    cell.BodyVertices.Add(bodyPoints[i]);
                    bodyPoints[i] = ConvertUnits.ToSimUnits(bodyPoints[i]);
                }
                
                if (cell.CellType == CellType.Empty) continue;

                cellBody.UserData = cell;
                var triangles = MathUtils.TriangulateConvexHull(bodyPoints, ConvertUnits.ToSimUnits(cell.Center));
                
                for (int i = 0; i < triangles.Count; i++)
                {
                    //don't create a triangle if the area of the triangle is too small
                    //(apparently Farseer doesn't like polygons with a very small area, see Shape.ComputeProperties)
                    Vector2 a = triangles[i][0];
                    Vector2 b = triangles[i][1];
                    Vector2 c = triangles[i][2];
                    float area = Math.Abs(a.X * (b.Y - c.Y) + b.X * (c.Y - a.Y) + c.X * (a.Y - b.Y)) / 2.0f;
                    if (area < 1.0f) continue;

                    Vertices bodyVertices = new Vertices(triangles[i]);
                    var newFixture = FixtureFactory.AttachPolygon(bodyVertices, 5.0f, cellBody);
                    newFixture.UserData = cell;

                    if (newFixture.Shape.MassData.Area < FarseerPhysics.Settings.Epsilon)
                    {
                        DebugConsole.ThrowError("Invalid triangle created by CaveGenerator (" + triangles[i][0] + ", " + triangles[i][1] + ", " + triangles[i][2] + ")");
                        GameAnalyticsManager.AddErrorEventOnce(
                            "CaveGenerator.GeneratePolygons:InvalidTriangle",
                            GameAnalyticsSDK.Net.EGAErrorSeverity.Warning,
                            "Invalid triangle created by CaveGenerator (" + triangles[i][0] + ", " + triangles[i][1] + ", " + triangles[i][2] + "). Seed: " + level.Seed);
                    }
                }
                
                cell.Body = cellBody;
            }

            return cellBody;
        }
Пример #18
0
        private static void UpdateWaterAmbience(float ambienceVolume, float deltaTime)
        {
            if (GameMain.SoundManager.Disabled)
            {
                return;
            }

            //how fast the sub is moving, scaled to 0.0 -> 1.0
            float movementSoundVolume = 0.0f;

            float insideSubFactor = 0.0f;

            foreach (Submarine sub in Submarine.Loaded)
            {
                float movementFactor = (sub.Velocity == Vector2.Zero) ? 0.0f : sub.Velocity.Length() / 10.0f;
                movementFactor = MathHelper.Clamp(movementFactor, 0.0f, 1.0f);

                if (Character.Controlled == null || Character.Controlled.Submarine != sub)
                {
                    float dist = Vector2.Distance(GameMain.GameScreen.Cam.WorldViewCenter, sub.WorldPosition);
                    movementFactor /= Math.Max(dist / 1000.0f, 1.0f);
                    insideSubFactor = Math.Max(1.0f / Math.Max(dist / 1000.0f, 1.0f), insideSubFactor);
                }
                else
                {
                    insideSubFactor = 1.0f;
                }

                movementSoundVolume = Math.Max(movementSoundVolume, movementFactor);
                if (!MathUtils.IsValid(movementSoundVolume))
                {
                    string errorMsg = "Failed to update water ambience volume - submarine's movement value invalid (" + movementSoundVolume + ", sub velocity: " + sub.Velocity + ")";
                    DebugConsole.Log(errorMsg);
                    GameAnalyticsManager.AddErrorEventOnce("SoundPlayer.UpdateWaterAmbience:InvalidVolume", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                    movementSoundVolume = 0.0f;
                }
            }

            for (int i = 0; i < 3; i++)
            {
                float volume = 0.0f;
                Sound sound  = null;
                switch (i)
                {
                case 0:
                    volume = ambienceVolume * (1.0f - movementSoundVolume) * insideSubFactor;
                    sound  = waterAmbienceIn;
                    break;

                case 1:
                    volume = ambienceVolume * movementSoundVolume * insideSubFactor;
                    sound  = waterAmbienceMoving;
                    break;

                case 2:
                    volume = 1.0f - insideSubFactor;
                    sound  = waterAmbienceOut;
                    break;
                }

                if ((waterAmbienceChannels[i] == null || !waterAmbienceChannels[i].IsPlaying) && volume > 0.01f)
                {
                    waterAmbienceChannels[i]         = sound.Play(volume, "waterambience");
                    waterAmbienceChannels[i].Looping = true;
                }
                else if (waterAmbienceChannels[i] != null)
                {
                    waterAmbienceChannels[i].Gain += deltaTime * Math.Sign(volume - waterAmbienceChannels[i].Gain);
                    if (waterAmbienceChannels[i].Gain < 0.01f)
                    {
                        waterAmbienceChannels[i].FadeOutAndDispose();
                    }
                }
            }
        }
Пример #19
0
        //constructors & generation ----------------------------------------------------

        public Submarine(string filePath, string hash = "", bool tryLoad = true) : base(null)
        {
            this.filePath = filePath;
            try
            {
                name = System.IO.Path.GetFileNameWithoutExtension(filePath);
            }
            catch (Exception e)
            {
                DebugConsole.ThrowError("Error loading submarine " + filePath + "!", e);
            }

            if (hash != "")
            {
                this.hash = new Md5Hash(hash);
            }

            if (tryLoad)
            {
                XDocument doc = OpenFile(filePath);

                if (doc != null && doc.Root != null)
                {
                    Description = doc.Root.GetAttributeString("description", "");
                    Enum.TryParse(doc.Root.GetAttributeString("tags", ""), out tags);
                    Dimensions                = doc.Root.GetAttributeVector2("dimensions", Vector2.Zero);
                    RecommendedCrewSizeMin    = doc.Root.GetAttributeInt("recommendedcrewsizemin", 0);
                    RecommendedCrewSizeMax    = doc.Root.GetAttributeInt("recommendedcrewsizemax", 0);
                    RecommendedCrewExperience = doc.Root.GetAttributeString("recommendedcrewexperience", "Unknown");
                    string[] contentPackageNames = doc.Root.GetAttributeStringArray("compatiblecontentpackages", new string[0]);
                    foreach (string contentPackageName in contentPackageNames)
                    {
                        CompatibleContentPackages.Add(contentPackageName);
                    }

#if CLIENT
                    string previewImageData = doc.Root.GetAttributeString("previewimage", "");
                    if (!string.IsNullOrEmpty(previewImageData))
                    {
                        try
                        {
                            using (MemoryStream mem = new MemoryStream(Convert.FromBase64String(previewImageData)))
                            {
                                PreviewImage = new Sprite(TextureLoader.FromStream(mem), null, null);
                            }
                        }
                        catch (Exception e)
                        {
                            DebugConsole.ThrowError("Loading the preview image of the submarine \"" + Name + "\" failed. The file may be corrupted.", e);
                            GameAnalyticsManager.AddErrorEventOnce("Submarine..ctor:PreviewImageLoadingFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                                                                   "Loading the preview image of the submarine \"" + Name + "\" failed. The file may be corrupted.");
                            PreviewImage = null;
                        }
                    }
#endif
                }
            }

            DockedTo = new List <Submarine>();

            ID = ushort.MaxValue;
            FreeID();
        }
Пример #20
0
        private void UpdateLocationView(Location location)
        {
            if (location == null)
            {
                string errorMsg = "Failed to update CampaignUI location view (location was null)\n" + Environment.StackTrace;
                DebugConsole.ThrowError(errorMsg);
                GameAnalyticsManager.AddErrorEventOnce("CampaignUI.UpdateLocationView:LocationNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                return;
            }

            if (characterPreviewFrame != null)
            {
                characterPreviewFrame.Parent?.RemoveChild(characterPreviewFrame);
                characterPreviewFrame = null;
            }

            if (characterList != null)
            {
                if (Campaign is SinglePlayerCampaign)
                {
                    var hireableCharacters = location.GetHireableCharacters();
                    foreach (GUIComponent child in characterList.Content.Children.ToList())
                    {
                        if (child.UserData is CharacterInfo character)
                        {
                            if (GameMain.GameSession.CrewManager != null)
                            {
                                if (GameMain.GameSession.CrewManager.GetCharacterInfos().Contains(character))
                                {
                                    continue;
                                }
                            }
                        }
                        else if (child.UserData as string == "mycrew" || child.UserData as string == "hire")
                        {
                            continue;
                        }
                        characterList.RemoveChild(child);
                    }
                    if (!hireableCharacters.Any())
                    {
                        new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.2f), characterList.Content.RectTransform), TextManager.Get("HireUnavailable"), textAlignment: Alignment.Center)
                        {
                            CanBeFocused = false
                        };
                    }
                    else
                    {
                        foreach (CharacterInfo c in hireableCharacters)
                        {
                            var frame = c.CreateCharacterFrame(characterList.Content, c.Name + " (" + c.Job.Name + ")", c);
                            new GUITextBlock(new RectTransform(Vector2.One, frame.RectTransform, Anchor.TopRight), c.Salary.ToString(), textAlignment: Alignment.CenterRight);
                        }
                    }
                }
                characterList.UpdateScrollBarSize();
            }

            RefreshMyItems();

            bool purchaseableItemsFound = false;

            foreach (MapEntityPrefab mapEntityPrefab in MapEntityPrefab.List)
            {
                if (!(mapEntityPrefab is ItemPrefab itemPrefab))
                {
                    continue;
                }

                PriceInfo priceInfo = itemPrefab.GetPrice(Campaign.Map.CurrentLocation);
                if (priceInfo != null)
                {
                    purchaseableItemsFound = true; break;
                }
            }

            //disable store tab if there's nothing to buy
            tabButtons.Find(btn => (Tab)btn.UserData == Tab.Store).Enabled = purchaseableItemsFound;

            if (selectedTab == Tab.Store && !purchaseableItemsFound)
            {
                //switch out from store tab if there's nothing to buy
                SelectTab(Tab.Map);
            }
            else
            {
                //refresh store view
                FillStoreItemList();

                MapEntityCategory?category = null;
                //only select a specific category if the search box is empty
                //(items from all categories are shown when searching)
                if (string.IsNullOrEmpty(searchBox.Text))
                {
                    category = selectedItemCategory;
                }
                FilterStoreItems(category, searchBox.Text);
            }
        }
Пример #21
0
        public static List <MapEntity> Clone(List <MapEntity> entitiesToClone)
        {
            List <MapEntity> clones = new List <MapEntity>();

            foreach (MapEntity e in entitiesToClone)
            {
                Debug.Assert(e != null);
                try
                {
                    clones.Add(e.Clone());
                }
                catch (Exception ex)
                {
                    DebugConsole.ThrowError("Cloning entity \"" + e.Name + "\" failed.", ex);
                    GameAnalyticsManager.AddErrorEventOnce(
                        "MapEntity.Clone:" + e.Name,
                        GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                        "Cloning entity \"" + e.Name + "\" failed (" + ex.Message + ").\n" + ex.StackTrace);
                    return(clones);
                }
                Debug.Assert(clones.Last() != null);
            }

            Debug.Assert(clones.Count == entitiesToClone.Count);

            //clone links between the entities
            for (int i = 0; i < clones.Count; i++)
            {
                if (entitiesToClone[i].linkedTo == null)
                {
                    continue;
                }
                foreach (MapEntity linked in entitiesToClone[i].linkedTo)
                {
                    if (!entitiesToClone.Contains(linked))
                    {
                        continue;
                    }
                    clones[i].linkedTo.Add(clones[entitiesToClone.IndexOf(linked)]);
                }
            }

            //connect clone wires to the clone items and refresh links between doors and gaps
            for (int i = 0; i < clones.Count; i++)
            {
                var cloneItem = clones[i] as Item;
                if (cloneItem == null)
                {
                    continue;
                }

                var door = cloneItem.GetComponent <Door>();
                if (door != null)
                {
                    door.RefreshLinkedGap();
                }

                var cloneWire = cloneItem.GetComponent <Wire>();
                if (cloneWire == null)
                {
                    continue;
                }

                var originalWire = ((Item)entitiesToClone[i]).GetComponent <Wire>();

                cloneWire.SetNodes(originalWire.GetNodes());

                for (int n = 0; n < 2; n++)
                {
                    if (originalWire.Connections[n] == null)
                    {
                        continue;
                    }

                    var connectedItem = originalWire.Connections[n].Item;
                    if (connectedItem == null)
                    {
                        continue;
                    }

                    //index of the item the wire is connected to
                    int itemIndex = entitiesToClone.IndexOf(connectedItem);
                    if (itemIndex < 0)
                    {
                        DebugConsole.ThrowError("Error while cloning wires - item \"" + connectedItem.Name + "\" was not found in entities to clone.");
                        GameAnalyticsManager.AddErrorEventOnce("MapEntity.Clone:ConnectedNotFound" + connectedItem.ID,
                                                               GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                                                               "Error while cloning wires - item \"" + connectedItem.Name + "\" was not found in entities to clone.");
                        continue;
                    }

                    //index of the connection in the connectionpanel of the target item
                    int connectionIndex = connectedItem.Connections.IndexOf(originalWire.Connections[n]);
                    if (connectionIndex < 0)
                    {
                        DebugConsole.ThrowError("Error while cloning wires - connection \"" + originalWire.Connections[n].Name + "\" was not found in connected item \"" + connectedItem.Name + "\".");
                        GameAnalyticsManager.AddErrorEventOnce("MapEntity.Clone:ConnectionNotFound" + connectedItem.ID,
                                                               GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                                                               "Error while cloning wires - connection \"" + originalWire.Connections[n].Name + "\" was not found in connected item \"" + connectedItem.Name + "\".");
                        continue;
                    }

                    (clones[itemIndex] as Item).Connections[connectionIndex].TryAddLink(cloneWire);
                    cloneWire.Connect((clones[itemIndex] as Item).Connections[connectionIndex], false);
                }
            }

            return(clones);
        }
        private static void Place(IEnumerable <Submarine> subs)
        {
            if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient)
            {
                DebugConsole.ThrowError("Clients are not allowed to use AutoItemPlacer.\n" + Environment.StackTrace.CleanupStackTrace());
                return;
            }

            int itemCountApprox         = MapEntityPrefab.List.Count() / 3;
            var containers              = new List <ItemContainer>(70 + 30 * subs.Count());
            var prefabsWithContainer    = new List <ItemPrefab>(itemCountApprox / 3);
            var prefabsWithoutContainer = new List <ItemPrefab>(itemCountApprox);
            var removals = new List <ItemPrefab>();

            foreach (Item item in Item.ItemList)
            {
                if (!subs.Contains(item.Submarine))
                {
                    continue;
                }
                if (item.GetRootInventoryOwner() is Character)
                {
                    continue;
                }
                containers.AddRange(item.GetComponents <ItemContainer>());
            }
            containers.Shuffle(Rand.RandSync.Server);

            foreach (MapEntityPrefab prefab in MapEntityPrefab.List)
            {
                if (!(prefab is ItemPrefab ip))
                {
                    continue;
                }

                if (ip.ConfigElement.Elements().Any(e => string.Equals(e.Name.ToString(), typeof(ItemContainer).Name.ToString(), StringComparison.OrdinalIgnoreCase)))
                {
                    prefabsWithContainer.Add(ip);
                }
                else
                {
                    prefabsWithoutContainer.Add(ip);
                }
            }

            spawnedItems.Clear();
            var validContainers = new Dictionary <ItemContainer, PreferredContainer>();

            prefabsWithContainer.Shuffle(Rand.RandSync.Server);
            // Spawn items that have an ItemContainer component first so we can fill them up with items if needed (oxygen tanks inside the spawned diving masks, etc)
            for (int i = 0; i < prefabsWithContainer.Count; i++)
            {
                var itemPrefab = prefabsWithContainer[i];
                if (itemPrefab == null)
                {
                    continue;
                }
                if (SpawnItems(itemPrefab))
                {
                    removals.Add(itemPrefab);
                }
            }
            // Remove containers that we successfully spawned items into so that they are not counted in in the second pass.
            removals.ForEach(i => prefabsWithContainer.Remove(i));
            // Another pass for items with containers because also they can spawn inside other items (like smg magazine)
            prefabsWithContainer.ForEach(i => SpawnItems(i));
            // Spawn items that don't have containers last
            prefabsWithoutContainer.Shuffle(Rand.RandSync.Server);
            prefabsWithoutContainer.ForEach(i => SpawnItems(i));

            if (OutputDebugInfo)
            {
                var subNames = subs.Select(s => s.Info.Name).ToList();
                DebugConsole.NewMessage($"Automatically placed items in { string.Join(", ", subNames) }:");
                foreach (string itemName in spawnedItems.Select(it => it.Name).Distinct())
                {
                    DebugConsole.NewMessage(" - " + itemName + " x" + spawnedItems.Count(it => it.Name == itemName));
                }
            }

            if (GameMain.GameSession?.Level != null &&
                GameMain.GameSession.Level.Type == LevelData.LevelType.Outpost &&
                GameMain.GameSession.StartLocation?.TakenItems != null)
            {
                foreach (Location.TakenItem takenItem in GameMain.GameSession.StartLocation.TakenItems)
                {
                    var matchingItem = spawnedItems.Find(it => takenItem.Matches(it));
                    if (matchingItem == null)
                    {
                        continue;
                    }
                    var containedItems = spawnedItems.FindAll(it => it.ParentInventory?.Owner == matchingItem);
                    matchingItem.Remove();
                    spawnedItems.Remove(matchingItem);
                    foreach (Item containedItem in containedItems)
                    {
                        containedItem.Remove();
                        spawnedItems.Remove(containedItem);
                    }
                }
            }
#if SERVER
            foreach (Item spawnedItem in spawnedItems)
            {
                Entity.Spawner.CreateNetworkEvent(spawnedItem, remove: false);
            }
#endif
            bool SpawnItems(ItemPrefab itemPrefab)
            {
                if (itemPrefab == null)
                {
                    string errorMsg = "Error in AutoItemPlacer.SpawnItems - itemPrefab was null.\n" + Environment.StackTrace.CleanupStackTrace();
                    DebugConsole.ThrowError(errorMsg);
                    GameAnalyticsManager.AddErrorEventOnce("AutoItemPlacer.SpawnItems:ItemNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                    return(false);
                }
                bool success = false;

                foreach (PreferredContainer preferredContainer in itemPrefab.PreferredContainers)
                {
                    if (preferredContainer.SpawnProbability <= 0.0f || preferredContainer.MaxAmount <= 0)
                    {
                        continue;
                    }
                    validContainers = GetValidContainers(preferredContainer, containers, validContainers, primary: true);
                    if (validContainers.None())
                    {
                        validContainers = GetValidContainers(preferredContainer, containers, validContainers, primary: false);
                    }
                    foreach (var validContainer in validContainers)
                    {
                        if (SpawnItem(itemPrefab, containers, validContainer))
                        {
                            success = true;
                        }
                    }
                }
                return(success);
            }
        }
Пример #23
0
        protected override void Draw(SpriteBatch spriteBatch)
        {
            if (!Visible)
            {
                return;
            }

            if (ProgressGetter != null)
            {
                float newSize = MathHelper.Clamp(ProgressGetter(), 0.0f, 1.0f);
                if (!MathUtils.IsValid(newSize))
                {
                    GameAnalyticsManager.AddErrorEventOnce(
                        "GUIProgressBar.Draw:GetProgress",
                        GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                        "ProgressGetter of a GUIProgressBar (" + ProgressGetter.Target.ToString() + " - " + ProgressGetter.Method.ToString() + ") returned an invalid value (" + newSize + ")\n" + Environment.StackTrace);
                }
                else
                {
                    BarSize = newSize;
                }
            }

            Rectangle sliderRect = new Rectangle(
                frame.Rect.X,
                (int)(frame.Rect.Y + (isHorizontal ? 0 : frame.Rect.Height * (1.0f - barSize))),
                isHorizontal ? (int)((frame.Rect.Width) * barSize) : frame.Rect.Width,
                isHorizontal ? (int)(frame.Rect.Height) : (int)(frame.Rect.Height * barSize));

            frame.Visible  = true;
            slider.Visible = true;
            if (AutoDraw)
            {
                frame.DrawAuto(spriteBatch);
            }
            else
            {
                frame.DrawManually(spriteBatch);
            }

            Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;

            if (BarSize <= 1.0f)
            {
                spriteBatch.End();
                spriteBatch.GraphicsDevice.ScissorRectangle = Rectangle.Intersect(prevScissorRect, sliderRect);
                spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
            }

            Color currColor = GetCurrentColor(state);

            slider.Color = currColor;
            if (AutoDraw)
            {
                slider.DrawAuto(spriteBatch);
            }
            else
            {
                slider.DrawManually(spriteBatch);
            }
            //hide the slider, we've already drawn it manually
            frame.Visible  = false;
            slider.Visible = false;
            if (BarSize <= 1.0f)
            {
                spriteBatch.End();
                spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
                spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
            }
        }
Пример #24
0
        protected virtual void PutItem(Item item, int i, Character user, bool removeItem = true, bool createNetworkEvent = true)
        {
            if (i < 0 || i >= slots.Length)
            {
                string errorMsg = "Inventory.PutItem failed: index was out of range(" + i + ").\n" + Environment.StackTrace.CleanupStackTrace();
                GameAnalyticsManager.AddErrorEventOnce("Inventory.PutItem:IndexOutOfRange", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                return;
            }

            if (Owner == null)
            {
                return;
            }

            Inventory prevInventory      = item.ParentInventory;
            Inventory prevOwnerInventory = item.FindParentInventory(inv => inv is CharacterInventory);

            if (createNetworkEvent)
            {
                CreateNetworkEvent();
                //also delay syncing the inventory the item was inside
                if (prevInventory != null && prevInventory != this)
                {
                    prevInventory.syncItemsDelay = 1.0f;
                }
            }

            if (removeItem)
            {
                item.Drop(user);
                if (item.ParentInventory != null)
                {
                    item.ParentInventory.RemoveItem(item);
                }
            }

            slots[i].Add(item);
            item.ParentInventory = this;

#if CLIENT
            if (visualSlots != null)
            {
                visualSlots[i]?.ShowBorderHighlight(Color.White, 0.1f, 0.4f);
            }
#endif

            if (item.body != null)
            {
                item.body.Enabled  = false;
                item.body.BodyType = FarseerPhysics.BodyType.Dynamic;
            }

#if SERVER
            if (prevOwnerInventory is CharacterInventory characterInventory && characterInventory != this && Owner == user)
            {
                var client = GameMain.Server?.ConnectedClients?.Find(cl => cl.Character == user);
                GameMain.Server?.KarmaManager.OnItemTakenFromPlayer(characterInventory, client, item);
            }
#endif
            if (this is CharacterInventory)
            {
                if (prevInventory != this && prevOwnerInventory != this)
                {
                    HumanAIController.ItemTaken(item, user);
                }
            }
            else
            {
                if (item.FindParentInventory(inv => inv is CharacterInventory) is CharacterInventory currentInventory)
                {
                    if (currentInventory != prevInventory)
                    {
                        HumanAIController.ItemTaken(item, user);
                    }
                }
            }
        }
Пример #25
0
        private void HandleLimbCollision(Impact collision, Limb limb)
        {
            if (limb?.body?.FarseerBody == null || limb.character == null)
            {
                return;
            }

            if (limb.Mass > MinImpactLimbMass)
            {
                Vector2 normal =
                    Vector2.DistanceSquared(Body.SimPosition, limb.SimPosition) < 0.0001f ?
                    Vector2.UnitY :
                    Vector2.Normalize(Body.SimPosition - limb.SimPosition);

                float impact = Math.Min(Vector2.Dot(collision.Velocity, -normal), 50.0f) * Math.Min(limb.Mass / 100.0f, 1);

                ApplyImpact(impact, -normal, collision.ImpactPos, applyDamage: false);
                foreach (Submarine dockedSub in submarine.DockedTo)
                {
                    dockedSub.SubBody.ApplyImpact(impact, -normal, collision.ImpactPos, applyDamage: false);
                }
            }

            //find all contacts between the limb and level walls
            List <Contact> levelContacts = new List <Contact>();
            ContactEdge    contactEdge   = limb.body.FarseerBody.ContactList;

            while (contactEdge?.Contact != null)
            {
                if (contactEdge.Contact.Enabled &&
                    contactEdge.Contact.IsTouching &&
                    contactEdge.Other?.UserData is VoronoiCell)
                {
                    levelContacts.Add(contactEdge.Contact);
                }
                contactEdge = contactEdge.Next;
            }

            if (levelContacts.Count == 0)
            {
                return;
            }

            //if the limb is in contact with the level, apply an artifical impact to prevent the sub from bouncing on top of it
            //not a very realistic way to handle the collisions (makes it seem as if the characters were made of reinforced concrete),
            //but more realistic than bouncing and prevents using characters as "bumpers" that prevent all collision damage
            Vector2 avgContactNormal = Vector2.Zero;

            foreach (Contact levelContact in levelContacts)
            {
                levelContact.GetWorldManifold(out Vector2 contactNormal, out FixedArray2 <Vector2> temp);

                //if the contact normal is pointing from the limb towards the level cell it's touching, flip the normal
                VoronoiCell cell = levelContact.FixtureB.UserData is VoronoiCell ?
                                   ((VoronoiCell)levelContact.FixtureB.UserData) : ((VoronoiCell)levelContact.FixtureA.UserData);

                var cellDiff = ConvertUnits.ToDisplayUnits(limb.body.SimPosition) - cell.Center;
                if (Vector2.Dot(contactNormal, cellDiff) < 0)
                {
                    contactNormal = -contactNormal;
                }

                avgContactNormal += contactNormal;

                //apply impacts at the positions where this sub is touching the limb
                ApplyImpact((Vector2.Dot(-collision.Velocity, contactNormal) / 2.0f) / levelContacts.Count, contactNormal, collision.ImpactPos, applyDamage: false);
            }
            avgContactNormal /= levelContacts.Count;

            float contactDot = Vector2.Dot(Body.LinearVelocity, -avgContactNormal);

            if (contactDot > 0.001f)
            {
                Vector2 velChange = Vector2.Normalize(Body.LinearVelocity) * contactDot;
                if (!MathUtils.IsValid(velChange))
                {
                    GameAnalyticsManager.AddErrorEventOnce(
                        "SubmarineBody.HandleLimbCollision:" + submarine.ID,
                        GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                        "Invalid velocity change in SubmarineBody.HandleLimbCollision (submarine velocity: " + Body.LinearVelocity
                        + ", avgContactNormal: " + avgContactNormal
                        + ", contactDot: " + contactDot
                        + ", velChange: " + velChange + ")");
                    return;
                }

                Body.LinearVelocity -= velChange;

                float damageAmount = contactDot * Body.Mass / limb.character.Mass;
                limb.character.LastDamageSource = submarine;
                limb.character.DamageLimb(ConvertUnits.ToDisplayUnits(collision.ImpactPos), limb,
                                          AfflictionPrefab.ImpactDamage.Instantiate(damageAmount).ToEnumerable(), 0.0f, true, 0.0f);

                if (limb.character.IsDead)
                {
                    foreach (LimbJoint limbJoint in limb.character.AnimController.LimbJoints)
                    {
                        if (limbJoint.IsSevered || (limbJoint.LimbA != limb && limbJoint.LimbB != limb))
                        {
                            continue;
                        }
                        limb.character.AnimController.SeverLimbJoint(limbJoint);
                    }
                }
            }
        }
Пример #26
0
        public void Save(string filePath)
        {
            UnsavedSettings = false;

            XDocument doc = new XDocument();

            if (doc.Root == null)
            {
                doc.Add(new XElement("config"));
            }

            doc.Root.Add(
                new XAttribute("masterserverurl", MasterServerUrl),
                new XAttribute("autocheckupdates", AutoCheckUpdates),
                new XAttribute("musicvolume", musicVolume),
                new XAttribute("soundvolume", soundVolume),
                new XAttribute("verboselogging", VerboseLogging),
                new XAttribute("savedebugconsolelogs", SaveDebugConsoleLogs),
                new XAttribute("enablesplashscreen", EnableSplashScreen));

            if (!ShowUserStatisticsPrompt)
            {
                doc.Root.Add(new XAttribute("senduserstatistics", sendUserStatistics));
            }

            if (WasGameUpdated)
            {
                doc.Root.Add(new XAttribute("wasgameupdated", true));
            }

            XElement gMode = doc.Root.Element("graphicsmode");

            if (gMode == null)
            {
                gMode = new XElement("graphicsmode");
                doc.Root.Add(gMode);
            }

            if (GraphicsWidth == 0 || GraphicsHeight == 0)
            {
                gMode.ReplaceAttributes(new XAttribute("displaymode", windowMode));
            }
            else
            {
                gMode.ReplaceAttributes(
                    new XAttribute("width", GraphicsWidth),
                    new XAttribute("height", GraphicsHeight),
                    new XAttribute("vsync", VSyncEnabled),
                    new XAttribute("displaymode", windowMode));
            }


            if (SelectedContentPackage != null)
            {
                doc.Root.Add(new XElement("contentpackage",
                                          new XAttribute("path", SelectedContentPackage.Path)));
            }

            var keyMappingElement = new XElement("keymapping");

            doc.Root.Add(keyMappingElement);
            for (int i = 0; i < keyMapping.Length; i++)
            {
                if (keyMapping[i].MouseButton == null)
                {
                    keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].Key));
                }
                else
                {
                    keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].MouseButton));
                }
            }

            var gameplay       = new XElement("gameplay");
            var jobPreferences = new XElement("jobpreferences");

            foreach (string jobName in JobNamePreferences)
            {
                jobPreferences.Add(new XElement("job", new XAttribute("name", jobName)));
            }
            gameplay.Add(jobPreferences);
            doc.Root.Add(gameplay);

            var playerElement = new XElement("player",
                                             new XAttribute("name", defaultPlayerName ?? ""),
                                             new XAttribute("headindex", characterHeadIndex),
                                             new XAttribute("gender", characterGender));

            doc.Root.Add(playerElement);

            try
            {
                doc.Save(filePath);
            }
            catch (Exception e)
            {
                DebugConsole.ThrowError("Saving game settings failed.", e);
                GameAnalyticsManager.AddErrorEventOnce("GameSettings.Save:SaveFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                                                       "Saving game settings failed.\n" + e.Message + "\n" + e.StackTrace);
            }
        }
        protected override void Draw(SpriteBatch spriteBatch)
        {
            if (!Visible)
            {
                return;
            }

            if (ProgressGetter != null)
            {
                float newSize = MathHelper.Clamp(ProgressGetter(), 0.0f, 1.0f);
                if (!MathUtils.IsValid(newSize))
                {
                    GameAnalyticsManager.AddErrorEventOnce(
                        "GUIProgressBar.Draw:GetProgress",
                        GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                        "ProgressGetter of a GUIProgressBar (" + ProgressGetter.Target.ToString() + " - " + ProgressGetter.Method.ToString() + ") returned an invalid value (" + newSize + ")\n" + Environment.StackTrace.CleanupStackTrace());
                }
                else
                {
                    BarSize = newSize;
                }
            }

            var sliderRect = GetSliderRect(barSize);

            slider.RectTransform.AbsoluteOffset = new Point((int)style.Padding.X, (int)style.Padding.Y);
            slider.RectTransform.MaxSize        = new Point(
                (int)(Rect.Width - style.Padding.X + style.Padding.Z),
                (int)(Rect.Height - style.Padding.Y + style.Padding.W));
            frame.Visible  = showFrame;
            slider.Visible = BarSize > 0.0f;

            if (showFrame)
            {
                if (AutoDraw)
                {
                    frame.DrawAuto(spriteBatch);
                }
                else
                {
                    frame.DrawManually(spriteBatch);
                }
            }

            Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;

            if (BarSize <= 1.0f)
            {
                spriteBatch.End();
                spriteBatch.GraphicsDevice.ScissorRectangle = Rectangle.Intersect(prevScissorRect, sliderRect);
                spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
            }

            Color currColor = GetColor(State);

            slider.Color = currColor;
            if (AutoDraw)
            {
                slider.DrawAuto(spriteBatch);
            }
            else
            {
                slider.DrawManually(spriteBatch);
            }
            //hide the slider, we've already drawn it manually
            frame.Visible  = false;
            slider.Visible = false;
            if (BarSize <= 1.0f)
            {
                spriteBatch.End();
                spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
                spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
            }
        }
Пример #28
0
        private void ApplyImpact(float impact, Vector2 direction, Vector2 impactPos, bool applyDamage = true)
        {
            if (impact < MinCollisionImpact)
            {
                return;
            }

            Vector2 impulse = direction * impact * 0.5f;

            impulse = impulse.ClampLength(MaxCollisionImpact);

            if (!MathUtils.IsValid(impulse))
            {
                string errorMsg =
                    "Invalid impulse in SubmarineBody.ApplyImpact: " + impulse +
                    ". Direction: " + direction + ", body position: " + Body.SimPosition + ", impact: " + impact + ".";
                if (GameMain.NetworkMember != null)
                {
                    errorMsg += GameMain.NetworkMember.IsClient ? " Playing as a client." : " Hosting a server.";
                }
                if (GameSettings.VerboseLogging)
                {
                    DebugConsole.ThrowError(errorMsg);
                }
                GameAnalyticsManager.AddErrorEventOnce(
                    "SubmarineBody.ApplyImpact:InvalidImpulse",
                    GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                    errorMsg);
                return;
            }

#if CLIENT
            if (Character.Controlled != null && Character.Controlled.Submarine == submarine)
            {
                GameMain.GameScreen.Cam.Shake = impact * 2.0f;
                if (submarine.Info.Type == SubmarineType.Player && !submarine.DockedTo.Any(s => s.Info.Type != SubmarineType.Player))
                {
                    float angularVelocity =
                        (impactPos.X - Body.SimPosition.X) / ConvertUnits.ToSimUnits(submarine.Borders.Width / 2) * impulse.Y
                        - (impactPos.Y - Body.SimPosition.Y) / ConvertUnits.ToSimUnits(submarine.Borders.Height / 2) * impulse.X;
                    GameMain.GameScreen.Cam.AngularVelocity = MathHelper.Clamp(angularVelocity * 0.1f, -1.0f, 1.0f);
                }
            }
#endif

            foreach (Character c in Character.CharacterList)
            {
                if (c.Submarine != submarine)
                {
                    continue;
                }

                foreach (Limb limb in c.AnimController.Limbs)
                {
                    if (limb.IsSevered)
                    {
                        continue;
                    }
                    limb.body.ApplyLinearImpulse(limb.Mass * impulse, 10.0f);
                }
                c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse, 10.0f);

                bool holdingOntoSomething = false;
                if (c.SelectedConstruction != null)
                {
                    var controller = c.SelectedConstruction.GetComponent <Items.Components.Controller>();
                    holdingOntoSomething = controller != null && controller.LimbPositions.Any();
                }

                //stun for up to 1 second if the impact equal or higher to the maximum impact
                if (impact >= MaxCollisionImpact && !holdingOntoSomething)
                {
                    c.SetStun(Math.Min(impulse.Length() * 0.2f, 1.0f));
                }
            }

            foreach (Item item in Item.ItemList)
            {
                if (item.Submarine != submarine || item.CurrentHull == null ||
                    item.body == null || !item.body.Enabled)
                {
                    continue;
                }

                item.body.ApplyLinearImpulse(item.body.Mass * impulse, 10.0f);
            }

            var damagedStructures = Explosion.RangedStructureDamage(
                ConvertUnits.ToDisplayUnits(impactPos),
                impact * 50.0f,
                applyDamage ? impact * ImpactDamageMultiplier : 0.0f);

#if CLIENT
            //play a damage sound for the structure that took the most damage
            float     maxDamage          = 0.0f;
            Structure maxDamageStructure = null;
            foreach (KeyValuePair <Structure, float> structureDamage in damagedStructures)
            {
                if (maxDamageStructure == null || structureDamage.Value > maxDamage)
                {
                    maxDamage          = structureDamage.Value;
                    maxDamageStructure = structureDamage.Key;
                }
            }

            if (maxDamageStructure != null)
            {
                SoundPlayer.PlayDamageSound(
                    "StructureBlunt",
                    impact * 10.0f,
                    ConvertUnits.ToDisplayUnits(impactPos),
                    MathHelper.Lerp(2000.0f, 10000.0f, (impact - MinCollisionImpact) / 2.0f),
                    maxDamageStructure.Tags);
            }
#endif
        }
Пример #29
0
        public static void RemoveAll()
        {
            List <Entity> list = new List <Entity>(dictionary.Values);

            foreach (Entity e in list)
            {
                try
                {
                    e.Remove();
                }
                catch (Exception exception)
                {
                    DebugConsole.ThrowError("Error while removing entity \"" + e.ToString() + "\"", exception);
                    GameAnalyticsManager.AddErrorEventOnce(
                        "Entity.RemoveAll:Exception" + e.ToString(),
                        GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                        "Error while removing entity \"" + e.ToString() + " (" + exception.Message + ")\n" + exception.StackTrace);
                }
            }
            StringBuilder errorMsg = new StringBuilder();

            if (dictionary.Count > 0)
            {
                errorMsg.AppendLine("Some entities were not removed in Entity.RemoveAll:");
                foreach (Entity e in dictionary.Values)
                {
                    errorMsg.AppendLine(" - " + e.ToString() + "(ID " + e.id + ")");
                }
            }
            if (Item.ItemList.Count > 0)
            {
                errorMsg.AppendLine("Some items were not removed in Entity.RemoveAll:");
                foreach (Item item in Item.ItemList)
                {
                    errorMsg.AppendLine(" - " + item.Name + "(ID " + item.id + ")");
                }

                var items = new List <Item>(Item.ItemList);
                foreach (Item item in items)
                {
                    try
                    {
                        item.Remove();
                    }
                    catch (Exception exception)
                    {
                        DebugConsole.ThrowError("Error while removing item \"" + item.ToString() + "\"", exception);
                    }
                }
                Item.ItemList.Clear();
            }
            if (Character.CharacterList.Count > 0)
            {
                errorMsg.AppendLine("Some characters were not removed in Entity.RemoveAll:");
                foreach (Character character in Character.CharacterList)
                {
                    errorMsg.AppendLine(" - " + character.Name + "(ID " + character.id + ")");
                }

                var characters = new List <Character>(Character.CharacterList);
                foreach (Character character in characters)
                {
                    try
                    {
                        character.Remove();
                    }
                    catch (Exception exception)
                    {
                        DebugConsole.ThrowError("Error while removing character \"" + character.ToString() + "\"", exception);
                    }
                }
                Character.CharacterList.Clear();
            }

            if (!string.IsNullOrEmpty(errorMsg.ToString()))
            {
                foreach (string errorLine in errorMsg.ToString().Split('\n'))
                {
                    DebugConsole.ThrowError(errorLine);
                }
                GameAnalyticsManager.AddErrorEventOnce("Entity.RemoveAll", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg.ToString());
            }

            dictionary.Clear();
        }
Пример #30
0
        public override bool TryPutItem(Item item, int index, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true)
        {
            if (index < 0 || index >= Items.Length)
            {
                string errorMsg = "CharacterInventory.TryPutItem failed: index was out of range(" + index + ").\n" + Environment.StackTrace;
                GameAnalyticsManager.AddErrorEventOnce("CharacterInventory.TryPutItem:IndexOutOfRange", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                return(false);
            }

            //there's already an item in the slot
            if (Items[index] != null)
            {
                if (Items[index] == item)
                {
                    return(false);
                }

                return(base.TryPutItem(item, index, allowSwapping, allowCombine, user, createNetworkEvent));
            }

            if (SlotTypes[index] == InvSlotType.Any)
            {
                if (!item.AllowedSlots.Contains(InvSlotType.Any))
                {
                    return(false);
                }
                if (Items[index] != null)
                {
                    return(Items[index] == item);
                }

                PutItem(item, index, user, true, createNetworkEvent);
                return(true);
            }

            InvSlotType placeToSlots = InvSlotType.None;

            bool slotsFree = true;
            List <InvSlotType> allowedSlots = item.AllowedSlots;

            foreach (InvSlotType allowedSlot in allowedSlots)
            {
                if (!allowedSlot.HasFlag(SlotTypes[index]))
                {
                    continue;
                }

                for (int i = 0; i < capacity; i++)
                {
                    if (allowedSlot.HasFlag(SlotTypes[i]) && Items[i] != null && Items[i] != item)
                    {
                        slotsFree = false;
                        break;
                    }

                    placeToSlots = allowedSlot;
                }
            }

            if (!slotsFree)
            {
                return(false);
            }

            return(TryPutItem(item, user, new List <InvSlotType>()
            {
                placeToSlots
            }, createNetworkEvent));
        }