Example #1
0
        partial void ApplyProjSpecific(float deltaTime, Entity entity, List <ISerializableEntity> targets, Hull hull, Vector2 worldPosition)
        {
            if (entity == null)
            {
                return;
            }

            if (sounds.Count > 0)
            {
                if (soundChannel == null || !soundChannel.IsPlaying)
                {
                    if (soundSelectionMode == SoundSelectionMode.All)
                    {
                        foreach (RoundSound sound in sounds)
                        {
                            if (sound?.Sound == null)
                            {
                                string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
                                GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                                return;
                            }
                            soundChannel = SoundPlayer.PlaySound(sound.Sound, worldPosition, sound.Volume, sound.Range, hull);
                            if (soundChannel != null)
                            {
                                soundChannel.Looping = loopSound;
                            }
                        }
                    }
                    else
                    {
                        int selectedSoundIndex = 0;
                        if (soundSelectionMode == SoundSelectionMode.ItemSpecific && entity is Item item)
                        {
                            selectedSoundIndex = item.ID % sounds.Count;
                        }
                        else if (soundSelectionMode == SoundSelectionMode.CharacterSpecific && entity is Character user)
                        {
                            selectedSoundIndex = user.ID % sounds.Count;
                        }
                        else
                        {
                            selectedSoundIndex = Rand.Int(sounds.Count);
                        }
                        var selectedSound = sounds[selectedSoundIndex];
                        if (selectedSound?.Sound == null)
                        {
                            string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace;
                            GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                            return;
                        }
                        soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, worldPosition, selectedSound.Volume, selectedSound.Range, hull);
                        if (soundChannel != null)
                        {
                            soundChannel.Looping = loopSound;
                        }
                    }
                }

                if (soundChannel != null && soundChannel.Looping)
                {
                    ActiveLoopingSounds.Add(this);
                    soundEmitter  = entity;
                    loopStartTime = Timing.TotalTime;
                }
            }

            foreach (ParticleEmitter emitter in particleEmitters)
            {
                float angle = 0.0f;
                if (emitter.Prefab.CopyEntityAngle)
                {
                    if (entity is Item item && item.body != null)
                    {
                        angle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
                    }
                }

                emitter.Emit(deltaTime, worldPosition, hull, angle);
            }
        }
Example #2
0
        partial void ApplyProjSpecific(float deltaTime, Entity entity, IEnumerable <ISerializableEntity> targets, Hull hull, Vector2 worldPosition, bool playSound)
        {
            if (entity == null)
            {
                return;
            }

            if (sounds.Count > 0 && playSound)
            {
                if (soundChannel == null || !soundChannel.IsPlaying)
                {
                    if (soundSelectionMode == SoundSelectionMode.All)
                    {
                        foreach (RoundSound sound in sounds)
                        {
                            if (sound?.Sound == null)
                            {
                                string errorMsg = $"Error in StatusEffect.ApplyProjSpecific1 (sound \"{sound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
                                GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull1" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                                return;
                            }
                            soundChannel = SoundPlayer.PlaySound(sound.Sound, worldPosition, sound.Volume, sound.Range, hullGuess: hull);
                            if (soundChannel != null)
                            {
                                soundChannel.Looping = loopSound;
                            }
                        }
                    }
                    else
                    {
                        int selectedSoundIndex;
                        if (soundSelectionMode == SoundSelectionMode.ItemSpecific && entity is Item item)
                        {
                            selectedSoundIndex = item.ID % sounds.Count;
                        }
                        else if (soundSelectionMode == SoundSelectionMode.CharacterSpecific && entity is Character user)
                        {
                            selectedSoundIndex = user.ID % sounds.Count;
                        }
                        else
                        {
                            selectedSoundIndex = Rand.Int(sounds.Count);
                        }
                        var selectedSound = sounds[selectedSoundIndex];
                        if (selectedSound?.Sound == null)
                        {
                            string errorMsg = $"Error in StatusEffect.ApplyProjSpecific2 (sound \"{selectedSound?.Filename ?? "unknown"}\" was null)\n" + Environment.StackTrace.CleanupStackTrace();
                            GameAnalyticsManager.AddErrorEventOnce("StatusEffect.ApplyProjSpecific:SoundNull2" + Environment.StackTrace.CleanupStackTrace(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                            return;
                        }
                        if (selectedSound.Sound.Disposed)
                        {
                            Submarine.ReloadRoundSound(selectedSound);
                        }
                        soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, worldPosition, selectedSound.Volume, selectedSound.Range, hullGuess: hull);
                        if (soundChannel != null)
                        {
                            soundChannel.Looping = loopSound;
                        }
                    }
                }
                else
                {
                    soundChannel.Position = new Vector3(worldPosition, 0.0f);
                }

                if (soundChannel != null && soundChannel.Looping)
                {
                    ActiveLoopingSounds.Add(this);
                    soundEmitter  = entity;
                    loopStartTime = Timing.TotalTime;
                }
            }

            foreach (ParticleEmitter emitter in particleEmitters)
            {
                float angle            = 0.0f;
                float particleRotation = 0.0f;
                if (emitter.Prefab.CopyEntityAngle)
                {
                    Limb targetLimb = null;
                    if (entity is Item item && item.body != null)
                    {
                        angle            = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
                        particleRotation = -item.body.Rotation;
                        if (item.body.Dir < 0.0f)
                        {
                            particleRotation += MathHelper.Pi;
                        }
                    }
                    else if (entity is Character c && targetLimbs?.FirstOrDefault(l => l != LimbType.None) is LimbType l)
                    {
                        targetLimb = c.AnimController.GetLimb(l);
                    }
Example #3
0
        private IEnumerable <object> Load(bool isSeparateThread)
        {
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime);
            }

            while (TitleScreen.WaitForLanguageSelection)
            {
                yield return(CoroutineStatus.Running);
            }

            SoundManager = new Sounds.SoundManager();
            SoundManager.SetCategoryGainMultiplier("default", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("ui", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("waterambience", Config.SoundVolume, 0);
            SoundManager.SetCategoryGainMultiplier("music", Config.MusicVolume, 0);
            SoundManager.SetCategoryGainMultiplier("voip", Math.Min(Config.VoiceChatVolume, 1.0f), 0);

            if (Config.EnableSplashScreen && !ConsoleArguments.Contains("-skipintro"))
            {
                var   pendingSplashScreens = TitleScreen.PendingSplashScreens;
                float baseVolume           = MathHelper.Clamp(Config.SoundVolume * 2.0f, 0.0f, 1.0f);
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_UTG.webm", baseVolume * 0.5f));
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_FF.webm", baseVolume));
                pendingSplashScreens?.Enqueue(new LoadingScreen.PendingSplashScreen("Content/SplashScreens/Splash_Daedalic.webm", baseVolume * 0.1f));
            }

            //if not loading in a separate thread, wait for the splash screens to finish before continuing the loading
            //otherwise the videos will look extremely choppy
            if (!isSeparateThread)
            {
                while (TitleScreen.PlayingSplashScreen || TitleScreen.PendingSplashScreens.Count > 0)
                {
                    yield return(CoroutineStatus.Running);
                }
            }

            GUI.Init(Window, Config.SelectedContentPackages, GraphicsDevice);
            DebugConsole.Init();

            if (Config.AutoUpdateWorkshopItems)
            {
                bool waitingForWorkshopUpdates = true;
                bool result = false;
                TaskPool.Add(SteamManager.AutoUpdateWorkshopItemsAsync(), (task) =>
                {
                    result = task.Result;
                    waitingForWorkshopUpdates = false;
                });

                while (waitingForWorkshopUpdates)
                {
                    yield return(CoroutineStatus.Running);
                }

                if (result)
                {
                    CrossThread.RequestExecutionOnMainThread(() =>
                    {
                        ContentPackage.LoadAll();
                        Config.ReloadContentPackages();
                    });
                }
            }


            if (SelectedPackages.None())
            {
                DebugConsole.Log("No content packages selected");
            }
            else
            {
                DebugConsole.Log("Selected content packages: " + string.Join(", ", SelectedPackages.Select(cp => cp.Name)));
            }

#if DEBUG
            GameSettings.ShowUserStatisticsPrompt = false;
            GameSettings.SendUserStatistics       = false;
#endif

            InitUserStats();

            yield return(CoroutineStatus.Running);

            Debug.WriteLine("sounds");

            int i = 0;
            foreach (object crObj in SoundPlayer.Init())
            {
                CoroutineStatus status = (CoroutineStatus)crObj;
                if (status == CoroutineStatus.Success)
                {
                    break;
                }

                i++;
                TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ?
                                        1.0f :
                                        Math.Min(40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 40.0f);

                yield return(CoroutineStatus.Running);
            }

            TitleScreen.LoadState = 40.0f;
            yield return(CoroutineStatus.Running);

            LightManager = new Lights.LightManager(base.GraphicsDevice, Content);

            TitleScreen.LoadState = 41.0f;
            yield return(CoroutineStatus.Running);

            GUI.LoadContent();
            TitleScreen.LoadState = 42.0f;

            yield return(CoroutineStatus.Running);

            CharacterPrefab.LoadAll();
            MissionPrefab.Init();
            TraitorMissionPrefab.Init();
            MapEntityPrefab.Init();
            Tutorials.Tutorial.Init();
            MapGenerationParams.Init();
            LevelGenerationParams.LoadPresets();
            WreckAIConfig.LoadAll();
            ScriptedEventSet.LoadPrefabs();
            AfflictionPrefab.LoadAll(GetFilesOfType(ContentType.Afflictions));
            SkillSettings.Load(GetFilesOfType(ContentType.SkillSettings));
            Order.Init();
            EventManagerSettings.Init();
            TitleScreen.LoadState = 50.0f;
            yield return(CoroutineStatus.Running);

            StructurePrefab.LoadAll(GetFilesOfType(ContentType.Structure));
            TitleScreen.LoadState = 53.0f;
            yield return(CoroutineStatus.Running);

            ItemPrefab.LoadAll(GetFilesOfType(ContentType.Item));
            TitleScreen.LoadState = 55.0f;
            yield return(CoroutineStatus.Running);

            JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
            CorpsePrefab.LoadAll(GetFilesOfType(ContentType.Corpses));

            NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations));

            ItemAssemblyPrefab.LoadAll();
            TitleScreen.LoadState = 60.0f;
            yield return(CoroutineStatus.Running);

            GameModePreset.Init();

            SubmarineInfo.RefreshSavedSubs();

            TitleScreen.LoadState = 65.0f;
            yield return(CoroutineStatus.Running);

            GameScreen = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content);

            TitleScreen.LoadState = 68.0f;
            yield return(CoroutineStatus.Running);

            MainMenuScreen   = new MainMenuScreen(this);
            LobbyScreen      = new LobbyScreen();
            ServerListScreen = new ServerListScreen();

            TitleScreen.LoadState = 70.0f;
            yield return(CoroutineStatus.Running);

#if USE_STEAM
            SteamWorkshopScreen = new SteamWorkshopScreen();
            if (SteamManager.IsInitialized)
            {
                Steamworks.SteamFriends.OnGameRichPresenceJoinRequested += OnInvitedToGame;
                Steamworks.SteamFriends.OnGameLobbyJoinRequested        += OnLobbyJoinRequested;
            }
#endif

            SubEditorScreen = new SubEditorScreen();

            TitleScreen.LoadState = 75.0f;
            yield return(CoroutineStatus.Running);

            ParticleEditorScreen = new ParticleEditorScreen();

            TitleScreen.LoadState = 80.0f;
            yield return(CoroutineStatus.Running);

            LevelEditorScreen     = new LevelEditorScreen();
            SpriteEditorScreen    = new SpriteEditorScreen();
            CharacterEditorScreen = new CharacterEditor.CharacterEditorScreen();

            yield return(CoroutineStatus.Running);

            TitleScreen.LoadState = 85.0f;
            ParticleManager       = new ParticleManager(GameScreen.Cam);
            ParticleManager.LoadPrefabs();
            TitleScreen.LoadState = 88.0f;
            LevelObjectPrefab.LoadAll();

            TitleScreen.LoadState = 90.0f;
            yield return(CoroutineStatus.Running);

            DecalManager = new DecalManager();
            LocationType.Init();
            MainMenuScreen.Select();

            CheckContentPackage();

            foreach (string steamError in SteamManager.InitializationErrors)
            {
                new GUIMessageBox(TextManager.Get("Error"), TextManager.Get(steamError));
            }

            TitleScreen.LoadState = 100.0f;
            hasLoaded             = true;
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE FINISHED", Color.Lime);
            }
            yield return(CoroutineStatus.Success);
        }
