280 lines
11 KiB
C#
280 lines
11 KiB
C#
using Code.App.Loading;
|
||
using Code.App.StateMachine;
|
||
using Code.Audio;
|
||
using Code.Gameplay.Camera;
|
||
using Code.Gameplay.Camera.CameraStates;
|
||
using Code.Gameplay.Character.Core;
|
||
using Code.Gameplay.Orders.Order;
|
||
using Code.Gameplay.Player;
|
||
using Code.Input;
|
||
using Code.Scenes;
|
||
using Code.Scenes.SceneEnvironments;
|
||
using Code.StateMachine;
|
||
using Code.UI;
|
||
using Code.UI.Panels;
|
||
using Cysharp.Threading.Tasks;
|
||
using DG.Tweening;
|
||
using Reflex.Core;
|
||
using Reflex.Extensions;
|
||
using UnityEngine;
|
||
using UnityEngine.InputSystem;
|
||
using UnityEngine.Rendering;
|
||
using UnityEngine.SceneManagement;
|
||
|
||
namespace Code.App.AppStates
|
||
{
|
||
public class GameplayState : BaseState<AppStateMachineContext>
|
||
{
|
||
private PlayerHealth _playerHealth;
|
||
private IPlayerScore _playerScore;
|
||
|
||
private IOrderService _orderService;
|
||
|
||
private CharacterProvider _playerCharacter;
|
||
public GameplayState(AppStateMachineContext context) : base(context)
|
||
{
|
||
}
|
||
|
||
public override void EnterState()
|
||
{
|
||
Context.UIService.LoadingScreen.Show();
|
||
|
||
Context.LoadingManager
|
||
.RegisterLoading(LoadingWork.LoadScene)
|
||
.RegisterLoading(LoadingWork.LoadUI)
|
||
.RegisterLoading(LoadingWork.LoadModelResource)
|
||
.RegisterLoading(LoadingWork.LoadAudio);
|
||
|
||
Context.AudioService.TransitToSnapshot(AudioSnapshotState.None);
|
||
|
||
Context.InputService.EnableMap(ActionMappings.Gameplay);
|
||
|
||
Context.InputService.DebugBindAction((int)ActionMappings.Debug, (int)DebugActions.Debug1, InstaKillDEBUG);
|
||
Context.InputService.DebugBindAction((int)ActionMappings.Debug, (int)DebugActions.Debug4, TakeGamageDEBUG);
|
||
|
||
Context.SceneLoaderService.LoadSceneAsyncAwaitable((int)SceneIds.DevGen);
|
||
Context.LoadingManager.OnLoadingEnded += AfterSceneLoaded;
|
||
|
||
WaitForLoad().Forget();
|
||
}
|
||
private async UniTask WaitForPlayerCharacterLoad() => _playerCharacter = await Context.PlayerFactory.CreatePlayer();
|
||
|
||
private async UniTaskVoid WaitForLoad()
|
||
{
|
||
await UniTask.WhenAll(
|
||
Context.UIService.AsyncSwitchPanelTo(UIPanel.Gameplay),
|
||
Context.AudioFactory.WarmGameplayMusic(),
|
||
Context.AudioFactory.WarmDeathMusic(),
|
||
// Context.AudioFactory.WarmSFX(),
|
||
Context.AudioFactory.WarmDispatcher(),
|
||
Context.AudioFactory.WarmEnemies(),
|
||
Context.AudioFactory.WarmCourier()
|
||
);
|
||
|
||
Context.LoadingManager
|
||
.UnregisterLoading(LoadingWork.LoadUI)
|
||
.UnregisterLoading(LoadingWork.LoadAudio);
|
||
|
||
InputServiceInitialize();
|
||
|
||
MusicInitialize();
|
||
}
|
||
|
||
private async void AfterSceneLoaded()
|
||
{
|
||
Context.LoadingManager
|
||
.RegisterLoading(LoadingWork.LoadModelResource);
|
||
|
||
Context.LoadingManager.OnLoadingEnded -= AfterSceneLoaded;
|
||
Context.LoadingManager.OnLoadingEnded += AfterPlayerLoaded;
|
||
|
||
Context.PlayerProvider = SceneManager.GetActiveScene().GetSceneContainer().Resolve<IPlayerProvider>();
|
||
Context.PlayerFactory = SceneManager.GetActiveScene().GetSceneContainer().Resolve<IPlayerFactory>();
|
||
|
||
await UniTask.WhenAll(
|
||
WaitForPlayerArmsToInitialize(),
|
||
WaitForPlayerCharacterLoad()
|
||
);
|
||
|
||
_playerHealth = Context.PlayerProvider.Health;
|
||
_playerHealth.OnDamage += PlayerDamageTaken;
|
||
_playerHealth.OnDeath += EndGame;
|
||
|
||
Context.LoadingManager
|
||
.UnregisterLoading(LoadingWork.LoadModelResource);
|
||
}
|
||
|
||
private void AfterPlayerLoaded()
|
||
{
|
||
Container sceneContainer = SceneManager.GetActiveScene().GetSceneContainer();
|
||
|
||
_playerScore = sceneContainer.Resolve<IPlayerScore>();
|
||
|
||
GameplaySceneEnvironment sceneEnvironment = SceneEnvironmentVariables(sceneContainer);
|
||
|
||
_volume = sceneEnvironment.volume;
|
||
|
||
PlayerInitialize(sceneEnvironment);
|
||
|
||
CameraInitialize();
|
||
|
||
GameplayServicesInitialize(sceneContainer);
|
||
|
||
UIInitialize();
|
||
|
||
Context.LoadingManager.OnLoadingEnded -= AfterPlayerLoaded;
|
||
|
||
_tickEnabled = true;
|
||
}
|
||
|
||
private async UniTask WaitForPlayerArmsToInitialize() => _armsMesh = await Context.PlayerFactory.CreateArms(Context.CameraStateMachine.Camera.transform);
|
||
|
||
private void OrderGiven(float time)
|
||
{
|
||
_gameplayPanel.ShowTimer();
|
||
Context.AudioService.TransitToSnapshot(AudioSnapshotState.Action);
|
||
}
|
||
private void OrderFailure()
|
||
{
|
||
_playerHealth.InstaKill();
|
||
}
|
||
private void OrderRecieved(float time)
|
||
{
|
||
Context.AudioService.PlayDispatcher((DispatcherSounds)Random.Range((int)DispatcherSounds.Recieve1,(int)DispatcherSounds.Recieve2 + 1));
|
||
}
|
||
private void OrderDelivered(int score, float time)
|
||
{
|
||
_gameplayPanel.HideTimer();
|
||
|
||
if(time < 0f) Context.AudioService.PlayDispatcher((DispatcherSounds)Random.Range((int)DispatcherSounds.Late1,(int)DispatcherSounds.Late2 + 1));
|
||
_playerScore.UpdateScore(score);
|
||
|
||
Context.AudioService.TransitToSnapshot(AudioSnapshotState.Peaceful);
|
||
}
|
||
|
||
private void PlayerDamageTaken(int damage, PlayerHealth health)
|
||
{
|
||
Context.AudioService.PlayDispatcher((DispatcherSounds)Random.Range((int)DispatcherSounds.TakeDamage1,(int)DispatcherSounds.TakeDamage4 + 1));
|
||
Context.AudioService.PlayCourier((CourierSounds)Random.Range((int)CourierSounds.Damage1,(int)CourierSounds.Damage2 + 1));
|
||
DamageEffectProcess().Forget();
|
||
}
|
||
|
||
// TODO В конфиг
|
||
private async UniTaskVoid DamageEffectProcess()
|
||
{
|
||
_damagePanel.Show();
|
||
Context.AudioService.ApplyStun(200, 0.5f);
|
||
|
||
DOTween.To(() => _volume.weight, x => _volume.weight = x, 1f, 0.5f);
|
||
await UniTask.WaitForSeconds(3f);
|
||
DOTween.To(() => _volume.weight, x => _volume.weight = x, 0f, 1f);
|
||
Context.AudioService.ApplyStun(5000, 1f);
|
||
_damagePanel.Hide();
|
||
}
|
||
// DEBUG
|
||
private void InstaKillDEBUG(InputAction.CallbackContext context)
|
||
{
|
||
_playerHealth.InstaKill();
|
||
}
|
||
private void TakeGamageDEBUG(InputAction.CallbackContext context)
|
||
{
|
||
_playerHealth.GetDamage(1);
|
||
}
|
||
// DEBUG
|
||
private bool _tickEnabled;
|
||
public override void Tick()
|
||
{
|
||
if (!_tickEnabled) return;
|
||
|
||
_orderService.DecreaseTimer(Time.deltaTime);
|
||
}
|
||
|
||
private void EndGame()
|
||
{
|
||
Context.StateMachine.SwitchState(AppState.GameOver)
|
||
.AllowStateTransition(AppState.MainMenu);
|
||
}
|
||
|
||
public override void ExitState()
|
||
{
|
||
_playerHealth = null;
|
||
_playerScore = null;
|
||
|
||
_tickEnabled = false;
|
||
|
||
Context.PlayerFactory.ReleasePlayer(_playerCharacter);
|
||
_playerCharacter = null;
|
||
Context.PlayerFactory.ReleaseArms(_armsMesh);
|
||
_armsMesh = null;
|
||
_orderService = null;
|
||
|
||
Context.AudioService.OnDispatcherStarted -= _gameplayPanel.SummonDispatcher;
|
||
Context.AudioService.OnDispatcherEnded -= _gameplayPanel.CloseDispatcher;
|
||
|
||
Context.InputService.DisableMap(ActionMappings.Gameplay);
|
||
Context.AudioService.GladlyAskToStopMusic(MusicType.Action, time: 0f, callback: Context.AudioFactory.ReleaseActionMusic);
|
||
Context.AudioService.GladlyAskToStopMusic(MusicType.Peaceful, time: 0f, callback: Context.AudioFactory.ReleasePeacefulMusic);
|
||
Context.AudioFactory.ReleaseCourier();
|
||
Context.AudioFactory.ReleaseDispatcher();
|
||
Context.AudioFactory.ReleaseEnemies();
|
||
// Context.AudioFactory.ReleaseSFX();
|
||
|
||
|
||
Context.InputService.DebugUnbindAction((int)ActionMappings.Debug, (int)DebugActions.Debug1, InstaKillDEBUG);
|
||
Context.InputService.DebugUnbindAction((int)ActionMappings.Debug, (int)DebugActions.Debug4, TakeGamageDEBUG);
|
||
|
||
base.ExitState();
|
||
}
|
||
|
||
private void InputServiceInitialize()
|
||
{
|
||
Context.InputService.EnableMap(ActionMappings.Gameplay);
|
||
}
|
||
private void CameraInitialize()
|
||
{
|
||
Context.CameraStateMachine.SwitchState(CameraMode.FirstPerson);
|
||
((BaseCameraState)Context.CameraStateMachine.CurrentBaseState).SetFollowTransform(_playerCharacter.GetFollowTransform());
|
||
}
|
||
|
||
private GameplayPanel _gameplayPanel;
|
||
private ArmsMeshProvider _armsMesh;
|
||
private DamagePanel _damagePanel;
|
||
private void UIInitialize()
|
||
{
|
||
_gameplayPanel = (GameplayPanel)Context.UIService.CurrentPanel;
|
||
_gameplayPanel.Initialize(_playerScore, _playerHealth, _orderService);
|
||
Context.AudioService.OnDispatcherStarted += _gameplayPanel.SummonDispatcher;
|
||
Context.AudioService.OnDispatcherEnded += _gameplayPanel.CloseDispatcher;
|
||
|
||
_damagePanel = _gameplayPanel.DamagePanel;
|
||
}
|
||
private void MusicInitialize()
|
||
{
|
||
Context.AudioService.PlayRandomMusicUntilHumanityWillBeDestroyedForTheySins(MusicType.Peaceful);
|
||
Context.AudioService.PlayRandomMusicUntilHumanityWillBeDestroyedForTheySins(MusicType.Action);
|
||
Context.AudioService.TransitToSnapshot(AudioSnapshotState.Peaceful);
|
||
}
|
||
private void PlayerInitialize(GameplaySceneEnvironment sceneEnvironment)
|
||
{
|
||
_playerCharacter.Teleport(sceneEnvironment.playerSpawnPoint.position, sceneEnvironment.playerSpawnPoint.rotation);
|
||
_playerCharacter.PlayerAnimator.SetAnimator(_armsMesh.ArmsAnimator);
|
||
}
|
||
private void GameplayServicesInitialize(Container sceneContainer)
|
||
{
|
||
_orderService = sceneContainer.Resolve<IOrderService>();
|
||
|
||
_orderService.OnOrderGiven += OrderGiven;
|
||
_orderService.OnOrderRecieved += OrderRecieved;
|
||
_orderService.OnOrderDelivered += OrderDelivered;
|
||
_orderService.OnOrderFailure += OrderFailure;
|
||
}
|
||
|
||
private Volume _volume;
|
||
private GameplaySceneEnvironment SceneEnvironmentVariables(Container sceneContainer)
|
||
{
|
||
var sceneEnvironment = (GameplaySceneEnvironment)sceneContainer.Resolve<CurrentSceneEnvironment>();
|
||
|
||
return sceneEnvironment;
|
||
}
|
||
}
|
||
} |