using asap.core; using System.Threading.Tasks; using UniRx; using UnityEngine.AddressableAssets; using UnityEngine; using System.Collections.Generic; using cfg; using System; using game; using GameCore; using System.Linq; using DG.Tweening; using System.Collections; public class ShooterFishAct : AGameAct { AquariumShooterFishManager AM; CompositeDisposable disposables; GameObject aquarium; cfg.Tables _tables; AquariumInit aquariumInit; Material mutantMaterial; GameObject fxLeftEye; GameObject fxRightEye; AquariumFishController aquariumFishController; Dictionary fishUnDownloadAlter = new Dictionary(); OpponentItemData localOpponentItemData; FishMovement targetMovement; EventFishHuntingPanel eventFishHuntingPanel; bool shoot = false; [Header("General Settings")] public float[] FxScale;//不同品质的鱼的特效缩放大小 Dictionary fx_hunt_prefab = new Dictionary(); [Header("Aim Settings")] public float AimCameraMoveDelay = 0.05f;//延迟这么久开始挪动相机 public float AimCameraMoveTime = 0.4f;//相机后续挪动时间,挪到位置后 public Vector3 AimCameraMovePos;//相机挪到这个位置 public AnimationCurve AimCameraMoveCurve = AnimationCurve.Linear(0, 1, 1, 1); //时间缩放曲线 float fieldOfView = 60; [Header("Back Settings")] public float BackShowDelay = 0.1f;//延迟这么久开始显示弩箭 public float BackCameraMoveTime = 0.25f;//相机后续挪动时间 public float AimBlockTime = 0.25f;//相机挪回去之后,在这段时间内禁止开镜射鱼 [Header("Shoot Settings")] public float ShootTime = 1; public float ShootDelay = 0.2f;//延迟这么久干掉弩箭模型 public float timeStartScale = 0.5f; //开始慢镜头时间 public float timeEndScale = 1f; //结束慢镜头时间 public AnimationCurve timeScaleCurve = AnimationCurve.Linear(0, 1, 1, 1); //时间缩放曲线 public Vector3 reasonableLocation; public Vector3 reasonableCenter; public float reasonableMinDistance = 2; public float reasonableMaxDistance = 5; public float[] shootSwimSpeed = new float[2] { 1.25f, 1.75f }; //射鱼时鱼的最小速度,最大速度 [Header("Escape Settings")] public AnimationCurve EscapeShockCurve = AnimationCurve.Linear(0, 1, 1, 1); //在这段时间里,位移一个距离的受击位移曲线 public float[] EscapeShockTime;//不同品质的鱼的受击时间 public float[] EscapeShockDistance;//不同品质的鱼的受击距离 public float EscapeDelay = 0.5f;//鱼的Hurt01动画播放时间,延迟这么久箭会脱落 public float EscapeDistance = 30; public float EscapeDuration = 2; public float EscapeAnimSpeed = 3;//鱼逃跑时动画播放的速度 public float EscapeAnimRecoverTime = 1.5f;//鱼逃跑时动画恢复的时间 public float escapeRewardUIDelay = 1.25f;//鱼开始游走算起,多长时间出现结算UI public float ArrowEscapeTime = 2; [Header("Capture Settings")] public AnimationCurve CaptureShockCurve = AnimationCurve.Linear(0, 1, 1, 1); //在这段时间里,位移一个距离的受击位移曲线 public float[] CaptureShockTime;//不同品质的鱼的受击时间 public float[] CaptureShockDistance;//不同品质的鱼的受击距离 public float CaptureDelay = 1.16f;//鱼的Hurt02动画播放时间,延迟这么久往回拉 public float lineDrawSpeed = 4f;//每秒往回拉的距离 public float lineDrawMinTime = 1.25f;//最少也得拉这么长时间 public float fishAnimMinSpeed = 1.5f; public float fishAnimMaxSpeed = 3; public float addRotation = 15; public float addRotationPeriod = 0.75f;//拉回时,每间隔这段时间,鱼会从-addRotation到+addRotation中随机一个值,然后摆动过去 public float fishToCameraDistance = 1f;//额外的距离 public float fishDisappearDelay = 0.4f;//拉回来后,鱼延迟消失的时间 public override async Task StartAsync() { UIManager.Instance.DestroyUI(UITypes.EventGamePlayPanel); _tables = GContext.container.Resolve(); aquariumInit = _tables.TbAquariumInit.DataList[0]; disposables = new CompositeDisposable(); GContext.container.Unregister(); AM = new AquariumShooterFishManager(); GContext.container.RegisterInstance(AM); localOpponentItemData = GContext.container.Resolve().GetBankHeistOpponent(EnemyType.Aquarium); List huntInits = _tables.TbFishHuntInit.DataList; if (GContext.container.Resolve().FishHuntGameCount < huntInits.Count && GContext.container.Resolve().fishingEvent == null) { FishHuntInit inti = huntInits[GContext.container.Resolve().FishHuntGameCount]; var itemDatas = GContext.container.Resolve().opponentItemDatas.Where(x => x.isRobot).ToList(); //机器人数据 localOpponentItemData = itemDatas[UnityEngine.Random.Range(0, itemDatas.Count)]; GContext.container.Resolve().opponentData = localOpponentItemData; AM.GetDataFishHuntInit(localOpponentItemData.playFabID, inti); } else { await AM.GetData(localOpponentItemData.playFabID, localOpponentItemData.isRobot, false); if (AM.serverData == null) { var itemDatas = GContext.container.Resolve().opponentItemDatas.Where(x => x.isRobot).ToList(); //机器人数据 localOpponentItemData = itemDatas[UnityEngine.Random.Range(0, itemDatas.Count)]; localOpponentItemData.target_group = GContext.container.Resolve().opponentData.target_group; GContext.container.Resolve().opponentData = localOpponentItemData; await AM.GetData(localOpponentItemData.playFabID, localOpponentItemData.isRobot, false); } } GContext.OnEvent().Subscribe(ChangeSmallGameTargetEvent).AddTo(disposables); // 加载场景 mutantMaterial = await Addressables.LoadAssetAsync(_tables.TbFishMutant.Material).Task; fxLeftEye = await Addressables.LoadAssetAsync(_tables.TbFishMutant.FxLeftEye).Task; fxRightEye = await Addressables.LoadAssetAsync(_tables.TbFishMutant.FxRightEye).Task; await LoadFX(); await EnterMapScene(); return await base.StartAsync(); } async Task LoadFX() { ///fx_aquarium_hunt_shoot ///fx_aquarium_hunt_fishhitbig ///fx_aquarium_hunt_fishhitsmall ///fx_aquarium_hunt_fishhurt ///fx_aquarium_hunt_escape ///fx_aquarium_hunt_capture GameObject fx_aquarium_hunt_shoot = await Addressables.LoadAssetAsync("fx_aquarium_hunt_shoot").Task; if (fx_aquarium_hunt_shoot != null) { fx_hunt_prefab["fx_aquarium_hunt_shoot"] = fx_aquarium_hunt_shoot; } GameObject fx_aquarium_hunt_fishhitbig = await Addressables.LoadAssetAsync("fx_aquarium_hunt_fishhitbig").Task; if (fx_aquarium_hunt_fishhitbig != null) { fx_hunt_prefab["fx_aquarium_hunt_fishhitbig"] = fx_aquarium_hunt_fishhitbig; } GameObject fx_aquarium_hunt_fishhitsmall = await Addressables.LoadAssetAsync("fx_aquarium_hunt_fishhitsmall").Task; if (fx_aquarium_hunt_fishhitsmall != null) { fx_hunt_prefab["fx_aquarium_hunt_fishhitsmall"] = fx_aquarium_hunt_fishhitsmall; } GameObject fx_aquarium_hunt_fishhurt = await Addressables.LoadAssetAsync("fx_aquarium_hunt_fishhurt").Task; if (fx_aquarium_hunt_fishhurt != null) { fx_hunt_prefab["fx_aquarium_hunt_fishhurt"] = fx_aquarium_hunt_fishhurt; } GameObject fx_aquarium_hunt_escape = await Addressables.LoadAssetAsync("fx_aquarium_hunt_escape").Task; if (fx_aquarium_hunt_escape != null) { fx_hunt_prefab["fx_aquarium_hunt_escape"] = fx_aquarium_hunt_escape; } GameObject fx_aquarium_hunt_capture = await Addressables.LoadAssetAsync("fx_aquarium_hunt_capture").Task; if (fx_aquarium_hunt_capture != null) { fx_hunt_prefab["fx_aquarium_hunt_capture"] = fx_aquarium_hunt_capture; } } public async void ChangeSmallGameTargetEvent(ChangeSmallGameTargetEvent changeSmallGameTargetEvent) { await UIManager.Instance.ShowUI(UITypes.CloudTransitionPanel); OpponentItemData opponentItemData = changeSmallGameTargetEvent.opponentItemData; AquariumServerData data = await AM.GetData(opponentItemData.playFabID, opponentItemData.isRobot, !changeSmallGameTargetEvent.random); if (data == null) { var itemDatas = GContext.container.Resolve().opponentItemDatas.Where(x => x.isRobot).ToList(); //机器人数据 opponentItemData = itemDatas[UnityEngine.Random.Range(0, itemDatas.Count)]; opponentItemData.target_group = GContext.container.Resolve().opponentData.target_group; GContext.container.Resolve().opponentData = opponentItemData; data = await AM.GetData(opponentItemData.playFabID, opponentItemData.isRobot, false); } await Task.Delay(500); if (data != null) { changeSmallGameTargetEvent.opponentItemData = opponentItemData; localOpponentItemData = opponentItemData; //机器人数据 if (aquarium != null) { Addressables.ReleaseInstance(aquarium); aquarium = null; } await EnterMapScene(); } else { GContext.container.Resolve().opponentData = localOpponentItemData; } changeSmallGameTargetEvent.ts.SetResult(data != null); GContext.Publish(new EndTransition()); } async Task EnterMapScene() { List slotDatas = AM.serverData.slotDatas; for (int i = 0; i < slotDatas.Count; i++) { AquariumSlotData slotData = slotDatas[i]; Item item = _tables.TbItem.GetOrDefault(slotData.fishItemID); if (!fishUnDownloadAlter.ContainsKey(item.Quality - 1)) { int id = _tables.GetItemData(_tables.TbGlobalConfig.FishUnDownloadAlter[item.Quality - 1]).RedirectID; FishData fishData = _tables.TbFishData.GetOrDefault(id); fishUnDownloadAlter[item.Quality - 1] = await Addressables.LoadAssetAsync(fishData.Fbx).Task; } } await LoadScene(); Debug.Log($"EnterMap OpponentData playerID {localOpponentItemData.playFabID}"); InitFish(); await Awaiters.Seconds(1); StartTime(); ShowCrossbowLow(); } async void ShowCrossbowLow() { await Awaiters.Seconds(0.5f); GameObject panel = await UIManager.Instance.ShowUINotLoading(UITypes.EventFishHuntingPanel); eventFishHuntingPanel = panel.GetComponent(); eventFishHuntingPanel.shooterFishAct = this; bool isGuide = GContext.container.Resolve().InspectTriggerGuide("EventFishHuntingPanel"); FishMovement guide = null; if (isGuide && GContext.container.Resolve().curGroupDefine.groupName == GroupName.Raid) { guide = GetMutantFish(); } aquariumFishController.cameraManager.PlayCrossbow(guide); } async Task LoadScene() { var mapData = _tables.TbMapData.DataMap[AM.MapId]; string prefabName = mapData.AquariumPrefab; if (prefabName != "aquarium02") { ILoadResourceService loadResourceService = GContext.container.Resolve(); bool loadResult = await loadResourceService.CheckResource(prefabName); if (!loadResult) { Debug.LogError($"check resource failed prefabName:{prefabName}"); prefabName = "aquarium02"; } } aquarium = await Addressables.InstantiateAsync(prefabName).Task; aquariumFishController = aquarium.GetComponent(); aquariumFishController.fishManager.MaxLoadTime = 3f; } void InitFish() { Debug.Log($"nextOpponent InitFish MapID {AM.serverData.mapId}"); List slotDatas = AM.serverData.slotDatas; if (slotDatas == null) { return; } aquariumFishController.fishManager.fishUnDownloadAlter = fishUnDownloadAlter; var time = ZZTimeHelper.UtcNow(); List aquariumResultDatas = AM.serverData.aquariumResultDatas; string[] cardLv = AM.GetCardLv(); for (int i = 0; i < slotDatas.Count; i++) { AquariumSlotData slotData = slotDatas[i]; slotData.index = i; var HatchTime = slotData.FishHatchTime(); string cardLvStr = ""; if (i < cardLv.Length) { cardLvStr = cardLv[i]; } if (HatchTime < time) { if (!slotData.IsResult() && i < aquariumResultDatas.Count && i < AM.serverData.aquariumHurtDatas.Count && !aquariumResultDatas[i].IsResult()) { //检查是否受伤 //正常的成长时间 自然时间+加速成长-总恢复时间 float normalH = (float)(time - HatchTime).TotalHours + slotData.accelerationGrowth - slotData.allRecoveryTime; float injuryH = slotData.injuryGrowthTime; int fishQ = slotData.fishMQ; if (injuryH < normalH) { AM.serverData.aquariumHurtDatas[i].fishLQ = 0; } else { fishQ -= AM.serverData.aquariumHurtDatas[i].fishLQ; if (fishQ <= 0) { fishQ = 1; } } AddFish(slotData, cardLvStr, i, fishQ); } } //else //{ // //初始化蛋 // aquariumFishController.fishEggManager.AddEgg(i, slotData.eggId); //} } } void StartTime() { List slotDatas = AM.serverData.slotDatas; List aquariumResultDatas = AM.serverData.aquariumResultDatas; for (int i = 0; i < slotDatas.Count; i++) { if (aquariumResultDatas.Count > 1 && !aquariumResultDatas[i].IsResult() && !slotDatas[i].IsResult()) { SetFishScale(slotDatas[i], i); } } } /// /// 加载鱼的模型 /// /// /// void AddFish(AquariumSlotData aquariumSlotData, string cardLv, int index, int count) { int huntResult = -1, dropID = 0; if (AM.HuntResult != null && AM.HuntResult.Contains(index)) { huntResult = AM.HuntResult[index]; dropID = AM.DropID[index]; } aquariumFishController.fishManager.AddFish( mutantMaterial, fxLeftEye, fxRightEye, aquariumSlotData, cardLv, count, index, huntResult, dropID); } FishMovement GetMutantFish() { List slotDatas = AM.serverData.slotDatas; AquariumSlotData aquariumSlotData = null; for (int i = 0; i < slotDatas.Count; i++) { aquariumSlotData = slotDatas[i]; if (aquariumSlotData.mutants > 0) { break; } } return aquariumFishController.fishManager.GetFish(aquariumSlotData.index); } /// /// 刷新鱼的大小 /// /// /// void SetFishScale(AquariumSlotData slotData, int index) { var dateTime = ZZTimeHelper.UtcNow(); DateTime startTime = slotData.FishHatchTime(); float normalH = (float)(dateTime - startTime).TotalHours + slotData.accelerationGrowth - slotData.allRecoveryTime; float progress = normalH / slotData.growthTime; if (progress > 1) { progress = 1; } Item item = _tables.TbItem.GetOrDefault(slotData.fishItemID); FishData fishData = _tables.TbFishData.GetOrDefault(item.RedirectID); float scale = fishData.AquariumMinScale + (fishData.AquariumMaxScale - fishData.AquariumMinScale) * progress; aquariumFishController.fishManager.SetFishScale(index, scale, slotData.mutants, _tables.TbFishMutant.AquariumScale[fishData.Quality - 1]); } public void OnTargetChange(FishMovement fish) { this.targetMovement = fish; } public IEnumerator AniCameraMove() { GContext.Publish(EShootState.Aim); shoot = false; aquariumFishController.cameraManager.TriggerCrossbow("Aim"); yield return new WaitForSeconds(AimCameraMoveDelay); DOTween.Kill("FieldOfView"); aquariumFishController.cameraManager.cameraVirtual.transform.DOKill(); aquariumFishController.cameraManager.cameraVirtual.transform.DOLocalMove(AimCameraMovePos, AimCameraMoveTime) .SetEase(AimCameraMoveCurve); cfg.Crossbow crossBow = _tables.TbCrossbow.DataList[0]; float fov = aquariumFishController.cameraManager.cameraVirtual.m_Lens.FieldOfView; DOTween.To(() => fov, x => fov = x, crossBow.AimFov, AimCameraMoveTime).OnUpdate(() => { aquariumFishController.cameraManager.cameraVirtual.m_Lens.FieldOfView = fov; }).SetId("FieldOfView"); yield return new WaitForSeconds(AimCameraMoveTime); aquariumFishController.cameraManager.HideCrossbow(true); shoot = true; } public IEnumerator OnBack() { shoot = false; DOTween.Kill("FieldOfView"); aquariumFishController.cameraManager.cameraVirtual.transform.DOKill(); aquariumFishController.cameraManager.cameraVirtual.transform.DOLocalMove(Vector3.zero, BackCameraMoveTime); float fov = aquariumFishController.cameraManager.cameraVirtual.m_Lens.FieldOfView; DOTween.To(() => fov, x => fov = x, fieldOfView, AimCameraMoveTime).OnUpdate(() => { aquariumFishController.cameraManager.cameraVirtual.m_Lens.FieldOfView = fov; }).SetId("FieldOfView"); yield return new WaitForSeconds(BackShowDelay); aquariumFishController.cameraManager.HideCrossbow(false); GContext.Publish(EShootState.Back); aquariumFishController.cameraManager.TriggerCrossbow("Back"); } public FishMovement Target() { if (shoot) { bool hasTarget = targetMovement != null; if (hasTarget) { aquariumFishController.cameraManager.Target(); //结算 targetMovement.fish.SetTrigger("Idle"); return targetMovement; } } return null; } public async Task OnShoot(bool isRob) { aquariumFishController.cameraManager.TriggerCrossbow("Shoot"); GContext.Publish(EShootState.Shoot); DOTween.Kill("FieldOfView"); ///先操作鱼,获取终点 await Awaiters.Seconds(ShootDelay); aquariumFishController.cameraManager.cameraVirtual.m_Lens.FieldOfView = fieldOfView; float speed = UnityEngine.Random.Range(shootSwimSpeed[0], shootSwimSpeed[1]); targetMovement.OnShoot(isRob, speed, ShootTime, reasonableCenter, reasonableLocation, UnityEngine.Random.Range(reasonableMinDistance, reasonableMaxDistance)); aquariumFishController.cameraManager.Shoot(FxScale, fx_hunt_prefab, isRob, ShootTime, targetMovement); aquariumFishController.fishManager.AllEscape(); StartCoroutine(TimeScale()); aquariumFishController.fishManager.avoidance *= 10; aquariumFishController.fishManager.cohesion = 0; aquariumFishController.fishManager.alignment = 0; aquariumFishController.fishManager.areaConstrain = 0; } IEnumerator TimeScale() { yield return new WaitForSeconds(timeStartScale); targetMovement.fish.SetTrigger("Swim01"); DOTween.To(() => 0.01f, x => Time.timeScale = x, 1, timeEndScale - timeStartScale) .SetEase(timeScaleCurve); yield return new WaitForSeconds(timeEndScale); Time.timeScale = 1f; } public async Task OnShooted(bool isRob) { targetMovement.OnShooted(isRob); if (isRob) { float captureShockTime = CaptureShockTime[targetMovement.slotData.aquariumFishID - 1];//不同品质的鱼的受击时间 float captureShockDistance = CaptureShockDistance[targetMovement.slotData.aquariumFishID - 1];//不同品质的鱼的受击距离 targetMovement.Shock(captureShockDistance, captureShockTime, CaptureShockCurve); await Awaiters.Seconds(CaptureDelay); targetMovement.Capture(fishAnimMinSpeed, fishAnimMaxSpeed, addRotation, addRotationPeriod); float captureTime = aquariumFishController.cameraManager.Capture(fishToCameraDistance, lineDrawMinTime, lineDrawSpeed, targetMovement); GContext.Publish(EShootState.Capture); await Awaiters.Seconds(captureTime + fishDisappearDelay); //aquariumFishController.cameraManager.crossbowGo.SetActive(false); aquariumFishController.cameraManager.Captureed(); targetMovement.gameObject.SetActive(false); } else { float escapeShockTime = EscapeShockTime[targetMovement.slotData.aquariumFishID - 1];//不同品质的鱼的受击时间 float escapeShockDistance = EscapeShockDistance[targetMovement.slotData.aquariumFishID - 1];//不同品质的鱼的受击距离 targetMovement.Shock(escapeShockDistance, escapeShockTime, EscapeShockCurve); await Awaiters.Seconds(EscapeDelay); targetMovement.Escape(EscapeDistance, EscapeDuration); targetMovement.SetFishSpeed(EscapeAnimSpeed, EscapeAnimRecoverTime); aquariumFishController.cameraManager.Escape(ArrowEscapeTime); GContext.Publish(EShootState.Escape); await Awaiters.Seconds(escapeRewardUIDelay); } } public override async System.Threading.Tasks.Task StopAsync() { foreach (var item in fx_hunt_prefab) { Addressables.Release(item.Value); } fx_hunt_prefab.Clear(); if (mutantMaterial != null) { Addressables.Release(mutantMaterial); mutantMaterial = null; } if (fxLeftEye != null) { Addressables.Release(fxLeftEye); fxLeftEye = null; } if (fxRightEye != null) { Addressables.Release(fxRightEye); fxRightEye = null; } if (aquarium != null) { Addressables.ReleaseInstance(aquarium); aquarium = null; } if (fishUnDownloadAlter != null) { foreach (var item in fishUnDownloadAlter) { Addressables.Release(item.Value); } } eventFishHuntingPanel = null; UIManager.Instance.DestroyUI(UITypes.EventFishHuntingPanel); disposables?.Dispose(); disposables = null; GContext.container.Unregister(); await base.StopAsync(); } protected override void OnDestroy() { } }