Example #4
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds;
            int updateIterations = (int)Math.Floor(Timing.Accumulator / Timing.Step);

            if (Timing.Accumulator > Timing.Step * 6.0)
            {
                //if the game's running too slowly then we have no choice
                //but to skip a bunch of steps
                //otherwise it snowballs and becomes unplayable
                Timing.Accumulator = Timing.Step;
            }

            CrossThread.ProcessTasks();

            PlayerInput.UpdateVariable();

            if (SoundManager != null)
            {
                if (WindowActive || !Config.MuteOnFocusLost)
                {
                    SoundManager.ListenerGain = SoundManager.CompressionDynamicRangeGain;
                }
                else
                {
                    SoundManager.ListenerGain = 0.0f;
                }
            }

            while (Timing.Accumulator >= Timing.Step)
            {
                Timing.TotalTime += Timing.Step;

                Stopwatch sw = new Stopwatch();
                sw.Start();

                fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly;
                TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16);
                fixedTime.ElapsedGameTime = addTime;
                fixedTime.TotalGameTime.Add(addTime);
                base.Update(fixedTime);

                PlayerInput.Update(Timing.Step);


                if (loadingScreenOpen)
                {
                    //reset accumulator if loading
                    // -> less choppy loading screens because the screen is rendered after each update
                    // -> no pause caused by leftover time in the accumulator when starting a new shift
                    GameMain.ResetFrameTime();

                    if (!TitleScreen.PlayingSplashScreen)
                    {
                        SoundPlayer.Update((float)Timing.Step);
                    }

                    if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen &&
                        (!waitForKeyHit || ((PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.PrimaryMouseButtonClicked()) && WindowActive)))
                    {
                        loadingScreenOpen = false;
                    }

#if DEBUG
                    if (TitleScreen.LoadState >= 100.0f && !TitleScreen.PlayingSplashScreen && Config.AutomaticQuickStartEnabled && FirstLoad)
                    {
                        loadingScreenOpen = false;
                        FirstLoad         = false;
                        MainMenuScreen.QuickStart();
                    }
#endif

                    if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine))
                    {
                        throw new LoadingException(loadingCoroutine.Exception);
                    }
                }
                else if (hasLoaded)
                {
                    if (ConnectLobby != 0)
                    {
                        if (Client != null)
                        {
                            Client.Disconnect();
                            Client = null;

                            GameMain.MainMenuScreen.Select();
                        }
                        Steam.SteamManager.JoinLobby(ConnectLobby, true);

                        ConnectLobby    = 0;
                        ConnectEndpoint = null;
                        ConnectName     = null;
                    }
                    else if (!string.IsNullOrWhiteSpace(ConnectEndpoint))
                    {
                        if (Client != null)
                        {
                            Client.Disconnect();
                            Client = null;

                            GameMain.MainMenuScreen.Select();
                        }
                        UInt64 serverSteamId = SteamManager.SteamIDStringToUInt64(ConnectEndpoint);
                        Client = new GameClient(Config.PlayerName,
                                                serverSteamId != 0 ? null : ConnectEndpoint,
                                                serverSteamId,
                                                string.IsNullOrWhiteSpace(ConnectName) ? ConnectEndpoint : ConnectName);
                        ConnectLobby    = 0;
                        ConnectEndpoint = null;
                        ConnectName     = null;
                    }

                    SoundPlayer.Update((float)Timing.Step);

                    if (PlayerInput.KeyHit(Keys.Escape) && WindowActive)
                    {
                        // Check if a text input is selected.
                        if (GUI.KeyboardDispatcher.Subscriber != null)
                        {
                            if (GUI.KeyboardDispatcher.Subscriber is GUITextBox textBox)
                            {
                                textBox.Deselect();
                            }
                            GUI.KeyboardDispatcher.Subscriber = null;
                        }
                        //if a verification prompt (are you sure you want to x) is open, close it
                        else if (GUIMessageBox.VisibleBox as GUIMessageBox != null &&
                                 GUIMessageBox.VisibleBox.UserData as string == "verificationprompt")
                        {
                            ((GUIMessageBox)GUIMessageBox.VisibleBox).Close();
                        }
                        else if (Tutorial.Initialized && Tutorial.ContentRunning)
                        {
                            (GameSession.GameMode as TutorialMode).Tutorial.CloseActiveContentGUI();
                        }
                        else if (GameSession.IsTabMenuOpen)
                        {
                            gameSession.ToggleTabMenu();
                        }
                        else if (GUI.PauseMenuOpen)
                        {
                            GUI.TogglePauseMenu();
                        }
                        //open the pause menu if not controlling a character OR if the character has no UIs active that can be closed with ESC
                        else if ((Character.Controlled == null || !itemHudActive())
                                 //TODO: do we need to check Inventory.SelectedSlot?
                                 && Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null &&
                                 !CrewManager.IsCommandInterfaceOpen &&
                                 !(Screen.Selected is SubEditorScreen editor && !editor.WiringMode && Character.Controlled?.SelectedConstruction != null))
                        {
                            // Otherwise toggle pausing, unless another window/interface is open.
                            GUI.TogglePauseMenu();
                        }

                        bool itemHudActive()
                        {
                            if (Character.Controlled?.SelectedConstruction == null)
                            {
                                return(false);
                            }
                            return
                                (Character.Controlled.SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null) ||
                                 ((Character.Controlled.ViewTarget as Item)?.Prefab?.FocusOnSelected ?? false));
                        }
                    }

