Files
2026-05-26 16:15:54 +08:00

553 lines
23 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<int, GameObject> fishUnDownloadAlter = new Dictionary<int, GameObject>();
OpponentItemData localOpponentItemData;
FishMovement targetMovement;
EventFishHuntingPanel eventFishHuntingPanel;
bool shoot = false;
[Header("General Settings")]
public float[] FxScale;//不同品质的鱼的特效缩放大小
Dictionary<string, GameObject> fx_hunt_prefab = new Dictionary<string, GameObject>();
[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<bool> StartAsync()
{
UIManager.Instance.DestroyUI(UITypes.EventGamePlayPanel);
_tables = GContext.container.Resolve<cfg.Tables>();
aquariumInit = _tables.TbAquariumInit.DataList[0];
disposables = new CompositeDisposable();
GContext.container.Unregister<AquariumShooterFishManager>();
AM = new AquariumShooterFishManager();
GContext.container.RegisterInstance(AM);
localOpponentItemData = GContext.container.Resolve<SmallGameData>().GetBankHeistOpponent(EnemyType.Aquarium);
List<FishHuntInit> huntInits = _tables.TbFishHuntInit.DataList;
if (GContext.container.Resolve<SmallGameData>().FishHuntGameCount < huntInits.Count && GContext.container.Resolve<LeadboardData>().fishingEvent == null)
{
FishHuntInit inti = huntInits[GContext.container.Resolve<SmallGameData>().FishHuntGameCount];
var itemDatas = GContext.container.Resolve<SmallGameData>().opponentItemDatas.Where(x => x.isRobot).ToList();
//机器人数据
localOpponentItemData = itemDatas[UnityEngine.Random.Range(0, itemDatas.Count)];
GContext.container.Resolve<SmallGameData>().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<SmallGameData>().opponentItemDatas.Where(x => x.isRobot).ToList();
//机器人数据
localOpponentItemData = itemDatas[UnityEngine.Random.Range(0, itemDatas.Count)];
localOpponentItemData.target_group = GContext.container.Resolve<SmallGameData>().opponentData.target_group;
GContext.container.Resolve<SmallGameData>().opponentData = localOpponentItemData;
await AM.GetData(localOpponentItemData.playFabID, localOpponentItemData.isRobot, false);
}
}
GContext.OnEvent<ChangeSmallGameTargetEvent>().Subscribe(ChangeSmallGameTargetEvent).AddTo(disposables);
// 加载场景
mutantMaterial = await Addressables.LoadAssetAsync<Material>(_tables.TbFishMutant.Material).Task;
fxLeftEye = await Addressables.LoadAssetAsync<GameObject>(_tables.TbFishMutant.FxLeftEye).Task;
fxRightEye = await Addressables.LoadAssetAsync<GameObject>(_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<GameObject>("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<GameObject>("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<GameObject>("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<GameObject>("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<GameObject>("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<GameObject>("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<SmallGameData>().opponentItemDatas.Where(x => x.isRobot).ToList();
//机器人数据
opponentItemData = itemDatas[UnityEngine.Random.Range(0, itemDatas.Count)];
opponentItemData.target_group = GContext.container.Resolve<SmallGameData>().opponentData.target_group;
GContext.container.Resolve<SmallGameData>().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<SmallGameData>().opponentData = localOpponentItemData;
}
changeSmallGameTargetEvent.ts.SetResult(data != null);
GContext.Publish(new EndTransition());
}
async Task EnterMapScene()
{
List<AquariumSlotData> 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<GameObject>(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>();
eventFishHuntingPanel.shooterFishAct = this;
bool isGuide = GContext.container.Resolve<GuideDataCenter>().InspectTriggerGuide("EventFishHuntingPanel");
FishMovement guide = null;
if (isGuide && GContext.container.Resolve<GuideDataCenter>().curGroupDefine.groupName == GroupName.Raid)
{
guide = GetMutantFish();
}
aquariumFishController.cameraManager.PlayCrossbow(guide);
}
async Task LoadScene()
{
var mapData = _tables.TbMapData.DataMap[AM.MapId];
string prefabName = mapData.AquariumPrefab;
aquarium = await Addressables.InstantiateAsync(prefabName).Task;
aquariumFishController = aquarium.GetComponent<AquariumFishController>();
aquariumFishController.fishManager.MaxLoadTime = 0.5f;
}
void InitFish()
{
Debug.Log($"nextOpponent InitFish MapID {AM.serverData.mapId}");
List<AquariumSlotData> slotDatas = AM.serverData.slotDatas;
if (slotDatas == null)
{
return;
}
aquariumFishController.fishManager.fishUnDownloadAlter = fishUnDownloadAlter;
var time = ZZTimeHelper.UtcNow();
List<AquariumResultData> aquariumResultDatas = AM.serverData.aquariumResultDatas;
for (int i = 0; i < slotDatas.Count; i++)
{
AquariumSlotData slotData = slotDatas[i];
slotData.index = i;
var HatchTime = slotData.FishHatchTime();
if (HatchTime < time)
{
if (!slotData.IsResult() && !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, i, fishQ);
}
}
//else
//{
// //初始化蛋
// aquariumFishController.fishEggManager.AddEgg(i, slotData.eggId);
//}
}
}
void StartTime()
{
List<AquariumSlotData> slotDatas = AM.serverData.slotDatas;
List<AquariumResultData> aquariumResultDatas = AM.serverData.aquariumResultDatas;
for (int i = 0; i < slotDatas.Count; i++)
{
if (!aquariumResultDatas[i].IsResult() && !slotDatas[i].IsResult())
{
SetFishScale(slotDatas[i], i);
}
}
}
/// <summary>
/// 加载鱼的模型
/// </summary>
/// <param name="aquariumSlotData"></param>
/// <param name="index"></param>
void AddFish(AquariumSlotData aquariumSlotData, int index, int count)
{
aquariumFishController.fishManager.AddFish(
mutantMaterial, fxLeftEye, fxRightEye,
aquariumSlotData,
count,
index);
}
FishMovement GetMutantFish()
{
List<AquariumSlotData> 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);
}
/// <summary>
/// 刷新鱼的大小
/// </summary>
/// <param name="aquariumSlotData"></param>
/// <param name="index"></param>
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<AquariumShooterFishManager>();
await base.StopAsync();
}
protected override void OnDestroy()
{
}
}