using Barotrauma.Networking; using System.Collections.Generic; using System.Collections.Immutable; namespace Barotrauma { partial class EndMission : Mission { public override bool DisplayAsCompleted => false; public override bool DisplayAsFailed => false; partial void OnStateChangedProjSpecific() { SoundPlayer.ForceMusicUpdate(); if (Phase == MissionPhase.NoItemsDestroyed) { CoroutineManager.Invoke(() => { if (boss != null && !boss.Removed) { new CameraTransition(boss, GameMain.GameScreen.Cam, null, Alignment.Center, panDuration: 8, fadeOut: false, startZoom: 1.0f, endZoom: 0.3f * GUI.yScale) { RunWhilePaused = false, EndWaitDuration = 3.0f }; } }, delay: 3.0f); } else if (Phase == MissionPhase.AllItemsDestroyed) { CoroutineManager.StartCoroutine(wakeUpCoroutine(), name: "EndMission.wakeUpCoroutine"); } else if (Phase == MissionPhase.BossKilled) { if (!string.IsNullOrEmpty(endCinematicSound)) { SoundPlayer.PlaySound(endCinematicSound); } CoroutineManager.Invoke(() => { new CameraTransition(boss, GameMain.GameScreen.Cam, null, Alignment.Center, panDuration: 3, fadeOut: false, endZoom: 0.1f * GUI.yScale) { RunWhilePaused = false, EndWaitDuration = float.PositiveInfinity }; }, delay: 3.0f); } IEnumerable wakeUpCoroutine() { yield return new WaitForSeconds(wakeUpCinematicDelay); if (boss != null && !boss.Removed) { new CameraTransition(boss, GameMain.GameScreen.Cam, null, Alignment.Center, panDuration: 5.0f, fadeOut: false, losFadeIn: false, startZoom: 1.0f, endZoom: 0.4f * GUI.yScale) { RunWhilePaused = false, EndWaitDuration = cameraWaitDuration }; } yield return new WaitForSeconds(bossWakeUpDelay); if (boss != null && !boss.Removed) { foreach (var limb in boss.AnimController.Limbs) { if (!limb.FreezeBlinkState) { continue; } limb.FreezeBlinkState = false; if (limb.LightSource is Lights.LightSource light) { light.Enabled = true; } } } } } partial void UpdateProjSpecific() { if (boss == null || boss.Removed) { return; } if (Phase is MissionPhase.Initial or MissionPhase.NoItemsDestroyed or MissionPhase.SomeItemsDestroyed) { // Put asleep. // Have to set the light every frame (or at least periodically), because light.Enabled is changed when Character.IsVisible changes (off/on screen). See GameScreen.Draw(). foreach (var limb in boss.AnimController.Limbs) { if (limb.Params.BlinkFrequency > 0) { limb.FreezeBlinkState = true; limb.BlinkPhase = -limb.Params.BlinkHoldTime; if (limb.LightSource is Lights.LightSource light) { light.Enabled = false; } } } } #if DEBUG if (PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.O)) { State = 0; } if (PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Y)) { destructibleItems.ForEach(it => it.Condition = 0.0f); } if (PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.U)) { boss?.SetAllDamage(20000.0f, 0.0f, 0.0f); } #endif } public override void ClientReadInitial(IReadMessage msg) { base.ClientReadInitial(msg); boss = Character.ReadSpawnData(msg); byte minionCount = msg.ReadByte(); List minionList = new List(); for (int i = 0; i < minionCount; i++) { var minion = Character.ReadSpawnData(msg); if (minion == null) { throw new System.Exception($"Error in EndMission.ClientReadInitial: failed to create a minion (mission: {Prefab.Identifier}, index: {i})"); } minionList.Add(minion); } minions = minionList.ToImmutableArray(); if (minions.Length != minionCount) { throw new System.Exception("Error in EndMission.ClientReadInitial: minion count does not match the server count (" + minionCount + " != " + minions.Length + "mission: " + Prefab.Identifier + ")"); } } } }