#if DEBUG
                    if (GameMain.NetworkMember == null)
                    {
                        if (PlayerInput.KeyHit(Keys.P) && !(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
                        {
                            DebugConsole.Paused = !DebugConsole.Paused;
                        }
                    }
#endif

                    GUI.ClearUpdateList();
                    Paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || Tutorial.ContentRunning || DebugConsole.Paused) &&
                             (NetworkMember == null || !NetworkMember.GameStarted);

#if !DEBUG
                    if (NetworkMember == null && !WindowActive && !Paused && true && Screen.Selected != MainMenuScreen && Config.PauseOnFocusLost)
                    {
                        GUI.TogglePauseMenu();
                        Paused = true;
                    }
#endif

                    Screen.Selected.AddToGUIUpdateList();

                    if (Client != null)
                    {
                        Client.AddToGUIUpdateList();
                    }

                    FileSelection.AddToGUIUpdateList();

                    DebugConsole.AddToGUIUpdateList();

                    DebugConsole.Update((float)Timing.Step);
                    Paused = Paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted));

                    if (!Paused)
                    {
                        Screen.Selected.Update(Timing.Step);
                    }
                    else if (Tutorial.Initialized && Tutorial.ContentRunning)
                    {
                        (GameSession.GameMode as TutorialMode).Update((float)Timing.Step);
                    }
                    else if (DebugConsole.Paused)
                    {
                        if (Screen.Selected.Cam == null)
                        {
                            DebugConsole.Paused = false;
                        }
                        else
                        {
                            Screen.Selected.Cam.MoveCamera((float)Timing.Step);
                        }
                    }

                    if (NetworkMember != null)
                    {
                        NetworkMember.Update((float)Timing.Step);
                    }

                    GUI.Update((float)Timing.Step);
                }

                CoroutineManager.Update((float)Timing.Step, Paused ? 0.0f : (float)Timing.Step);

                SteamManager.Update((float)Timing.Step);

                TaskPool.Update();

                SoundManager?.Update();

                Timing.Accumulator -= Timing.Step;

                sw.Stop();
                PerformanceCounter.AddElapsedTicks("Update total", sw.ElapsedTicks);
                PerformanceCounter.UpdateTimeGraph.Update(sw.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency);
                PerformanceCounter.UpdateIterationsGraph.Update(updateIterations);
            }

            if (!Paused)
            {
                Timing.Alpha = Timing.Accumulator / Timing.Step;
            }
        }
Example #5
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 == SubmarineInfo.SubmarineType.Player && !submarine.DockedTo.Any(s => s.Info.Type != SubmarineInfo.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)
                {
                    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
        }
Example #6
0
        protected void Apply(float deltaTime, Entity entity, List <ISerializableEntity> targets)
        {
            Hull hull = null;

            if (entity is Character)
            {
                hull = ((Character)entity).AnimController.CurrentHull;
            }
            else if (entity is Item)
            {
                hull = ((Item)entity).CurrentHull;
            }
#if CLIENT
            if (entity != null && sounds.Count > 0)
            {
                if (soundChannel == null || !soundChannel.IsPlaying)
                {
                    if (soundSelectionMode == SoundSelectionMode.All)
                    {
                        foreach (RoundSound sound in sounds)
                        {
                            soundChannel = SoundPlayer.PlaySound(sound.Sound, sound.Volume, sound.Range, entity.WorldPosition, hull);
                            if (soundChannel != null)
                            {
                                soundChannel.Looping = loopSound;
                            }
                        }
                    }
                    else
                    {
                        int selectedSoundIndex = 0;
                        if (soundSelectionMode == SoundSelectionMode.ItemSpecific && entity is Item item)
                        {
                            selectedSoundIndex = item.ID % sounds.Count;
                        }
                        else if (soundSelectionMode == SoundSelectionMode.CharacterSpecific && entity is Character user)
                        {
                            selectedSoundIndex = user.ID % sounds.Count;
                        }
                        else
                        {
                            selectedSoundIndex = Rand.Int(sounds.Count);
                        }
                        var selectedSound = sounds[selectedSoundIndex];
                        soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, selectedSound.Volume, selectedSound.Range, entity.WorldPosition, hull);
                        if (soundChannel != null)
                        {
                            soundChannel.Looping = loopSound;
                        }
                    }
                }
            }
#endif

            foreach (ISerializableEntity serializableEntity in targets)
            {
                Item item = serializableEntity as Item;
                if (item == null)
                {
                    continue;
                }

                Character targetCharacter = targets.FirstOrDefault(t => t is Character character && !character.Removed) as Character;
                if (targetCharacter == null)
                {
                    foreach (var target in targets)
                    {
                        if (target is Limb limb && limb.character != null && !limb.character.Removed)
                        {
                            targetCharacter = ((Limb)target).character;
                        }
                    }
                }
                for (int i = 0; i < useItemCount; i++)
                {
                    if (item.Removed)
                    {
                        continue;
                    }
                    item.Use(deltaTime, targetCharacter, targets.FirstOrDefault(t => t is Limb) as Limb);
                }
            }

            if (removeItem)
            {
                foreach (Item item in targets.Where(t => t is Item).Cast <Item>())
                {
                    Entity.Spawner?.AddToRemoveQueue(item);
                }
            }

            if (duration > 0.0f)
            {
                DurationListElement element = new DurationListElement
                {
                    Parent  = this,
                    Timer   = duration,
                    Entity  = entity,
                    Targets = targets
                };

                DurationList.Add(element);
            }
            else
            {
                foreach (ISerializableEntity target in targets)
                {
                    if (target is Entity targetEntity)
                    {
                        if (targetEntity.Removed)
                        {
                            continue;
                        }
                    }

                    for (int i = 0; i < propertyNames.Length; i++)
                    {
                        if (target == null || target.SerializableProperties == null ||
                            !target.SerializableProperties.TryGetValue(propertyNames[i], out SerializableProperty property))
                        {
                            continue;
                        }
                        ApplyToProperty(target, property, propertyEffects[i], deltaTime);
                    }
                }
            }

            if (explosion != null && entity != null)
            {
                explosion.Explode(entity.WorldPosition, entity);
            }

            foreach (ISerializableEntity target in targets)
            {
                foreach (Affliction affliction in Afflictions)
                {
                    Affliction multipliedAffliction = affliction;
                    if (!disableDeltaTime)
                    {
                        multipliedAffliction = affliction.CreateMultiplied(deltaTime);
                    }

                    if (target is Character character)
                    {
                        character.LastDamageSource = entity;
                        foreach (Limb limb in character.AnimController.Limbs)
                        {
                            limb.character.DamageLimb(entity.WorldPosition, limb, new List <Affliction>()
                            {
                                multipliedAffliction
                            }, stun: 0.0f, playSound: false, attackImpulse: 0.0f);
                            //only apply non-limb-specific afflictions to the first limb
                            if (!affliction.Prefab.LimbSpecific)
                            {
                                break;
                            }
                        }
                    }
                    else if (target is Limb limb)
                    {
                        limb.character.DamageLimb(entity.WorldPosition, limb, new List <Affliction>()
                        {
                            multipliedAffliction
                        }, stun: 0.0f, playSound: false, attackImpulse: 0.0f);
                    }
                }

                foreach (Pair <string, float> reduceAffliction in ReduceAffliction)
                {
                    float reduceAmount = disableDeltaTime ? reduceAffliction.Second : reduceAffliction.Second * deltaTime;
                    if (target is Character character)
                    {
                        character.CharacterHealth.ReduceAffliction(null, reduceAffliction.First, reduceAmount);
                    }
                    else if (target is Limb limb)
                    {
                        limb.character.CharacterHealth.ReduceAffliction(limb, reduceAffliction.First, reduceAmount);
                    }
                }
            }

            if (FireSize > 0.0f && entity != null)
            {
                var fire = new FireSource(entity.WorldPosition, hull);
                fire.Size = new Vector2(FireSize, fire.Size.Y);
            }

            bool isNotClient = true;
#if CLIENT
            isNotClient = GameMain.Client == null;
#endif

            if (isNotClient && entity != null && Entity.Spawner != null) //clients are not allowed to spawn items
            {
                foreach (ItemSpawnInfo itemSpawnInfo in spawnItems)
                {
                    switch (itemSpawnInfo.SpawnPosition)
                    {
                    case ItemSpawnInfo.SpawnPositionType.This:
                        Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, entity.WorldPosition);
                        break;

                    case ItemSpawnInfo.SpawnPositionType.ThisInventory:
                    {
                        if (entity is Character character)
                        {
                            if (character.Inventory != null && character.Inventory.Items.Any(it => it == null))
                            {
                                Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, character.Inventory);
                            }
                        }
                        else if (entity is Item item)
                        {
                            var inventory = item?.GetComponent <ItemContainer>()?.Inventory;
                            if (inventory != null && inventory.Items.Any(it => it == null))
                            {
                                Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, inventory);
                            }
                        }
                    }
                    break;

                    case ItemSpawnInfo.SpawnPositionType.ContainedInventory:
                    {
                        Inventory thisInventory = null;
                        if (entity is Character character)
                        {
                            thisInventory = character.Inventory;
                        }
                        else if (entity is Item item)
                        {
                            thisInventory = item?.GetComponent <ItemContainer>()?.Inventory;
                        }
                        if (thisInventory != null)
                        {
                            foreach (Item item in thisInventory.Items)
                            {
                                if (item == null)
                                {
                                    continue;
                                }
                                Inventory containedInventory = item.GetComponent <ItemContainer>()?.Inventory;
                                if (containedInventory == null || !containedInventory.Items.Any(i => i == null))
                                {
                                    continue;
                                }
                                Entity.Spawner.AddToSpawnQueue(itemSpawnInfo.ItemPrefab, containedInventory);
                                break;
                            }
                        }
                    }
                    break;
                    }
                }
            }

