600 lines
20 KiB
C#
600 lines
20 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Threading.Tasks;
|
||
using asap.core;
|
||
using cfg;
|
||
using game;
|
||
using GameCore;
|
||
using Newtonsoft.Json;
|
||
using UnityEngine;
|
||
|
||
namespace DataCenter
|
||
{
|
||
// EventPartnerGather 游戏数据结构
|
||
public class EventPartnerGatherData
|
||
{
|
||
public bool FirstOpen = true;
|
||
public int EventId;
|
||
public DateTime StartTime;
|
||
public DateTime EndTime;
|
||
|
||
// 核心游戏数据
|
||
public int CurrentPoints = 0; // 当前积分
|
||
public int CurrentMiningProgress = 0; // 挖矿进度
|
||
public int TrainProgress = 0; // 火车进度 (0-5节点)
|
||
public List<int> CompletedNodes = new List<int>(); // 已完成的节点
|
||
|
||
// 好友系统数据(第二阶段)
|
||
public List<FriendData> Friends = new List<FriendData>();
|
||
public int InvitedCount = 0;
|
||
|
||
// 奖励记录
|
||
public List<int> CollectedRewards = new List<int>();
|
||
public bool IsFinished = false;
|
||
public float BonusPercent = 0f;
|
||
public DateTime BonusExpireUtc = DateTime.MinValue;
|
||
|
||
public class FriendData
|
||
{
|
||
public string Id;
|
||
public string Name;
|
||
public int MiningProgress;
|
||
public int ContributionPoints;
|
||
public bool IsActive;
|
||
}
|
||
}
|
||
|
||
// EventPartnerGather 管理器
|
||
public class EventPartnerGatherManager
|
||
{
|
||
public const string SaveKey = "EventPartnerGatherData";
|
||
|
||
[Inject] public Tables _tables { get; set; }
|
||
|
||
private FishingEvent _fishingEvent;
|
||
|
||
// 检查数据是否改变过
|
||
private bool _isEventDataChanged = false;
|
||
|
||
public EventPartnerGatherData GatherData { get; private set; }
|
||
// 数据
|
||
public EventPartnerMain2 EventPartnerMain2Data { get; private set; }
|
||
// 抽奖数据
|
||
public List<EventPartnerSpinPoint> EventPartnerSpinPointList { get; private set; }
|
||
// 模型数据,目前开来需要构造模型从表里读取
|
||
public EventPartnerInit EventPartnerInitData { get; private set; }
|
||
|
||
// 累分状态
|
||
private readonly List<int> _nodeCumulativeSteps = new List<int>();
|
||
|
||
// 配置数据(后续从表格读取)
|
||
public int MaxTrainNodes => 5;
|
||
public int PointsPerMining => 10;
|
||
public int PointsPerNode => 100;
|
||
|
||
public bool IsFirstOpen
|
||
{
|
||
get => GatherData?.FirstOpen ?? false;
|
||
set
|
||
{
|
||
if (GatherData != null && GatherData.FirstOpen)
|
||
{
|
||
GatherData.FirstOpen = false;
|
||
SaveData();
|
||
}
|
||
}
|
||
}
|
||
|
||
public void UpdateEventData(FishingEvent fishingEvent)
|
||
{
|
||
Log($"UpdateEventData: {fishingEvent?.ID}");
|
||
|
||
_fishingEvent = fishingEvent;
|
||
InitializeData();
|
||
// }
|
||
}
|
||
|
||
public void CheckInit()
|
||
{
|
||
Init();
|
||
}
|
||
public void Init()
|
||
{
|
||
Log("Init()-> ");
|
||
if (GatherData == null && _fishingEvent != null)
|
||
{
|
||
CreateNewData();
|
||
}
|
||
|
||
//TODO:LF 等上面触发完成之后,移走
|
||
//TODO:LF:后面优化 2025-09-17
|
||
InitializeData();
|
||
ValidateAndUpdateData();
|
||
}
|
||
private void CreateNewData()
|
||
{
|
||
var limitedTime = (LimitedTime)_fishingEvent.TimeDefinition;
|
||
var startTime = GlobalUtils.TryParseDateTime(limitedTime.StartTime, ZZTimeHelper.UtcNow());
|
||
var endTime = GlobalUtils.TryParseDateTime(limitedTime.EndTime, ZZTimeHelper.UtcNow());
|
||
|
||
GatherData = new EventPartnerGatherData
|
||
{
|
||
FirstOpen = true,
|
||
EventId = _fishingEvent.ID,
|
||
StartTime = startTime,
|
||
EndTime = endTime,
|
||
CurrentPoints = 0,
|
||
CurrentMiningProgress = 0,
|
||
TrainProgress = 0
|
||
};
|
||
|
||
SaveData();
|
||
}
|
||
|
||
private void InitializeData()
|
||
{
|
||
Log("InitializeData() -> ");
|
||
|
||
if (_fishingEvent == null) return;
|
||
|
||
var redirectId = _fishingEvent.RedirectID;
|
||
var eventPartnerDataList = _tables.TbEventPartnerMain2.DataList;
|
||
EventPartnerMain2Data = eventPartnerDataList.FirstOrDefault(data => data.ID == redirectId);
|
||
var allSpinPoints = _tables.TbEventPartnerSpinPoint.DataList;
|
||
var ids = EventPartnerMain2Data?.SpinPoint;
|
||
if (ids != null && ids.Count > 0)
|
||
{
|
||
var filtered = new List<EventPartnerSpinPoint>();
|
||
foreach (var id in ids)
|
||
{
|
||
var sp = _tables.TbEventPartnerSpinPoint.GetOrDefault(id);
|
||
if (sp != null) filtered.Add(sp);
|
||
}
|
||
EventPartnerSpinPointList = filtered;
|
||
}
|
||
else
|
||
{
|
||
EventPartnerSpinPointList = new List<EventPartnerSpinPoint>();
|
||
}
|
||
_nodeCumulativeSteps.Clear();
|
||
if (EventPartnerMain2Data?.StagePoint != null && EventPartnerMain2Data.StagePoint.Count > 0)
|
||
{
|
||
int sum = 0;
|
||
for (int i = 0; i < EventPartnerMain2Data.StagePoint.Count; i++)
|
||
{
|
||
sum += EventPartnerMain2Data.StagePoint[i];
|
||
_nodeCumulativeSteps.Add(sum);
|
||
}
|
||
}
|
||
var eventPartnerInitDataList = _tables.TbEventPartnerInit.DataList;
|
||
// foreach (var eventPartnerInitData in eventPartnerInitDataList.Where(data => data.ID == redirectId))
|
||
// {
|
||
// EventPartnerInitData = eventPartnerInitData;
|
||
// }
|
||
EventPartnerInitData = eventPartnerInitDataList.FirstOrDefault(data => data.ID == redirectId);
|
||
// 检查是否需要重置数据
|
||
if (GatherData != null && !IsTimeValid())
|
||
{
|
||
HandleEventEnd();
|
||
GatherData = null;
|
||
}
|
||
}
|
||
|
||
private void ValidateAndUpdateData()
|
||
{
|
||
if (GatherData == null) return;
|
||
|
||
// 验证时间有效性
|
||
if (!IsTimeValid())
|
||
{
|
||
HandleEventEnd();
|
||
}
|
||
}
|
||
|
||
public bool IsTimeValid()
|
||
{
|
||
if (GatherData == null) return false;
|
||
|
||
var now = ZZTimeHelper.UtcNow();
|
||
return now >= GatherData.StartTime && now <= GatherData.EndTime;
|
||
}
|
||
|
||
public TimeSpan GetRemainingTime()
|
||
{
|
||
if (GatherData == null)
|
||
return TimeSpan.Zero;
|
||
|
||
return GatherData.EndTime - ZZTimeHelper.UtcNow();
|
||
}
|
||
|
||
public bool CheckOpen()
|
||
{
|
||
if (GatherData == null) return false;
|
||
if (!IsTimeValid()) return false;
|
||
if (GatherData.IsFinished) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
// 核心游戏逻辑
|
||
|
||
// 抽奖数据
|
||
public EventPartnerSpinPoint GetSpinPointElem()
|
||
{
|
||
// if (EventPartnerSpinPointList is { Count: > 0 })
|
||
// {
|
||
// // 根据权重,生成字典
|
||
// var dict = EventPartnerSpinPointList.ToDictionary(elem => elem, elem => elem.Weight);
|
||
// var elem = OfferChainsChestManager.WeightedRandom(dict);
|
||
// Log($"GetSpinPointElem -> {elem.ID}");
|
||
// return elem;
|
||
// }
|
||
return null;
|
||
}
|
||
|
||
public void AddPoints(int points)
|
||
{
|
||
if (GatherData == null)
|
||
{
|
||
Log("错误:GatherData 为空,无法添加积分");
|
||
return;
|
||
}
|
||
|
||
if (GatherData.IsFinished)
|
||
{
|
||
Log("警告:游戏已结束,无法添加积分");
|
||
return;
|
||
}
|
||
|
||
if (points <= 0)
|
||
{
|
||
Log($"警告:尝试添加无效积分值:{points}");
|
||
return;
|
||
}
|
||
|
||
EnsureBonusValid();
|
||
float mult = 1f + Mathf.Max(0f, GatherData.BonusPercent);
|
||
int eff = Mathf.Max(0, Mathf.RoundToInt(points * mult));
|
||
|
||
// 防止积分溢出
|
||
long newPoints = (long)GatherData.CurrentPoints + eff;
|
||
if (newPoints > int.MaxValue)
|
||
{
|
||
Log($"警告:积分即将溢出,限制在最大值");
|
||
GatherData.CurrentPoints = int.MaxValue;
|
||
}
|
||
else
|
||
{
|
||
GatherData.CurrentPoints += eff;
|
||
}
|
||
|
||
Log($"AddPoints: {eff}, TotalPoints: {GatherData.CurrentPoints}");
|
||
SaveData();
|
||
GContext.Publish(new EventPartnerGatherPointsUpdate { Points = GatherData.CurrentPoints });
|
||
|
||
// 检查是否需要触发自动挖矿
|
||
CheckAutoMining();
|
||
}
|
||
|
||
private void CheckAutoMining()
|
||
{
|
||
// 每累积一定积分自动触发挖矿
|
||
bool dataChanged = false;
|
||
while (GatherData.CurrentPoints >= PointsPerMining)
|
||
{
|
||
GatherData.CurrentPoints -= PointsPerMining;
|
||
GatherData.CurrentMiningProgress++;
|
||
dataChanged = true;
|
||
|
||
// 检查节点完成
|
||
CheckNodeProgress();
|
||
}
|
||
|
||
// 如果数据有变化,发布更新事件
|
||
if (dataChanged)
|
||
{
|
||
SaveData();
|
||
PublishDataUpdateEvents();
|
||
}
|
||
}
|
||
|
||
private void CheckNodeProgress()
|
||
{
|
||
int completedNodes = 0;
|
||
if (_nodeCumulativeSteps != null && _nodeCumulativeSteps.Count > 0)
|
||
{
|
||
for (int i = 0; i < _nodeCumulativeSteps.Count; i++)
|
||
{
|
||
if (GatherData.CurrentMiningProgress >= _nodeCumulativeSteps[i]) completedNodes++;
|
||
else break;
|
||
}
|
||
}
|
||
if (completedNodes > GatherData.TrainProgress)
|
||
{
|
||
int target = Mathf.Min(completedNodes, MaxTrainNodes);
|
||
for (int idx = GatherData.TrainProgress; idx < target; idx++)
|
||
{
|
||
CompleteTrainNode(idx);
|
||
}
|
||
GatherData.TrainProgress = target;
|
||
if (GatherData.TrainProgress >= MaxTrainNodes)
|
||
{
|
||
HandleGameComplete();
|
||
}
|
||
}
|
||
}
|
||
|
||
private void CompleteTrainNode(int nodeIndex)
|
||
{
|
||
Log($"CompleteNode: {nodeIndex}");
|
||
|
||
if (!GatherData.CompletedNodes.Contains(nodeIndex))
|
||
{
|
||
GatherData.CompletedNodes.Add(nodeIndex);
|
||
|
||
// 发放节点奖励
|
||
DistributeNodeReward(nodeIndex);
|
||
}
|
||
}
|
||
|
||
private void DistributeNodeReward(int nodeIndex)
|
||
{
|
||
// 使用现有的奖励系统
|
||
var dropId = GetNodeRewardDropId(nodeIndex);
|
||
if (dropId > 0)
|
||
{
|
||
var playerItemData = GContext.container.Resolve<PlayerItemData>();
|
||
var rewards = playerItemData.GetItemDataByDropId(dropId);
|
||
|
||
playerItemData.AddItem(rewards);
|
||
GContext.Publish(new ShowData(rewards));
|
||
|
||
GatherData.CollectedRewards.Add(dropId);
|
||
SaveData();
|
||
}
|
||
}
|
||
|
||
private int GetNodeRewardDropId(int nodeIndex)
|
||
{
|
||
// 根据节点返回对应的掉落ID(后续从配置表读取)
|
||
return 10000 + nodeIndex;
|
||
}
|
||
|
||
private void HandleGameComplete()
|
||
{
|
||
Log("Game Complete!");
|
||
GatherData.IsFinished = true;
|
||
|
||
// 发放最终大奖
|
||
DistributeFinalReward();
|
||
|
||
SaveData();
|
||
GContext.Publish(new EventPartnerGatherComplete());
|
||
}
|
||
|
||
private void DistributeFinalReward()
|
||
{
|
||
var dropId = GetFinalRewardDropId();
|
||
if (dropId > 0)
|
||
{
|
||
var playerItemData = GContext.container.Resolve<PlayerItemData>();
|
||
var rewards = playerItemData.GetItemDataByDropId(dropId);
|
||
|
||
playerItemData.AddItem(rewards);
|
||
GContext.Publish(new ShowData(rewards));
|
||
}
|
||
}
|
||
|
||
private int GetFinalRewardDropId()
|
||
{
|
||
// 最终奖励掉落ID(后续从配置表读取)
|
||
return 99999;
|
||
}
|
||
|
||
private void HandleEventEnd()
|
||
{
|
||
if (GatherData == null || GatherData.IsFinished) return;
|
||
|
||
Log("Event Ended");
|
||
|
||
// 结算未领取的奖励
|
||
if (GatherData.TrainProgress >= MaxTrainNodes && !GatherData.IsFinished)
|
||
{
|
||
HandleGameComplete();
|
||
}
|
||
|
||
ClearData();
|
||
}
|
||
public int ResolveSpinAndGetPoints(EventPartnerSpinPoint p)
|
||
{
|
||
if (p == null || p.SpinPointParam == null) return 0;
|
||
switch (p.SpinPointParam)
|
||
{
|
||
case NormalSpinPoint n:
|
||
return Mathf.Max(0, n.SpinPoints);
|
||
case FreeSpinPoint f:
|
||
return Mathf.Max(0, f.SpinPoints);
|
||
case MoreSpinPoint m:
|
||
ApplyBonus(m.BonusPercent, m.BonusDuration);
|
||
return 0;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
private void ApplyBonus(float percent, int durationSec)
|
||
{
|
||
if (GatherData == null) return;
|
||
GatherData.BonusPercent = Mathf.Max(0f, percent);
|
||
GatherData.BonusExpireUtc = ZZTimeHelper.UtcNow().AddSeconds(Mathf.Max(0, durationSec));
|
||
SaveData();
|
||
GContext.Publish(new EventPartnerGatherRefreshEvent());
|
||
}
|
||
private void EnsureBonusValid()
|
||
{
|
||
if (GatherData == null) return;
|
||
if (GatherData.BonusPercent > 0f && ZZTimeHelper.UtcNow() > GatherData.BonusExpireUtc)
|
||
{
|
||
GatherData.BonusPercent = 0f;
|
||
GatherData.BonusExpireUtc = DateTime.MinValue;
|
||
SaveData();
|
||
GContext.Publish(new EventPartnerGatherRefreshEvent());
|
||
}
|
||
}
|
||
public bool IsBonusActive()
|
||
{
|
||
return GatherData != null && GatherData.BonusPercent > 0f && ZZTimeHelper.UtcNow() <= GatherData.BonusExpireUtc;
|
||
}
|
||
private void SaveData()
|
||
{
|
||
if (GatherData != null)
|
||
{
|
||
PlayFabMgr.Instance.UpdateUserDataValue(SaveKey, JsonConvert.SerializeObject(GatherData));
|
||
}
|
||
}
|
||
public void LoadData(string dataValue)
|
||
{
|
||
if (!string.IsNullOrEmpty(dataValue))
|
||
{
|
||
GatherData = JsonConvert.DeserializeObject<EventPartnerGatherData>(dataValue);
|
||
}
|
||
}
|
||
|
||
private void ClearData()
|
||
{
|
||
GatherData = null;
|
||
SaveData();
|
||
}
|
||
|
||
// 进入游戏场景
|
||
public void EnterGatherScene()
|
||
{
|
||
Log("EnterGatherScene() ");
|
||
IsFirstOpen = false;
|
||
GContext.Publish(new UnloadActToNextAct("EventPartnerGatherAct", UITypes.CloudTransitionPanel, 0.5f));
|
||
}
|
||
|
||
// 开始采矿
|
||
public void StartMining()
|
||
{
|
||
// throw new NotImplementedException();
|
||
Log("StartMining()");
|
||
((EventPartnerGatherAct)_act)?.OnEnterGather();
|
||
}
|
||
|
||
private static void Log(object t)
|
||
{
|
||
Debug.Log($"<color=cyan>EventPartnerGatherManager-> {t} </color>");
|
||
}
|
||
|
||
private AGameAct _act;
|
||
public void SetGameAct(AGameAct act)
|
||
{
|
||
_act = act;
|
||
}
|
||
// 组件绑定管理
|
||
private UI.PartnerGather.Mining.EventPartnerMiningSceneController _miningController;
|
||
private UI.PartnerGather.Mining.EventPartnerDrawMiningPanel _drawPanel;
|
||
|
||
/// <summary>
|
||
/// 设置挖矿场景控制器引用
|
||
/// </summary>
|
||
public void SetMiningController(UI.PartnerGather.Mining.EventPartnerMiningSceneController controller)
|
||
{
|
||
_miningController = controller;
|
||
Log($"设置挖矿控制器: {controller?.name ?? "null"}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置抽奖UI面板引用
|
||
/// </summary>
|
||
public void SetDrawPanel(UI.PartnerGather.Mining.EventPartnerDrawMiningPanel panel)
|
||
{
|
||
_drawPanel = panel;
|
||
Log($"设置抽奖面板: {panel?.name ?? "null"}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取挖矿控制器引用
|
||
/// </summary>
|
||
public UI.PartnerGather.Mining.EventPartnerMiningSceneController GetMiningController()
|
||
{
|
||
return _miningController;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取抽奖面板引用
|
||
/// </summary>
|
||
public UI.PartnerGather.Mining.EventPartnerDrawMiningPanel GetDrawPanel()
|
||
{
|
||
return _drawPanel;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 通知所有绑定组件刷新数据显示
|
||
/// </summary>
|
||
public void RefreshAllUI()
|
||
{
|
||
if (GatherData == null) return;
|
||
|
||
// 刷新抽奖面板
|
||
if (_drawPanel != null)
|
||
{
|
||
_drawPanel.SetPoints(GatherData.CurrentPoints);
|
||
_drawPanel.SetMiningProgress(GatherData.CurrentMiningProgress);
|
||
_drawPanel.SetTrainProgress(GatherData.TrainProgress, MaxTrainNodes);
|
||
}
|
||
|
||
Log("已刷新所有UI组件数据");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发布所有相关的数据更新事件
|
||
/// </summary>
|
||
private void PublishDataUpdateEvents()
|
||
{
|
||
if (GatherData == null) return;
|
||
|
||
// 发布积分更新事件
|
||
GContext.Publish(new EventPartnerGatherPointsUpdate { Points = GatherData.CurrentPoints });
|
||
|
||
// 发布挖矿进度更新事件
|
||
GContext.Publish(new EventPartnerGatherMiningProgressUpdate { Progress = GatherData.CurrentMiningProgress });
|
||
|
||
// 发布火车进度更新事件
|
||
GContext.Publish(new EventPartnerGatherTrainProgressUpdate { Progress = GatherData.TrainProgress, MaxNodes = MaxTrainNodes });
|
||
|
||
// 刷新绑定的UI组件
|
||
RefreshAllUI();
|
||
|
||
Log($"已发布数据更新事件 - 积分:{GatherData.CurrentPoints}, 挖矿进度:{GatherData.CurrentMiningProgress}, 火车进度:{GatherData.TrainProgress}");
|
||
}
|
||
|
||
// 有可能会激活,不应该在OnEnable 中调用Init();
|
||
public void CheckForOnEnable()
|
||
{
|
||
//throw new NotImplementedException();
|
||
}
|
||
}
|
||
|
||
// 事件定义
|
||
public class EventPartnerGatherPointsUpdate
|
||
{
|
||
public int Points;
|
||
}
|
||
|
||
public class EventPartnerGatherMiningProgressUpdate
|
||
{
|
||
public int Progress;
|
||
}
|
||
|
||
public class EventPartnerGatherTrainProgressUpdate
|
||
{
|
||
public int Progress;
|
||
public int MaxNodes;
|
||
}
|
||
|
||
public class EventPartnerGatherComplete { }
|
||
|
||
public class EventPartnerGatherRefreshEvent { }
|
||
} |