#if CLIENT
            if (entity != null)
            {
                foreach (ParticleEmitter emitter in particleEmitters)
                {
                    float angle = 0.0f;
                    if (emitter.Prefab.CopyEntityAngle)
                    {
                        if (entity is Item it)
                        {
                            angle = it.body == null ? 0.0f : it.body.Rotation;
                        }
                    }

                    emitter.Emit(deltaTime, entity.WorldPosition, hull, angle);
                }
            }
#endif
        }
Example #7
0
        /// <summary>
        /// Update the selection logic in submarine editor
        /// </summary>
        public static void UpdateSelecting(Camera cam)
        {
            if (resizing)
            {
                if (selectedList.Count == 0)
                {
                    resizing = false;
                }
                return;
            }

            foreach (MapEntity e in mapEntityList)
            {
                e.isHighlighted = false;
            }

            if (DisableSelect)
            {
                DisableSelect = false;
                return;
            }

            if (GUI.MouseOn != null || !PlayerInput.MouseInsideWindow)
            {
                if (highlightedListBox == null ||
                    (GUI.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUI.MouseOn)))
                {
                    UpdateHighlightedListBox(null, false);
                    return;
                }
            }

            if (MapEntityPrefab.Selected != null)
            {
                selectionPos = Vector2.Zero;
                selectedList.Clear();
                return;
            }
            if (GUI.KeyboardDispatcher.Subscriber == null)
            {
                if (PlayerInput.KeyHit(Keys.Delete))
                {
                    if (selectedList.Any())
                    {
                        SubEditorScreen.StoreCommand(new AddOrDeleteCommand(selectedList, true));
                    }
                    selectedList.ForEach(e => { if (!e.Removed)
                                                {
                                                    e.Remove();
                                                }
                                         });
                    selectedList.Clear();
                }

                if (PlayerInput.IsCtrlDown())
                {
#if DEBUG
                    if (PlayerInput.KeyHit(Keys.D))
                    {
                        bool terminate = false;
                        foreach (MapEntity entity in selectedList)
                        {
                            if (entity is Item item && item.GetComponent <Planter>() is { } planter)
                            {
                                planter.Update(1.0f, cam);
                                for (var i = 0; i < planter.GrowableSeeds.Length; i++)
                                {
                                    Growable  seed = planter.GrowableSeeds[i];
                                    PlantSlot slot = planter.PlantSlots.ContainsKey(i) ? planter.PlantSlots[i] : Planter.NullSlot;
                                    if (seed == null)
                                    {
                                        continue;
                                    }

                                    seed.CreateDebugHUD(planter, slot);
                                    terminate = true;
                                    break;
                                }
                            }

                            if (terminate)
                            {
                                break;
                            }
                        }
                    }
#endif
                    if (PlayerInput.KeyHit(Keys.C))
                    {
                        Copy(selectedList);
                    }
                    else if (PlayerInput.KeyHit(Keys.X))
                    {
                        Cut(selectedList);
                    }
                    else if (PlayerInput.KeyHit(Keys.V))
                    {
                        Paste(cam.ScreenToWorld(PlayerInput.MousePosition));
                    }
                    else if (PlayerInput.KeyHit(Keys.G))
                    {
                        if (selectedList.Any())
                        {
                            if (SelectionGroups.ContainsKey(selectedList.Last()))
                            {
                                // Ungroup all selected
                                selectedList.ForEach(e => SelectionGroups.Remove(e));
                            }
                            else
                            {
                                foreach (var entity in selectedList)
                                {
                                    // Remove the old group, if any
                                    SelectionGroups.Remove(entity);
                                    // Create a group that can be accessed with any member
                                    SelectionGroups.Add(entity, selectedList);
                                }
                            }
                        }
                    }
                }
            }

            Vector2   position          = cam.ScreenToWorld(PlayerInput.MousePosition);
            MapEntity highLightedEntity = null;
            if (startMovingPos == Vector2.Zero)
            {
                List <MapEntity> highlightedEntities = new List <MapEntity>();
                if (highlightedListBox != null && highlightedListBox.IsParentOf(GUI.MouseOn))
                {
                    highLightedEntity = GUI.MouseOn.UserData as MapEntity;
                }
                else
                {
                    foreach (MapEntity e in mapEntityList)
                    {
                        if (!e.SelectableInEditor)
                        {
                            continue;
                        }

                        if (e.IsMouseOn(position))
                        {
                            int i = 0;
                            while (i < highlightedEntities.Count &&
                                   e.Sprite != null &&
                                   (highlightedEntities[i].Sprite == null || highlightedEntities[i].SpriteDepth < e.SpriteDepth))
                            {
                                i++;
                            }

                            highlightedEntities.Insert(i, e);

                            if (i == 0)
                            {
                                highLightedEntity = e;
                            }
                        }
                    }

                    UpdateHighlighting(highlightedEntities);
                }

                if (highLightedEntity != null)
                {
                    highLightedEntity.isHighlighted = true;
                }
            }

            if (GUI.KeyboardDispatcher.Subscriber == null)
            {
                Vector2 nudge = GetNudgeAmount();
                if (nudge != Vector2.Zero)
                {
                    foreach (MapEntity entityToNudge in selectedList)
                    {
                        entityToNudge.Move(nudge);
                    }
                }
            }
            else
            {
                keyDelay = 0;
            }

            bool isShiftDown = PlayerInput.IsShiftDown();

            //started moving selected entities
            if (startMovingPos != Vector2.Zero)
            {
                Item targetContainer = GetPotentialContainer(position, selectedList);

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

                if (PlayerInput.PrimaryMouseButtonReleased())
                {
                    //mouse released -> move the entities to the new position of the mouse

                    Vector2 moveAmount = position - startMovingPos;

                    if (!isShiftDown)
                    {
                        moveAmount.X = (float)(moveAmount.X > 0.0f ? Math.Floor(moveAmount.X / Submarine.GridSize.X) : Math.Ceiling(moveAmount.X / Submarine.GridSize.X)) * Submarine.GridSize.X;
                        moveAmount.Y = (float)(moveAmount.Y > 0.0f ? Math.Floor(moveAmount.Y / Submarine.GridSize.Y) : Math.Ceiling(moveAmount.Y / Submarine.GridSize.Y)) * Submarine.GridSize.Y;
                    }

                    if (Math.Abs(moveAmount.X) >= Submarine.GridSize.X || Math.Abs(moveAmount.Y) >= Submarine.GridSize.Y || isShiftDown)
                    {
                        if (!isShiftDown)
                        {
                            moveAmount = Submarine.VectorToWorldGrid(moveAmount);
                        }

                        //clone
                        if (PlayerInput.IsCtrlDown())
                        {
                            var clones = Clone(selectedList).Where(c => c != null).ToList();
                            selectedList = clones;
                            selectedList.ForEach(c => c.Move(moveAmount));
                            SubEditorScreen.StoreCommand(new AddOrDeleteCommand(clones, false));
                        }
                        else // move
                        {
                            var oldRects = selectedList.Select(e => e.Rect).ToList();
                            List <MapEntity> deposited = new List <MapEntity>();
                            foreach (MapEntity e in selectedList)
                            {
                                e.Move(moveAmount);

                                if (isShiftDown && e is Item item && targetContainer != null)
                                {
                                    if (targetContainer.OwnInventory.TryPutItem(item, Character.Controlled))
                                    {
                                        SoundPlayer.PlayUISound(GUISoundType.DropItem);
                                        deposited.Add(item);
                                    }
                                    else
                                    {
                                        SoundPlayer.PlayUISound(GUISoundType.PickItemFail);
                                    }
                                }
                            }

                            SubEditorScreen.StoreCommand(new TransformCommand(new List <MapEntity>(selectedList), selectedList.Select(entity => entity.Rect).ToList(), oldRects, false));
                            if (deposited.Any() && deposited.Any(entity => entity is Item))
                            {
                                var depositedItems = deposited.Where(entity => entity is Item).Cast <Item>().ToList();
                                SubEditorScreen.StoreCommand(new InventoryPlaceCommand(targetContainer.OwnInventory, depositedItems, false));
                            }

                            deposited.ForEach(entity => { selectedList.Remove(entity); });
                        }
                    }
                    startMovingPos = Vector2.Zero;
                }
            }
            //started dragging a "selection rectangle"
            else if (selectionPos != Vector2.Zero)
            {
                selectionSize.X = position.X - selectionPos.X;
                selectionSize.Y = selectionPos.Y - position.Y;

                List <MapEntity> newSelection = new List <MapEntity>();// FindSelectedEntities(selectionPos, selectionSize);
                if (Math.Abs(selectionSize.X) > Submarine.GridSize.X || Math.Abs(selectionSize.Y) > Submarine.GridSize.Y)
                {
                    newSelection = FindSelectedEntities(selectionPos, selectionSize);
                }
                else
                {
                    if (highLightedEntity != null)
                    {
                        if (SelectionGroups.TryGetValue(highLightedEntity, out List <MapEntity> group))
                        {
                            newSelection.AddRange(group);
                        }
                        else
                        {
                            newSelection.Add(highLightedEntity);
                        }
                    }
                }

                if (PlayerInput.PrimaryMouseButtonReleased())
                {
                    if (PlayerInput.IsCtrlDown())
                    {
                        foreach (MapEntity e in newSelection)
                        {
                            if (selectedList.Contains(e))
                            {
                                RemoveSelection(e);
                            }
                            else
                            {
                                AddSelection(e);
                            }
                        }
                    }
                    else
                    {
                        selectedList = new List <MapEntity>(newSelection);
                        //selectedList.Clear();
                        //newSelection.ForEach(e => AddSelection(e));
                        foreach (var entity in newSelection)
                        {
                            HandleDoorGapLinks(entity,
                                               onGapFound: (door, gap) =>
                            {
                                door.RefreshLinkedGap();
                                if (!selectedList.Contains(gap))
                                {
                                    selectedList.Add(gap);
                                }
                            },
                                               onDoorFound: (door, gap) =>
                            {
                                if (!selectedList.Contains(door.Item))
                                {
                                    selectedList.Add(door.Item);
                                }
                            });
                        }
                    }

                    //select wire if both items it's connected to are selected
                    var selectedItems = selectedList.Where(e => e is Item).Cast <Item>().ToList();
                    foreach (Item item in selectedItems)
                    {
                        if (item.Connections == null)
                        {
                            continue;
                        }
                        foreach (Connection c in item.Connections)
                        {
                            foreach (Wire w in c.Wires)
                            {
                                if (w == null || selectedList.Contains(w.Item))
                                {
                                    continue;
                                }

                                if (w.OtherConnection(c) != null && selectedList.Contains(w.OtherConnection(c).Item))
                                {
                                    selectedList.Add(w.Item);
                                }
                            }
                        }
                    }

                    selectionPos  = Vector2.Zero;
                    selectionSize = Vector2.Zero;
                }
            }
            //default, not doing anything specific yet
            else
            {
                if (PlayerInput.PrimaryMouseButtonHeld() &&
                    PlayerInput.KeyUp(Keys.Space) &&
                    PlayerInput.KeyUp(Keys.LeftAlt) &&
                    PlayerInput.KeyUp(Keys.RightAlt) &&
                    (highlightedListBox == null || (GUI.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUI.MouseOn))))
                {
                    //if clicking a selected entity, start moving it
                    foreach (MapEntity e in selectedList)
                    {
                        if (e.IsMouseOn(position))
                        {
                            startMovingPos = position;
                        }
                    }
                    selectionPos = position;

                    //stop camera movement to prevent accidental dragging or rect selection
                    Screen.Selected.Cam.StopMovement();
                }
            }
        }
 static partial void PlayTinnitusProjSpecific(float volume) => SoundPlayer.PlaySound("tinnitus", volume: volume);
Example #9
0
        public void StartShift(Level level, bool reloadSub = true, bool loadSecondSub = false)
        {
#if CLIENT
            GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
#endif

            this.level = level;

            if (submarine == null)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine not selected");
                return;
            }

            if (reloadSub || Submarine.MainSub != submarine)
            {
                submarine.Load(true);
            }
            Submarine.MainSub = submarine;
            if (loadSecondSub)
            {
                if (Submarine.MainSubs[1] == null)
                {
                    Submarine.MainSubs[1] = new Submarine(Submarine.MainSub.FilePath, Submarine.MainSub.MD5Hash.Hash, true);
                    Submarine.MainSubs[1].Load(false);
                }
                else if (reloadSub)
                {
                    Submarine.MainSubs[1].Load(false);
                }
            }

            if (level != null)
            {
                level.Generate();

                submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));

#if CLIENT
                GameMain.GameScreen.BackgroundCreatureManager.SpawnSprites(80);
#endif
            }

            if (gameMode.Mission != null)
            {
                currentMission = gameMode.Mission;
            }

            if (gameMode != null)
            {
                gameMode.Start();
            }

            if (gameMode.Mission != null)
            {
                Mission.Start(Level.Loaded);
            }

            TaskManager.StartShift(level);

            if (gameMode != null)
            {
                gameMode.MsgBox();
            }

            Entity.Spawner = new EntitySpawner();

#if CLIENT
            shiftSummary = new ShiftSummary(this);

            GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);
            SoundPlayer.SwitchMusic();
#endif
        }
Example #10
0
        partial void AddDamageProjSpecific(IEnumerable <Affliction> afflictions, bool playSound, IEnumerable <DamageModifier> appliedDamageModifiers)
        {
            float bleedingDamage   = character.CharacterHealth.DoesBleed ? afflictions.Where(a => a is AfflictionBleeding).Sum(a => a.GetVitalityDecrease(character.CharacterHealth)) : 0;
            float damage           = afflictions.Where(a => a.Prefab.AfflictionType == "damage").Sum(a => a.GetVitalityDecrease(character.CharacterHealth));
            float damageMultiplier = 1;

            foreach (DamageModifier damageModifier in appliedDamageModifiers)
            {
                foreach (var afflictionPrefab in AfflictionPrefab.List)
                {
                    if (damageModifier.MatchesAffliction(afflictionPrefab.Identifier, afflictionPrefab.AfflictionType))
                    {
                        if (afflictionPrefab.Effects.Any(e => e.MaxVitalityDecrease > 0))
                        {
                            damageMultiplier *= damageModifier.DamageMultiplier;
                        }
                    }
                }
            }
            if (playSound)
            {
                string damageSoundType = (bleedingDamage > damage) ? "LimbSlash" : "LimbBlunt";
                foreach (DamageModifier damageModifier in appliedDamageModifiers)
                {
                    if (!string.IsNullOrWhiteSpace(damageModifier.DamageSound))
                    {
                        damageSoundType = damageModifier.DamageSound;
                        break;
                    }
                }
                SoundPlayer.PlayDamageSound(damageSoundType, Math.Max(damage, bleedingDamage), WorldPosition);
            }

            // spawn damage particles
            float damageParticleAmount = Math.Min(damage / 10, 1.0f) * damageMultiplier;

            if (damageParticleAmount > 0.001f)
            {
                foreach (ParticleEmitter emitter in character.DamageEmitters)
                {
                    if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air)
                    {
                        continue;
                    }
                    if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water)
                    {
                        continue;
                    }

                    emitter.Emit(1.0f, WorldPosition, character.CurrentHull, amountMultiplier: damageParticleAmount);
                }
            }

            if (bleedingDamage > 0)
            {
                float bloodParticleAmount = Math.Min(bleedingDamage / 5, 1.0f) * damageMultiplier;
                float bloodParticleSize   = MathHelper.Clamp(bleedingDamage / 5, 0.1f, 1.0f);

                foreach (ParticleEmitter emitter in character.BloodEmitters)
                {
                    if (inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Air)
                    {
                        continue;
                    }
                    if (!inWater && emitter.Prefab.ParticlePrefab.DrawTarget == ParticlePrefab.DrawTargetType.Water)
                    {
                        continue;
                    }

                    emitter.Emit(1.0f, WorldPosition, character.CurrentHull, sizeMultiplier: bloodParticleSize, amountMultiplier: bloodParticleAmount);
                }

                if (bloodParticleAmount > 0 && character.CurrentHull != null && !string.IsNullOrEmpty(character.BloodDecalName))
                {
                    character.CurrentHull.AddDecal(character.BloodDecalName, WorldPosition, MathHelper.Clamp(bloodParticleSize, 0.5f, 1.0f));
                }
            }
        }
Example #11
0
        public void StartRound(Level level, bool reloadSub = true, bool loadSecondSub = false, bool mirrorLevel = false)
        {
#if CLIENT
            GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
#endif

            this.level = level;

            if (submarine == null)
            {
                DebugConsole.ThrowError("Couldn't start game session, submarine not selected");
                return;
            }

            if (reloadSub || Submarine.MainSub != submarine)
            {
                submarine.Load(true);
            }
            Submarine.MainSub = submarine;
            if (loadSecondSub)
            {
                if (Submarine.MainSubs[1] == null)
                {
                    Submarine.MainSubs[1] = new Submarine(Submarine.MainSub.FilePath, Submarine.MainSub.MD5Hash.Hash, true);
                    Submarine.MainSubs[1].Load(false);
                }
                else if (reloadSub)
                {
                    Submarine.MainSubs[1].Load(false);
                }
            }

            if (level != null)
            {
                level.Generate(mirrorLevel);
                submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));
            }

            Entity.Spawner = new EntitySpawner();

            if (GameMode.Mission != null)
            {
                currentMission = GameMode.Mission;
            }
            if (GameMode != null)
            {
                GameMode.Start();
            }
            if (GameMode.Mission != null)
            {
                Mission.Start(Level.Loaded);
            }

            EventManager.StartRound(level);

            if (GameMode != null)
            {
                GameMode.MsgBox();
                if (GameMode is MultiPlayerCampaign mpCampaign && GameMain.Server != null)
                {
                    mpCampaign.CargoManager.CreateItems();
                }
            }

            GameAnalyticsManager.AddDesignEvent("Submarine:" + submarine.Name);
            GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level.Seed));
            GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
                                                     GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));


#if CLIENT
            roundSummary = new RoundSummary(this);

            GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);
            SoundPlayer.SwitchMusic();
#endif
        }
Example #12
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            Timing.TotalTime    = gameTime.TotalGameTime.TotalSeconds;
            Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds;
            PlayerInput.UpdateVariable();

            bool paused = true;

            if (GameMain.NilMod.UseExperimentalFPSLagPrevention && !loadingScreenOpen)
            {
                if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 2)
                {
                    Timing.Step = 1.0 / 8.0;
                    FarseerPhysics.Settings.VelocityIterations    = 10;
                    FarseerPhysics.Settings.PositionIterations    = 4;
                    FarseerPhysics.Settings.TOIPositionIterations = 25;
                    FarseerPhysics.Settings.TOIVelocityIterations = 10;
                }
                else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 4)
                {
                    Timing.Step = 1.0 / 10.0;
                    FarseerPhysics.Settings.VelocityIterations    = 10;
                    FarseerPhysics.Settings.PositionIterations    = 4;
                    FarseerPhysics.Settings.TOIPositionIterations = 25;
                    FarseerPhysics.Settings.TOIVelocityIterations = 10;
                }
                else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 6)
                {
                    Timing.Step = 1.0 / 12.0;
                    FarseerPhysics.Settings.VelocityIterations    = 10;
                    FarseerPhysics.Settings.PositionIterations    = 4;
                    FarseerPhysics.Settings.TOIPositionIterations = 25;
                    FarseerPhysics.Settings.TOIVelocityIterations = 10;
                }
                else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 8)
                {
                    Timing.Step = 1.0 / 15.0;
                    FarseerPhysics.Settings.VelocityIterations    = 9;
                    FarseerPhysics.Settings.PositionIterations    = 4;
                    FarseerPhysics.Settings.TOIPositionIterations = 22;
                    FarseerPhysics.Settings.TOIVelocityIterations = 9;
                }
                else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 10)
                {
                    Timing.Step = 1.0 / 20.0;
                    FarseerPhysics.Settings.VelocityIterations    = 9;
                    FarseerPhysics.Settings.PositionIterations    = 4;
                    FarseerPhysics.Settings.TOIPositionIterations = 22;
                    FarseerPhysics.Settings.TOIVelocityIterations = 9;
                }
                else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 12)
                {
                    Timing.Step = 1.0 / 25.0;
                    FarseerPhysics.Settings.VelocityIterations    = 9;
                    FarseerPhysics.Settings.PositionIterations    = 4;
                    FarseerPhysics.Settings.TOIPositionIterations = 22;
                    FarseerPhysics.Settings.TOIVelocityIterations = 9;
                }
                else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 14)
                {
                    Timing.Step = 1.0 / 30.0;
                    FarseerPhysics.Settings.VelocityIterations    = 8;
                    FarseerPhysics.Settings.PositionIterations    = 3;
                    FarseerPhysics.Settings.TOIPositionIterations = 20;
                    FarseerPhysics.Settings.TOIVelocityIterations = 8;
                }
                else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 16)
                {
                    Timing.Step = 1.0 / 35.0;
                    FarseerPhysics.Settings.VelocityIterations    = 8;
                    FarseerPhysics.Settings.PositionIterations    = 3;
                    FarseerPhysics.Settings.TOIPositionIterations = 20;
                    FarseerPhysics.Settings.TOIVelocityIterations = 8;
                }
                else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 18)
                {
                    Timing.Step = 1.0 / 40.0;
                    FarseerPhysics.Settings.VelocityIterations    = 8;
                    FarseerPhysics.Settings.PositionIterations    = 3;
                    FarseerPhysics.Settings.TOIPositionIterations = 20;
                    FarseerPhysics.Settings.TOIVelocityIterations = 8;
                }
                else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 20)
                {
                    Timing.Step = 1.0 / 45.0;
                    FarseerPhysics.Settings.VelocityIterations    = 8;
                    FarseerPhysics.Settings.PositionIterations    = 3;
                    FarseerPhysics.Settings.TOIPositionIterations = 20;
                    FarseerPhysics.Settings.TOIVelocityIterations = 8;
                }
                else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 22)
                {
                    Timing.Step = 1.0 / 50.0;
                    FarseerPhysics.Settings.VelocityIterations    = 8;
                    FarseerPhysics.Settings.PositionIterations    = 3;
                    FarseerPhysics.Settings.TOIPositionIterations = 20;
                    FarseerPhysics.Settings.TOIVelocityIterations = 8;
                }
                else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 25)
                {
                    Timing.Step = 1.0 / 55.0;
                    FarseerPhysics.Settings.VelocityIterations    = 8;
                    FarseerPhysics.Settings.PositionIterations    = 3;
                    FarseerPhysics.Settings.TOIPositionIterations = 20;
                    FarseerPhysics.Settings.TOIVelocityIterations = 8;
                }
                else
                {
                    Timing.Step = 1.0 / 60.0;
                    FarseerPhysics.Settings.VelocityIterations    = 8;
                    FarseerPhysics.Settings.PositionIterations    = 3;
                    FarseerPhysics.Settings.TOIPositionIterations = 20;
                    FarseerPhysics.Settings.TOIVelocityIterations = 8;
                }
            }
            else
            {
                Timing.Step = 1.0 / 60.0;
                FarseerPhysics.Settings.VelocityIterations    = 8;
                FarseerPhysics.Settings.PositionIterations    = 3;
                FarseerPhysics.Settings.TOIPositionIterations = 20;
                FarseerPhysics.Settings.TOIVelocityIterations = 8;
            }

            while (Timing.Accumulator >= Timing.Step)
            {
                NilModProfiler.SWMainUpdateLoop.Start();
                fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly;
                TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16);

                if (GameMain.NilMod.UseExperimentalFPSLagPrevention)
                {
                    if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 2)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 125);
                    }
                    else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 4)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 100);
                    }
                    else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 6)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 83);
                    }
                    else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 8)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 66);
                    }
                    else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 10)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 50);
                    }
                    else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 12)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 40);
                    }
                    else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 14)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 33);
                    }
                    else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 16)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 28);
                    }
                    else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 18)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 25);
                    }
                    else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 20)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 22);
                    }
                    else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 22)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 20);
                    }
                    else if ((int)GameMain.FrameCounter.CurrentFramesPerSecond <= 25)
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 18);
                    }
                    else
                    {
                        addTime = new TimeSpan(0, 0, 0, 0, 16);
                    }
                }

                fixedTime.ElapsedGameTime = addTime;
                fixedTime.TotalGameTime.Add(addTime);
                base.Update(fixedTime);

                NilModProfiler.SWPlayerInput.Start();
                if (WindowActive)
                {
                    PlayerInput.Update(Timing.Step);
                }
                NilModProfiler.RecordPlayerInput();

                if (loadingScreenOpen)
                {
                    //reset accumulator if loading
                    // -> less choppy loading screens because the screen is rendered after each update
                    // -> no pause caused by leftover time in the accumulator when starting a new shift
                    if (TitleScreen.LoadState >= 100f)
                    {
                        Timing.Accumulator     = 0.0f;
                        this.TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 12);
                    }
                    else
                    {
                        Timing.Accumulator     = Timing.Step * 1.99;
                        this.TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 1);
                    }

                    if (TitleScreen.LoadState >= 100.0f &&
                        (!waitForKeyHit || PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0 || PlayerInput.LeftButtonClicked()))
                    {
                        loadingScreenOpen = false;
                    }

                    if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine))
                    {
                        throw new Exception("Loading was interrupted due to an error");
                    }
                }
                else if (hasLoaded)
                {
                    NilMod.Update((float)Timing.Step);

                    NilModProfiler.SWSoundPlayer.Start();
                    SoundPlayer.Update((float)Timing.Step);
                    NilModProfiler.RecordSoundPlayer();

                    if (PlayerInput.KeyHit(Keys.Escape))
                    {
                        GUI.TogglePauseMenu();
                    }

                    GUIComponent.ClearUpdateList();
                    paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen) &&
                             (NetworkMember == null || !NetworkMember.GameStarted);

                    if (!paused)
                    {
                        Screen.Selected.AddToGUIUpdateList();
                    }

                    if (NetworkMember != null)
                    {
                        NetworkMember.AddToGUIUpdateList();
                    }

                    GUI.AddToGUIUpdateList();
                    DebugConsole.AddToGUIUpdateList();
                    GUIComponent.UpdateMouseOn();

                    NilModProfiler.SWDebugConsole.Start();
                    DebugConsole.Update(this, (float)Timing.Step);
                    paused = paused || (DebugConsole.IsOpen && (NetworkMember == null || !NetworkMember.GameStarted));
                    NilModProfiler.RecordDebugConsole();

                    if (!paused)
                    {
                        NilModProfiler.SWGameScreen.Start();
                        Screen.Selected.Update(Timing.Step);
                        NilModProfiler.RecordGameScreen();
                    }

                    if (NetworkMember != null)
                    {
                        NilModProfiler.SWNetworkMember.Start();
                        NetworkMember.Update((float)Timing.Step);
                        NilModProfiler.RecordNetworkMember();
                    }

                    NilModProfiler.SWGUIUpdate.Start();
                    GUI.Update((float)Timing.Step);
                    NilModProfiler.RecordGUIUpdate();
                }

                NilModProfiler.SWCoroutineManager.Start();
                CoroutineManager.Update((float)Timing.Step, paused ? 0.0f : (float)Timing.Step);
                NilModProfiler.RecordCoroutineManager();

                Timing.Accumulator -= Timing.Step;
                if (NilModProfiler.SWMainUpdateLoop.ElapsedTicks > 0)
                {
                    NilModProfiler.RecordMainLoopUpdate();
                }
            }

            GameMain.NilModProfiler.Update((float)Timing.Step);

            if (!paused)
            {
                Timing.Alpha = Timing.Accumulator / Timing.Step;
            }
        }
Example #13
0
        private IEnumerable <object> Load()
        {
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE", Color.Lime);
            }
            GUI.GraphicsDevice = base.GraphicsDevice;
            GUI.Init(Content);

            InitUserStats();

            GUIComponent.Init(Window);
            DebugConsole.Init(Window);
            DebugConsole.Log(SelectedPackage == null ? "No content package selected" : "Content package \"" + SelectedPackage.Name + "\" selected");
            yield return(CoroutineStatus.Running);

            LightManager = new Lights.LightManager(base.GraphicsDevice, Content);

            Hull.renderer         = new WaterRenderer(base.GraphicsDevice, Content);
            TitleScreen.LoadState = 1.0f;
            yield return(CoroutineStatus.Running);

            Sound.Init();
            GUI.LoadContent();
            TitleScreen.LoadState = 2.0f;
            yield return(CoroutineStatus.Running);

            MissionPrefab.Init();
            MapEntityPrefab.Init();
            LevelGenerationParams.LoadPresets();
            TitleScreen.LoadState = 10.0f;
            yield return(CoroutineStatus.Running);

            JobPrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Jobs));
            // Add any missing jobs from the prefab into Config.JobNamePreferences.
            foreach (JobPrefab job in JobPrefab.List)
            {
                if (!Config.JobNamePreferences.Contains(job.Name))
                {
                    Config.JobNamePreferences.Add(job.Name);
                }
            }
            StructurePrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Structure));
            TitleScreen.LoadState = 20.0f;
            yield return(CoroutineStatus.Running);

            ItemPrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Item));
            TitleScreen.LoadState = 30.0f;
            yield return(CoroutineStatus.Running);

            Debug.WriteLine("sounds");
            CoroutineManager.StartCoroutine(SoundPlayer.Init());

            int i = 0;

            while (!SoundPlayer.Initialized)
            {
                i++;
                TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ?
                                        30.0f :
                                        Math.Min(30.0f + 40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 70.0f);
                yield return(CoroutineStatus.Running);
            }

            TitleScreen.LoadState = 70.0f;
            yield return(CoroutineStatus.Running);

            GameModePreset.Init();

            Submarine.RefreshSavedSubs();
            TitleScreen.LoadState = 80.0f;
            yield return(CoroutineStatus.Running);

            GameScreen            = new GameScreen(GraphicsDeviceManager.GraphicsDevice, Content);
            TitleScreen.LoadState = 90.0f;
            yield return(CoroutineStatus.Running);

            MainMenuScreen = new MainMenuScreen(this);
            LobbyScreen    = new LobbyScreen();

            ServerListScreen = new ServerListScreen();

            SubEditorScreen       = new SubEditorScreen(Content);
            CharacterEditorScreen = new CharacterEditorScreen();
            ParticleEditorScreen  = new ParticleEditorScreen();

            GameSession.inGameInfo = new InGameInfo();

            yield return(CoroutineStatus.Running);

            ParticleManager = new ParticleManager(GameScreen.Cam);
            ParticleManager.LoadPrefabs();
            DecalManager = new DecalManager();
            yield return(CoroutineStatus.Running);

            LocationType.Init();
            MainMenuScreen.Select();

            NilMod.GameInitialize(true);

            TitleScreen.LoadState = 100.0f;
            hasLoaded             = true;
            if (GameSettings.VerboseLogging)
            {
                DebugConsole.NewMessage("LOADING COROUTINE FINISHED", Color.Lime);
            }

            //Nilmod Server Start code
            HandleParameters();
            if (NilMod.StartToServer)
            {
                Autostart();
            }

            GameMain.NilMod.SuccesfulStart = true;

            yield return(CoroutineStatus.Success);
        }
Example #14
0
        protected override void Update(float deltaTime)
        {
            if (!Visible)
            {
                return;
            }
            base.Update(deltaTime);
            if (Rect.Contains(PlayerInput.MousePosition) && CanBeSelected && CanBeFocused && Enabled && GUI.IsMouseOn(this))
            {
                State = Selected ?
                        ComponentState.HoverSelected :
                        ComponentState.Hover;
                if (PlayerInput.PrimaryMouseButtonDown())
                {
                    OnButtonDown?.Invoke();
                }
                if (PlayerInput.PrimaryMouseButtonHeld())
                {
                    if (OnPressed != null)
                    {
                        if (OnPressed())
                        {
                            State = ComponentState.Pressed;
                        }
                    }
                    else
                    {
                        State = ComponentState.Pressed;
                    }
                }
                else if (PlayerInput.PrimaryMouseButtonClicked())
                {
                    SoundPlayer.PlayUISound(ClickSound);
                    if (OnClicked != null)
                    {
                        if (OnClicked(this, UserData))
                        {
                            State = ComponentState.Selected;
                        }
                    }
                    else
                    {
                        Selected = !Selected;
                    }
                }
            }
            else
            {
                if (!ExternalHighlight)
                {
                    State = Selected ? ComponentState.Selected : ComponentState.None;
                }
                else
                {
                    State = ComponentState.Hover;
                }
            }

            foreach (GUIComponent child in Children)
            {
                child.State = State;
            }

            if (Pulse)
            {
                pulseTimer += deltaTime;
                if (pulseTimer > 1.0f)
                {
                    if (!flashed)
                    {
                        flashed = true;
                        Frame.Flash(Color.White * 0.2f, 0.8f, true);
                    }

                    pulseExpand += deltaTime;
                    if (pulseExpand > 1.0f)
                    {
                        pulseTimer  = 0.0f;
                        pulseExpand = 0.0f;
                        flashed     = false;
                    }
                }
            }
        }
Example #15
0
        protected bool TrySwapping(int index, Item item, Character user, bool createNetworkEvent, bool swapWholeStack)
        {
            if (item?.ParentInventory == null || !slots[index].Any())
            {
                return(false);
            }
            if (slots[index].Items.Any(it => !it.IsInteractable(user)))
            {
                return(false);
            }
            if (!AllowSwappingContainedItems)
            {
                return(false);
            }

            //swap to InvSlotType.Any if possible
            Inventory otherInventory  = item.ParentInventory;
            bool      otherIsEquipped = false;
            int       otherIndex      = -1;

            for (int i = 0; i < otherInventory.slots.Length; i++)
            {
                if (!otherInventory.slots[i].Contains(item))
                {
                    continue;
                }
                if (otherInventory is CharacterInventory characterInventory)
                {
                    if (characterInventory.SlotTypes[i] == InvSlotType.Any)
                    {
                        otherIndex = i;
                        break;
                    }
                    else
                    {
                        otherIsEquipped = true;
                    }
                }
            }
            if (otherIndex == -1)
            {
                otherIndex = otherInventory.FindIndex(item);
                if (otherIndex == -1)
                {
                    DebugConsole.ThrowError("Something went wrong when trying to swap items between inventory slots: couldn't find the source item from it's inventory.\n" + Environment.StackTrace.CleanupStackTrace());
                    return(false);
                }
            }

            List <Item> existingItems = new List <Item>();

            if (swapWholeStack)
            {
                existingItems.AddRange(slots[index].Items);
                for (int j = 0; j < capacity; j++)
                {
                    if (existingItems.Any(existingItem => slots[j].Contains(existingItem)))
                    {
                        slots[j].RemoveAllItems();
                    }
                }
            }
            else
            {
                existingItems.Add(slots[index].FirstOrDefault());
                for (int j = 0; j < capacity; j++)
                {
                    if (existingItems.Any(existingItem => slots[j].Contains(existingItem)))
                    {
                        slots[j].RemoveItem(existingItems.First());
                    }
                }
            }

            List <Item> stackedItems = new List <Item>();

            if (swapWholeStack)
            {
                for (int j = 0; j < otherInventory.capacity; j++)
                {
                    if (otherInventory.slots[j].Contains(item))
                    {
                        stackedItems.AddRange(otherInventory.slots[j].Items);
                        otherInventory.slots[j].RemoveAllItems();
                    }
                }
            }
            else
            {
                stackedItems.Add(item);
                otherInventory.slots[otherIndex].RemoveItem(item);
            }


            bool swapSuccessful = false;

            if (otherIsEquipped)
            {
                swapSuccessful =
                    stackedItems.Distinct().All(stackedItem => TryPutItem(stackedItem, index, false, false, user, createNetworkEvent))
                    &&
                    (existingItems.All(existingItem => otherInventory.TryPutItem(existingItem, otherIndex, false, false, user, createNetworkEvent)) ||
                     existingItems.Count == 1 && otherInventory.TryPutItem(existingItems.First(), user, CharacterInventory.anySlot, createNetworkEvent));
            }
            else
            {
                swapSuccessful =
                    (existingItems.All(existingItem => otherInventory.TryPutItem(existingItem, otherIndex, false, false, user, createNetworkEvent)) ||
                     existingItems.Count == 1 && otherInventory.TryPutItem(existingItems.First(), user, CharacterInventory.anySlot, createNetworkEvent))
                    &&
                    stackedItems.Distinct().All(stackedItem => TryPutItem(stackedItem, index, false, false, user, createNetworkEvent));

                if (!swapSuccessful && existingItems.Count == 1 && existingItems[0].AllowDroppingOnSwapWith(item))
                {
                    if (!(existingItems[0].Container?.ParentInventory is CharacterInventory characterInv) ||
                        !characterInv.TryPutItem(existingItems[0], user, new List <InvSlotType>()
                    {
                        InvSlotType.Any
                    }))
                    {
                        existingItems[0].Drop(user, createNetworkEvent);
                    }
                    swapSuccessful = stackedItems.Distinct().Any(stackedItem => TryPutItem(stackedItem, index, false, false, user, createNetworkEvent));
#if CLIENT
                    if (swapSuccessful)
                    {
                        SoundPlayer.PlayUISound(GUISoundType.DropItem);
                        if (otherInventory.visualSlots != null && otherIndex > -1)
                        {
                            otherInventory.visualSlots[otherIndex].ShowBorderHighlight(Color.Transparent, 0.1f, 0.1f);
                        }
                    }
#endif
                }
            }

            //if the item in the slot can be moved to the slot of the moved item
            if (swapSuccessful)
            {
                System.Diagnostics.Debug.Assert(slots[index].Contains(item), "Something when wrong when swapping items, item is not present in the inventory.");
                System.Diagnostics.Debug.Assert(!existingItems.Any(it => !it.Prefab.AllowDroppingOnSwap && !otherInventory.Contains(it)), "Something when wrong when swapping items, item is not present in the other inventory.");
#if CLIENT
                if (visualSlots != null)
                {
                    for (int j = 0; j < capacity; j++)
                    {
                        if (slots[j].Contains(item))
                        {
                            visualSlots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.9f);
                        }
                    }
                    for (int j = 0; j < otherInventory.capacity; j++)
                    {
                        if (otherInventory.slots[j].Contains(existingItems.FirstOrDefault()))
                        {
                            otherInventory.visualSlots[j].ShowBorderHighlight(GUI.Style.Green, 0.1f, 0.9f);
                        }
                    }
                }
#endif
                return(true);
            }
            else //swapping the items failed -> move them back to where they were
            {
                if (swapWholeStack)
                {
                    foreach (Item stackedItem in stackedItems)
                    {
                        for (int j = 0; j < capacity; j++)
                        {
                            if (slots[j].Contains(stackedItem))
                            {
                                slots[j].RemoveItem(stackedItem);
                            }
                            ;
                        }
                    }
                    foreach (Item existingItem in existingItems)
                    {
                        for (int j = 0; j < otherInventory.capacity; j++)
                        {
                            if (otherInventory.slots[j].Contains(existingItem))
                            {
                                otherInventory.slots[j].RemoveItem(existingItem);
                            }
                        }
                    }
                }
                else
                {
                    for (int j = 0; j < capacity; j++)
                    {
                        if (slots[j].Contains(item))
                        {
                            slots[j].RemoveWhere(it => existingItems.Contains(it) || stackedItems.Contains(it));
                        }
                    }
                    for (int j = 0; j < otherInventory.capacity; j++)
                    {
                        if (otherInventory.slots[j].Contains(existingItems.FirstOrDefault()))
                        {
                            otherInventory.slots[j].RemoveWhere(it => existingItems.Contains(it) || stackedItems.Contains(it));
                        }
                    }
                }

                if (otherIsEquipped)
                {
                    existingItems.ForEach(existingItem => TryPutItem(existingItem, index, false, false, user, createNetworkEvent));
                    stackedItems.ForEach(stackedItem => otherInventory.TryPutItem(stackedItem, otherIndex, false, false, user, createNetworkEvent));
                }
                else
                {
                    stackedItems.ForEach(stackedItem => otherInventory.TryPutItem(stackedItem, otherIndex, false, false, user, createNetworkEvent));
                    existingItems.ForEach(existingItem => TryPutItem(existingItem, index, false, false, user, createNetworkEvent));
                }

#if CLIENT
                if (visualSlots != null)
                {
                    for (int j = 0; j < capacity; j++)
                    {
                        if (slots[j].Contains(existingItems.FirstOrDefault()))
                        {
                            visualSlots[j].ShowBorderHighlight(GUI.Style.Red, 0.1f, 0.9f);
                        }
                    }
                }
#endif
                return(false);
            }
        }
        private void ApplyImpact(float impact, Vector2 direction, Contact contact)
        {
            if (impact < 3.0f)
            {
                return;
            }

            Vector2 tempNormal;
            FixedArray2 <Vector2> worldPoints;

            contact.GetWorldManifold(out tempNormal, out worldPoints);

            Vector2 lastContactPoint = worldPoints[0];

            if (Character.Controlled != null && Character.Controlled.Submarine == submarine)
            {
                GameMain.GameScreen.Cam.Shake = impact * 2.0f;
            }

            Vector2 impulse = direction * impact * 0.5f;

            impulse = impulse.ClampLength(5.0f);
            foreach (Character c in Character.CharacterList)
            {
                if (c.Submarine != submarine)
                {
                    continue;
                }
                if (impact > 2.0f)
                {
                    c.SetStun((impact - 2.0f) * 0.1f);
                }

                foreach (Limb limb in c.AnimController.Limbs)
                {
                    limb.body.ApplyLinearImpulse(limb.Mass * impulse, 20.0f);
                }
                c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse, 20.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, 20.0f);
            }

            var damagedStructures = Explosion.RangedStructureDamage(ConvertUnits.ToDisplayUnits(lastContactPoint), impact * 50.0f, impact * ImpactDamageMultiplier);

#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(lastContactPoint),
                    MathHelper.Clamp(maxDamage * 4.0f, 1000.0f, 4000.0f),
                    maxDamageStructure.Tags);
            }
#endif
        }
Example #17
0
        private void ApplyImpact(float impact, Vector2 direction, Contact contact, bool applyDamage = true)
        {
            float minImpact = 3.0f;

            if (impact < minImpact)
            {
                return;
            }

            contact.GetWorldManifold(out Vector2 tempNormal, out FixedArray2 <Vector2> worldPoints);
            Vector2 lastContactPoint = worldPoints[0];

            Vector2 impulse = direction * impact * 0.5f;

            impulse = impulse.ClampLength(5.0f);

            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;
                float angularVelocity =
                    (lastContactPoint.X - Body.SimPosition.X) / ConvertUnits.ToSimUnits(submarine.Borders.Width / 2) * impulse.Y
                    - (lastContactPoint.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 (impact > 2.0f)
                {
                    c.SetStun((impact - 2.0f) * 0.1f);
                }

                foreach (Limb limb in c.AnimController.Limbs)
                {
                    limb.body.ApplyLinearImpulse(limb.Mass * impulse, 20.0f);
                }
                c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse, 20.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, 20.0f);
            }

            var damagedStructures = Explosion.RangedStructureDamage(
                ConvertUnits.ToDisplayUnits(lastContactPoint),
                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(lastContactPoint),
                    MathHelper.Lerp(2000.0f, 10000.0f, (impact - minImpact) / 2.0f),
                    maxDamageStructure.Tags);
            }
#endif
        }