1714 lines
55 KiB
C#
1714 lines
55 KiB
C#
// EventCubeMeltManager.cs
|
||
// 锻刀大赛
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using asap.core;
|
||
using cfg;
|
||
using EventCubeMelt;
|
||
using EventCubeMelt.Data;
|
||
using EventCubeMelt.ShapePlacement;
|
||
using EventCubeMelt.UI;
|
||
using EventCubeMelt.Utils;
|
||
using game;
|
||
using GameCore;
|
||
using Newtonsoft.Json;
|
||
using UnityEngine;
|
||
using Random = UnityEngine.Random;
|
||
|
||
|
||
public class EventCubeMeltManager
|
||
{
|
||
//
|
||
public const string SaveKey = "EventCubeMeltData";
|
||
|
||
#region 与外部交互函数
|
||
|
||
public void UpdateEventData(FishingEvent fishingEvent)
|
||
{
|
||
_fishingEvent = fishingEvent;
|
||
if (EventData != null && _fishingEvent != null && _fishingEvent.ID != EventData.EventId)
|
||
{
|
||
ClearData();
|
||
}
|
||
|
||
if (!_isInit || EventData == null)
|
||
{
|
||
_isInit = false;
|
||
Init();
|
||
}
|
||
else
|
||
{
|
||
UpdateTime();
|
||
SetRedPoint();
|
||
UpdateLocalData();
|
||
}
|
||
}
|
||
|
||
public void LoadData(string dataValue)
|
||
{
|
||
ELog($"LoadData-> {dataValue}");
|
||
|
||
if (!string.IsNullOrEmpty(dataValue))
|
||
{
|
||
EventData = JsonConvert.DeserializeObject<EventCubeMeltData>(dataValue);
|
||
|
||
// 可调试的在这里放数据
|
||
if (true)
|
||
{
|
||
// EventData.CurrentStagetId = 15;
|
||
// EventData.IsFinished = false;
|
||
// EventData.BoardData = new List<int>
|
||
// {
|
||
// 0,99,0,99,99,0,99,0,
|
||
// 99,0,99,99,0,99,0,99,
|
||
// 0,99,0,99,99,0,99,99,
|
||
// 99,0,99,0,99,0,99,99,
|
||
// 0,99,99,99,99,99,99,99,
|
||
// 99,0,99,99,99,99,99,99,
|
||
// 0,99,99,99,99,99,99,99,
|
||
// 99,0,99,0,99,99,5,99
|
||
// };
|
||
|
||
// EventData.CollectRewardsId.Remove(14);
|
||
// EventData.IsFinalRewardGet = false;
|
||
// EventData.CollectItems = new List<CollectItem>
|
||
// {
|
||
// new()
|
||
// {
|
||
// ItemId = 1, Count = 20, MaxCount = 20, Icon = null,
|
||
// },
|
||
// new()
|
||
// {
|
||
// ItemId = 4, Count = 15, MaxCount = 15, Icon = null,
|
||
// },
|
||
// new()
|
||
// {
|
||
// ItemId = 5, Count = 10, MaxCount = 10, Icon = null,
|
||
// }
|
||
// };
|
||
|
||
// EventData.BoardData = new List<int>()
|
||
// {
|
||
// 0, 0, 99, 99, 99, 0, 0, 0,
|
||
// 1, 0, 99, 0, 0, 99, 99, 2,
|
||
// 99, 99, 99, 88, 88, 2, 0, 99,
|
||
// 99, 2, 99, 99, 99, 99, 0, 99,
|
||
// 99, 99, 2, 99, 99, 0, 0, 0,
|
||
// 0,0,0,0, 0, 2, 0, 0,
|
||
// 99, 0, 0, 99, 99, 99, 2, 0,
|
||
// 99, 0, 0, 99, 99, 99, 2, 0
|
||
// };
|
||
// EventData.BoardData = new List<int>
|
||
// {
|
||
// 99, 99, 99, 99, 0, 99, 0, 0,
|
||
// 99, 99, 99, 99, 0, 99, 0, 0,
|
||
// 99, 99, 99, 99, 0, 99, 0, 0,
|
||
// 99, 99, 99, 99, 0, 99, 0, 0,
|
||
// 99, 99, 99, 99, 0, 99, 0, 0,
|
||
// 0,0,0,0, 0, 0, 0, 0,
|
||
// 99, 99, 99, 99, 0, 99, 0, 0,
|
||
// 99, 99, 99, 99, 0, 99, 0, 0,
|
||
// };
|
||
// EventData.PieceDatas = new List<List<int>>
|
||
// {
|
||
// new() {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,99,99,99,99,99},
|
||
// new() {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0},
|
||
// new() {0,0,0,0,0,0,0,0,0,0,0,0,99,99,0,0,0,99,0,0,0,0,99,0,0},
|
||
// };
|
||
}
|
||
}
|
||
}
|
||
|
||
public void ClearData()
|
||
{
|
||
EventData = null;
|
||
_isInit = false;
|
||
SaveData();
|
||
}
|
||
|
||
private void SaveData()
|
||
{
|
||
var eventDataJson = JsonConvert.SerializeObject(EventData);
|
||
if (ShouldBuildELog())
|
||
{
|
||
ELog($"SaveData()-> {eventDataJson}");
|
||
}
|
||
PlayFabMgr.Instance.UpdateUserDataValue(SaveKey, eventDataJson);
|
||
}
|
||
|
||
public void AddTicket(int costValue)
|
||
{
|
||
if (EventData != null)
|
||
{
|
||
EventData.TicketCount += costValue;
|
||
if (EventData.TicketCount < 0)
|
||
{
|
||
EventData.TicketCount = 0;
|
||
}
|
||
GContext.container.Resolve<FishingEventData>().SaveTransitionData(EventData.EventId, EventData.TicketCount);
|
||
GContext.Publish(new EventCubeMeltUpdateTicketCount());
|
||
SaveData();
|
||
}
|
||
SetRedPoint();
|
||
}
|
||
|
||
public int GetTicketCount()
|
||
{
|
||
return EventData.TicketCount;
|
||
}
|
||
|
||
#endregion
|
||
|
||
private bool _isInit;
|
||
private FishingEvent _fishingEvent;
|
||
[Inject] public Tables _tables { get; set; }
|
||
|
||
public EventCubeMeltData EventData { get; private set; }
|
||
|
||
public FishingEvent FishingEvent {get => _fishingEvent;set => _fishingEvent = value;}
|
||
|
||
|
||
// 锻刀大赛数据
|
||
public EventCubeMeltMain EventCubeMeltMainData { get; private set; }
|
||
|
||
// 配置
|
||
private List<List<int>> EventCubeMeltConfig { get; set; }
|
||
|
||
// 当前的配置数据
|
||
public EventCubeMeltStage EventCubeMeltStageData { get; private set; }
|
||
|
||
// 当前收集数据
|
||
public EventCubeMeltCollection EventCubeMeltCollectionData { get; private set; }
|
||
|
||
// 当前的Piece
|
||
public List<EventCubeMeltPiece> EventCubeMeltPieces { get; private set; }
|
||
|
||
//
|
||
// 读取表格,生成所有的Piece
|
||
private List<PieceItem> EventCubeMeltPieceItems { get; set; } = new();
|
||
|
||
// 当前的Item
|
||
public List<EventCubeMeltItem> EventCubeMeltItems { get; private set; }
|
||
|
||
// 收集的列表
|
||
public List<EventCubeMeltCollection> EventCubeMeltCollections { get; private set; }
|
||
|
||
//- 当前的StageList
|
||
public List<int> EventStageList { get; private set; }
|
||
//
|
||
public int StageCount { get; set; }
|
||
|
||
//-
|
||
// public Vector2Int BoardViewSize { get; private set; }
|
||
|
||
|
||
|
||
public DateTime StartTime;
|
||
|
||
// 结束时间
|
||
public DateTime EndTime;
|
||
|
||
public void Init()
|
||
{
|
||
if (_fishingEvent == null)
|
||
return;
|
||
if (_isInit)
|
||
return;
|
||
ELog("Init()-> ");
|
||
if (EventData == null)
|
||
{
|
||
CreateNewData();
|
||
}
|
||
|
||
UpdateLocalData();
|
||
UpdateTime();
|
||
SetRedPoint();
|
||
_isInit = true;
|
||
}
|
||
|
||
public void SetRedPoint()
|
||
{
|
||
if (EventData != null)
|
||
{
|
||
RedPointManager.Instance.SetRedPointState(RedPointName.Home_CubeMelt, EventData.TicketCount > 0,
|
||
EventData.TicketCount);
|
||
}
|
||
else
|
||
{
|
||
RedPointManager.Instance.SetRedPointState(RedPointName.Home_CubeMelt, false);
|
||
}
|
||
}
|
||
|
||
private void UpdateTime()
|
||
{
|
||
if (_fishingEvent != null)
|
||
{
|
||
var limitedTime = (LimitedTime)_fishingEvent.TimeDefinition;
|
||
var startTime = GlobalUtils.TryParseDateTime(limitedTime.StartTime, ZZTimeHelper.UtcNow());
|
||
var endTime = GlobalUtils.TryParseDateTime(limitedTime.EndTime, ZZTimeHelper.UtcNow().AddDays(-1));
|
||
if (EventData != null)
|
||
{
|
||
if (EventData.EventId == _fishingEvent.ID)
|
||
{
|
||
EventData.StartTime = startTime;
|
||
EventData.EndTime = endTime;
|
||
}
|
||
else
|
||
{
|
||
EventData.EndTime = DateTime.Now.AddDays(-1);
|
||
}
|
||
}
|
||
|
||
EndTime = endTime;
|
||
StartTime = startTime;
|
||
}
|
||
}
|
||
|
||
private void UpdateLocalData()
|
||
{
|
||
ELog("UpdateLocalData() -> ");
|
||
if (_fishingEvent == null)
|
||
return;
|
||
|
||
var fishingEventRedirectID = _fishingEvent.RedirectID;
|
||
var cycleItemData = _tables.TbFishingEventCycleItem.GetOrDefault(fishingEventRedirectID);
|
||
var dataList = _tables.TbEventCubeMeltMain.DataList;
|
||
|
||
// 设置内容
|
||
EventCubeMeltMainData = dataList.FirstOrDefault(data => data.ID == cycleItemData.RedirectID);
|
||
// 道具
|
||
EventCubeMeltItems = _tables.TbEventCubeMeltItem.DataList;
|
||
EventCubeMeltPieces = _tables.TbEventCubeMeltPiece.DataList;
|
||
EventCubeMeltCollections = _tables.TbEventCubeMeltCollection.DataList;
|
||
//- StageList
|
||
EventStageList = EventData.Cycle == 0 ? EventCubeMeltMainData?.StageFirstList :EventCubeMeltMainData?.StageLoopList ?? new List<int>();
|
||
// var stageListCount = EventData.Cycle == 0 ? EventCubeMeltMainData?.StageFirstList.Count : EventCubeMeltMainData?.StageLoopList.Count;
|
||
// var stageListCount = EventStageList ?.Count ?? 0;
|
||
StageCount = EventStageList ?.Count ?? 0;
|
||
// PieceItems
|
||
InitPieceItems();
|
||
SyncEventDataChange();
|
||
|
||
}
|
||
|
||
private void SyncEventDataChange()
|
||
{
|
||
//- EventData 结构变化了,放在 这里
|
||
if (EventData.CollectRewardsId is not { Count: > 0 })
|
||
{
|
||
EventData.CollectRewardsId = new List<int>();
|
||
SaveData();
|
||
}
|
||
}
|
||
|
||
public async Task PrepareData()
|
||
{
|
||
ELog("PrepareData-> ");
|
||
|
||
if(EventData.CurrentStagetId > 0)
|
||
SetIsInGuideAnim(false);
|
||
|
||
// if (true)
|
||
// {
|
||
// if (EventData.CurrentStagetId == 2)
|
||
// {
|
||
// EventData.CurrentStagetId = 1;
|
||
// GenerateNextStageData();
|
||
// }
|
||
// }
|
||
|
||
FixOverStage();
|
||
UpdateCurrentStage();
|
||
await UpdateBoardData();
|
||
}
|
||
|
||
private async Task UpdateBoardData()
|
||
{
|
||
var isSaveDataRequired = false;
|
||
if (EventData.BoardData is not { Count: > 0 })
|
||
{
|
||
CreateNewBoard();
|
||
isSaveDataRequired = true;
|
||
}
|
||
|
||
// if (EventData.PieceItems is not { Count: > 0 })
|
||
if(EventData.PieceDatas is not {Count: > 0})
|
||
{
|
||
await CreateNewPieces();
|
||
isSaveDataRequired = true;
|
||
}
|
||
|
||
if (EventData.CollectItems is not { Count: > 0 })
|
||
{
|
||
UpdateNewCollect();
|
||
isSaveDataRequired = true;
|
||
}
|
||
|
||
if (isSaveDataRequired)
|
||
{
|
||
SaveData();
|
||
}
|
||
|
||
for (var i = CurrentPieceItems.Count; i < EventData.PieceDatas.Count; ++i)
|
||
{
|
||
CurrentPieceItems.Add(new PieceItem());
|
||
}
|
||
}
|
||
|
||
// 生成Item
|
||
private void InitPieceItems()
|
||
{
|
||
EventCubeMeltPieceItems.Clear();
|
||
foreach (var eventCubeMeltPiece in EventCubeMeltPieces)
|
||
{
|
||
foreach (var pc in eventCubeMeltPiece.PieceConfig)
|
||
{
|
||
EventCubeMeltPieceItems.Add(new PieceItem
|
||
{
|
||
MeltId = eventCubeMeltPiece.ID,
|
||
Weight = eventCubeMeltPiece.Weight,
|
||
PieceConfig = pc,
|
||
});
|
||
}
|
||
}
|
||
var valueBuilder = new StringBuilder();
|
||
foreach (var values in EventCubeMeltPieceItems)
|
||
{
|
||
valueBuilder.Append($"{values.MeltId},");
|
||
}
|
||
ELog($"UpdatePieceItems - >{valueBuilder}");
|
||
}
|
||
|
||
|
||
//TODO:CM 改成一次更新,多次返回的情况,每次更新 stageIndex 数据全部更新
|
||
/// <summary>
|
||
/// Key 为盘面 CellType(typeItem.Type),Value 含配置 TypeKey 与需求数量。
|
||
/// </summary>
|
||
public Dictionary<int, EventCubeMeltCollectionItemInfo> GetCollectionItems()
|
||
{
|
||
var ls = new Dictionary<int, EventCubeMeltCollectionItemInfo>();
|
||
for (var i = 0; i < EventCubeMeltCollectionData!.CollectingCountRequirement.Count; ++i)
|
||
{
|
||
var typeKey = EventCubeMeltCollectionData.CollectingItemRequirement[i];
|
||
var typeItem = EventCubeMeltItems.FirstOrDefault(elem => elem.ID == typeKey);
|
||
if (typeItem is { Type: > 0 })
|
||
{
|
||
var count = EventCubeMeltCollectionData.CollectingCountRequirement[i];
|
||
ls[typeItem.Type] = new EventCubeMeltCollectionItemInfo(typeKey, count);
|
||
}
|
||
}
|
||
|
||
var valueBuilder = new StringBuilder();
|
||
foreach (var kv in ls)
|
||
{
|
||
valueBuilder.Append($"{kv.Key}(key:{kv.Value.TrueId}):{kv.Value.RequiredCount} ");
|
||
}
|
||
ELog($"GetCollectionItems - >{valueBuilder}");
|
||
return ls;
|
||
}
|
||
|
||
private void CreateNewBoard()
|
||
{
|
||
var idx = Random.Range(0, EventCubeMeltConfig.Count);
|
||
ELog($"CreateNewBoard {idx}");
|
||
EventData.BoardData = EventCubeMeltConfig[idx];
|
||
var size = EventCubeMeltStageData.BoardSize;
|
||
EventData.BoardViewSize= new Vector2Int(size[0], size[1]);
|
||
}
|
||
|
||
|
||
private readonly int _pieceCount = 3;
|
||
private List<PieceItem> CurrentPieceItems { get; set; } = new();
|
||
|
||
private async Task CreateNewPieces()
|
||
{
|
||
ELog("CreateNewPieces");
|
||
// EventData.PieceItems.Clear();
|
||
CurrentPieceItems.Clear();
|
||
EventData.PieceDatas ??= new List<List<int>>();
|
||
EventData.PieceDatas.Clear();
|
||
|
||
|
||
if (EventCubeMeltStageData.InitItem is { Count: > 0 })
|
||
{
|
||
//TODO:注意保证InitItem的有效
|
||
var pieceIds = EventCubeMeltStageData.InitItem[0];
|
||
var repValueIndexs = EventCubeMeltStageData.InitItem[1];
|
||
var ids = EventCubeMeltStageData.InitItem[2];
|
||
|
||
var hasPieceIds = new List<int>(pieceIds.Where(id => id != 0));
|
||
|
||
for (var i = 0; i < _pieceCount; ++i)
|
||
{
|
||
var validMeltPieces = await GetValidMeltPieceItem();
|
||
var pieceId = pieceIds?[i]??0;
|
||
if (pieceId == 0)
|
||
{
|
||
validMeltPieces = validMeltPieces.Where(item => !hasPieceIds.Contains(item.MeltId)).ToList();
|
||
validMeltPieces = DoFilterSecond(validMeltPieces, EventData.PieceDatas);
|
||
var randomItem = WeightedRandom(validMeltPieces);
|
||
pieceId = randomItem.MeltId;
|
||
hasPieceIds.Add(pieceId);
|
||
}
|
||
var pieceItems = validMeltPieces.Where(item => item.MeltId == pieceId).ToList();
|
||
|
||
if (pieceItems.Count == 0)
|
||
{
|
||
LogError($"CreateNewPiecesInvalid pieceId = {pieceId}");
|
||
pieceItems = await GetValidMeltPieceItem();
|
||
}
|
||
|
||
var repValueIndex = repValueIndexs[i] ;
|
||
if (repValueIndex >= pieceItems.Count)
|
||
{
|
||
LogError($"CreateNewPiecesInvalid pieceId = {pieceId} repValueIndex={repValueIndex} validItemCount={pieceItems.Count}");
|
||
}
|
||
|
||
if (repValueIndex >= 0 && repValueIndex < pieceItems.Count)
|
||
{
|
||
var entity = pieceItems[repValueIndex];
|
||
CurrentPieceItems.Add(entity);
|
||
}
|
||
else
|
||
{
|
||
var entity = pieceItems[Random.Range(0, pieceItems.Count)];
|
||
CurrentPieceItems.Add(entity);
|
||
}
|
||
EventData.PieceDatas.Add(GetMeltPieceReal(i,ids[i],isPowerSet:true));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
var validMeltPieces = await GetValidMeltPieceItem();
|
||
var hasPieceIds = new List<int>();
|
||
for (var i = 0; i < _pieceCount; ++i)
|
||
{
|
||
validMeltPieces = validMeltPieces.Where(item => !hasPieceIds.Contains(item.MeltId)).ToList();
|
||
validMeltPieces = DoFilterSecond(validMeltPieces,EventData.PieceDatas);
|
||
var entity = WeightedRandom(validMeltPieces);
|
||
hasPieceIds.Add(entity.MeltId);
|
||
|
||
// var entity = validMeltPieces.FirstOrDefault(item => item.MeltId == pieceId);
|
||
// var entities = validMeltPieces.Where(item => item.MeltId == pieceId).ToList();
|
||
// var entity = entities[Random.Range(0, entities.Count)];
|
||
if (ShouldBuildELog())
|
||
{
|
||
ELog($"CreateNewPiece -> {entity?.MeltId} {string.Join(",", entity?.PieceConfig ?? new List<int>())}");
|
||
}
|
||
// EventData.PieceItems.Add(entity);
|
||
CurrentPieceItems.Add(entity);
|
||
EventData.PieceDatas.Add(GetMeltPieceReal(i));
|
||
}
|
||
}
|
||
|
||
|
||
// validMeltPieces = GetValidMeltPieceItem();
|
||
// for (var i = 0; i < _pieceCount; ++i)
|
||
// {
|
||
// validMeltPieces = DoFilterSecond(validMeltPieces,EventData.PieceDatas);
|
||
//
|
||
// var pieceId = WeightedRandom(validMeltPieces);
|
||
// // var entity = validMeltPieces.FirstOrDefault(item => item.MeltId == pieceId);
|
||
//
|
||
// var entities = validMeltPieces.Where(item => item.MeltId == pieceId).ToList();
|
||
// var entity = entities[Random.Range(0, entities.Count)];
|
||
// ELog($"CreateNewPiece -> {entity?.MeltId} {string.Join(",",entity?.PieceConfig ?? new List<int>())}");
|
||
// // EventData.PieceItems.Add(entity);
|
||
// CurrentPieceItems.Add(entity);
|
||
// EventData.PieceDatas.Add(GetMeltPieceReal(i));
|
||
// }
|
||
}
|
||
//-
|
||
private PieceItem WeightedRandom(List<PieceItem> pieceItems)
|
||
{
|
||
// return UnityEngine.Random.Range(0, pieceItems.Count);
|
||
// var totalWeight = pieceItems.Sum(pieceItem => pieceItem.Weight);
|
||
var totalWeight = pieceItems.Sum(item => item.ComplexityWeight);
|
||
|
||
// double min = 0.0;
|
||
// double max = 100.0;
|
||
var random = new System.Random();
|
||
double randomValue = (random.NextDouble() * (totalWeight - 0));
|
||
// var randomValue = Random.Range(0f, totalWeight);
|
||
var currentWeight = 0F;
|
||
foreach (var pieceItem in pieceItems)
|
||
{
|
||
currentWeight += (float)pieceItem.ComplexityWeight;
|
||
if (randomValue < currentWeight)
|
||
return pieceItem;
|
||
}
|
||
|
||
var item101 = pieceItems.Find(item => item.MeltId == 101);
|
||
// 默认返回一个点
|
||
// return 101 ; // 理论上不会执行到这里
|
||
return item101;
|
||
}
|
||
|
||
private void CreateNewData()
|
||
{
|
||
ELog("CreateNewData-> ");
|
||
var limitedTime = (LimitedTime)_fishingEvent.TimeDefinition;
|
||
var startTime = GlobalUtils.TryParseDateTime(limitedTime.StartTime, ZZTimeHelper.UtcNow());
|
||
var endTime = GlobalUtils.TryParseDateTime(limitedTime.EndTime, ZZTimeHelper.UtcNow());
|
||
var ticketCount = GContext.container.Resolve<FishingEventData>().GetInitWelcomeGift(_fishingEvent.ID);
|
||
// var ticketCount = GContext.container.Resolve<FishingEventData>().GetInitWelcomeGift(_fishingEvent.ID);
|
||
|
||
EventData = new EventCubeMeltData
|
||
{
|
||
FirstOpen = true,
|
||
EventId = _fishingEvent.ID,
|
||
TicketCount = ticketCount,
|
||
StartTime = startTime,
|
||
EndTime = endTime,
|
||
IsFinished = false,
|
||
CurrentStagetId = 0,
|
||
CollectItems = new List<CollectItem>(),
|
||
// PieceItems = new List<PieceItem>(),
|
||
PieceDatas = new List<List<int>>(),
|
||
CollectRewardsId = new List<int>(),
|
||
InflationRate = GContext.container.Resolve<PlayerData>().InflationRate
|
||
};
|
||
|
||
GContext.container.Resolve<FishingEventData>().SaveTransitionData(EventData.EventId, EventData.TicketCount);
|
||
// GContext.container.Resolve<GuideDataCenter>().ClearGuide(nameof(GroupName.Block01));
|
||
}
|
||
|
||
#region Log
|
||
|
||
private static void LogError(object message)
|
||
{
|
||
Debug.LogError($"<color=red>EventCubeMeltManager => {message} </color>");
|
||
}
|
||
|
||
private static bool ShouldBuildELog()
|
||
{
|
||
#if UNITY_EDITOR
|
||
return EventCubeMeltLogPolicy.EnableELog;
|
||
#else
|
||
return false;
|
||
#endif
|
||
}
|
||
|
||
private static void ELog(object message)
|
||
{
|
||
#if UNITY_EDITOR
|
||
if (!EventCubeMeltLogPolicy.EnableELog) return;
|
||
Debug.Log($"<color=orange> EventCubeMeltManager => {message} </color>");
|
||
#endif
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 时间相关
|
||
|
||
public bool CheckOpen()
|
||
{
|
||
//
|
||
if (EventData == null)
|
||
return false;
|
||
//
|
||
if (!IsTimeAllow())
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
public bool IsTimeAllow()
|
||
{
|
||
var now = ZZTimeHelper.UtcNow();
|
||
return now >= StartTime && now <= EndTime;
|
||
}
|
||
|
||
public TimeSpan GetRemainingTime()
|
||
{
|
||
if (EventData == null)
|
||
return TimeSpan.Zero;
|
||
|
||
return EndTime - ZZTimeHelper.UtcNow();
|
||
}
|
||
|
||
#endregion
|
||
|
||
public void OnSettle()
|
||
{
|
||
//throw new NotImplementedException();
|
||
ELog("OnSettle");
|
||
}
|
||
|
||
private void AddItem(int itemId, int count)
|
||
{
|
||
if (EventData?.CollectItems == null)
|
||
return;
|
||
var item = EventData.CollectItems.FirstOrDefault(x => x.ItemId == itemId);
|
||
if (item != null)
|
||
{
|
||
item.Count += count;
|
||
if (item.Count >= item.MaxCount)
|
||
{
|
||
item.Count = item.MaxCount;
|
||
}
|
||
}
|
||
}
|
||
|
||
//- [0,1]
|
||
public float GetCollectProgress()
|
||
{
|
||
var iCount = EventData.CollectItems.Count;
|
||
var iMaxCount = 0;
|
||
var iCollCount = 0;
|
||
// for (var i = 0; i < iCount; ++i)
|
||
foreach (var item in EventData.CollectItems)
|
||
{
|
||
iCollCount += item.Count;
|
||
iMaxCount += item.MaxCount;
|
||
}
|
||
return iCollCount * 1f / iMaxCount;
|
||
}
|
||
|
||
// 获取数据
|
||
public async Task SpawnNewPieceData()
|
||
{
|
||
|
||
}
|
||
public async Task SpawnNewPiece(int index,int clearCount)
|
||
{
|
||
ELog("SpawnNewPiece-> ");
|
||
|
||
var validMeltPieces = await GetValidNewPiece(index,clearCount);
|
||
var pieceItem = WeightedRandom(validMeltPieces);
|
||
if (pieceItem != null && ShouldBuildELog())
|
||
{
|
||
ELog(
|
||
$"SpawnNewPiece slotIndex={index} meltId={pieceItem.MeltId} row={pieceItem?.Row} col={pieceItem?.Col} complexity={pieceItem?.Complexity} complexityWeight={pieceItem.ComplexityWeight} config={string.Join(",", pieceItem.PieceConfig)}");
|
||
}
|
||
|
||
// var entities = validMeltPieces.Where(item => item.MeltId == pieceId).ToList();
|
||
// var entity = entities[Random.Range(0, entities.Count)];
|
||
// var entity = validMeltPieces.Find(item => item.MeltId == pieceId);
|
||
// ELog($"TCM: SpawnNewPiece -> {index} {pieceId} ");
|
||
// EventData.PieceItems[index] = entity;
|
||
// await Task.Run(() =>
|
||
{
|
||
CurrentPieceItems[index] = pieceItem;
|
||
EventData.PieceDatas[index] = GetMeltPieceReal(index);
|
||
SaveData();
|
||
}
|
||
|
||
ELog("SpawnNewPiece-> Finished-> ");
|
||
}
|
||
|
||
private async Task<List<PieceItem>> GetValidNewPiece(int index,int clearCount)
|
||
{
|
||
var validMeltPieces = await GetValidMeltPieceItem(clearCount);
|
||
var lastMeltPiece = EventData.PieceDatas[index];
|
||
// 和上一个不同
|
||
var validMeltPieces1 = DoFilterFirst(validMeltPieces,lastMeltPiece);
|
||
if (validMeltPieces1.Count <= 0)
|
||
{
|
||
return validMeltPieces;
|
||
}
|
||
//- 和全部不同
|
||
var validMeltPieces2 = DoFilterSecond(validMeltPieces1, EventData.PieceDatas);
|
||
if (validMeltPieces2.Count <= 0)
|
||
{
|
||
return validMeltPieces1;
|
||
}
|
||
return validMeltPieces2;
|
||
}
|
||
private List<PieceItem> DoFilterFirst(List<PieceItem> pieceItems, List<int> ints)
|
||
{
|
||
var checkInts = ints.Select(value => value == 0 ? 0 : 99);
|
||
return pieceItems.Where(p => !p.PieceConfig.SequenceEqual(checkInts)).ToList();
|
||
}
|
||
private List<PieceItem> DoFilterSecond(List<PieceItem> pieceItems, List<List<int>> eventDataPieceDatas)
|
||
{
|
||
return pieceItems?.Where(p => !eventDataPieceDatas?.Any(target =>
|
||
{
|
||
var checkInts = target.Select(value => value == 0 ? 0 : 99);
|
||
return p.PieceConfig.SequenceEqual(checkInts);
|
||
}) ?? true)
|
||
.ToList() ?? new List<PieceItem>();
|
||
}
|
||
|
||
// private List<PieceItem> GetValidMeltPieceItemByInitItem(List<int> pieceId, List<int> repValues)
|
||
// {
|
||
// // throw new NotImplementedException();
|
||
// var list = new List<PieceItem>();
|
||
// var grid = ConvertListIntToShape(EventData.BoardData,_boardDimension.x ,_boardDimension.y);
|
||
//
|
||
// foreach (var piece in EventCubeMeltPieceItems)
|
||
// {
|
||
// if (CanPlace(grid, ConvertListIntToShape(piece.PieceConfig,_pieceDimension.x ,_pieceDimension.y),piece.MeltId,out var p ))
|
||
// {
|
||
// piece.Complexity = p.Complexity;
|
||
// list.Add(piece);
|
||
// }
|
||
// }
|
||
// return list;
|
||
// }
|
||
|
||
public static double GaussianWeight(float x, double center = 0.5, double sigma = 1.0)
|
||
{
|
||
var diff = x - center;
|
||
var exponent = -(diff * diff) / (2 * sigma * sigma);
|
||
return Math.Exp(exponent);
|
||
}
|
||
|
||
//[0,1]-> [1,100]
|
||
public static float CosineWeight(float x, float center = 0.5f, double frequency = 2.0 * Math.PI)
|
||
{
|
||
var scaledX = (x - center) * frequency;
|
||
var cosineWeight = (float)(Math.Cos(scaledX) + 1.0F) / 2.0F;
|
||
return cosineWeight * 99.0F + 1.0F;
|
||
}
|
||
|
||
|
||
private async Task<List<PieceItem>> GetValidMeltPieceItem(int clearCount = 0)
|
||
{
|
||
var list = new List<PieceItem>();
|
||
// this.BoardViewSize.x
|
||
|
||
var grid = ConvertListIntToShape(EventData.BoardData,EventData.BoardViewSize.x ,EventData.BoardViewSize.y);
|
||
|
||
ELog($"GetValidMeltPieceItem-> Count = {EventCubeMeltPieceItems.Count}");
|
||
var weightDifficultyParam = EventCubeMeltStageData.WeightDifficultyParam;
|
||
var wdParam1 = weightDifficultyParam[0];
|
||
var wdParam2 = weightDifficultyParam[1];
|
||
var wdParam3 = weightDifficultyParam[2];
|
||
|
||
var priorityList1 = EventCubeMeltPieceItems.Where(item => item.MeltId > 300).ToList();
|
||
await Task.Run(() =>
|
||
{
|
||
foreach (var piece in priorityList1)
|
||
{
|
||
if (CanPlace(grid,
|
||
ConvertListIntToShape(piece.PieceConfig, _pieceDimension.x, _pieceDimension.y),
|
||
piece.MeltId,
|
||
out var p))
|
||
{
|
||
piece.Complexity = p.Complexity;
|
||
piece.ComplexityWeight = piece.Weight +
|
||
(float)wdParam1 * Math.Exp(wdParam2 * p.Complexity + wdParam3 * clearCount);
|
||
piece.Row = p.Row;
|
||
piece.Col = p.Col;
|
||
list.Add(piece);
|
||
}
|
||
} //一次性返回
|
||
});
|
||
|
||
//
|
||
if (list.Count <= 0)
|
||
{
|
||
if (ShouldBuildELog())
|
||
{
|
||
ELog($"GetValidMeltPieceItem priority1Empty boardData={string.Join(",", EventData.BoardData)}");
|
||
}
|
||
// list.Add(EventCubeMeltPieceItems.Find(item => item.MeltId == 101));
|
||
var priorityList2 = EventCubeMeltPieceItems.Where(item => item.MeltId <= 300).ToList();
|
||
// foreach (var piece in priorityList2)
|
||
// {
|
||
// if (CanPlace(grid, ConvertListIntToShape(piece.PieceConfig,_pieceDimension.x ,_pieceDimension.y),piece.MeltId,out var p))
|
||
// {
|
||
// piece.Complexity = p.Complexity;
|
||
// piece.ComplexityWeight = piece.Weight + (float) wdParam1 * Math.Exp(wdParam2 * p.Complexity + wdParam3 * clearCount);
|
||
// piece.Row = p.Row;
|
||
// piece.Col = p.Col;
|
||
// list.Add(piece);
|
||
// }
|
||
// }
|
||
await Task.Run(() =>
|
||
{
|
||
// var tmp = new List<PieceOut>(); //线程内临时列表
|
||
foreach (var piece in priorityList2)
|
||
{
|
||
if (CanPlace(grid, ConvertListIntToShape(piece.PieceConfig, _pieceDimension.x, _pieceDimension.y),
|
||
piece.MeltId,
|
||
out var p))
|
||
{
|
||
piece.Complexity = p.Complexity;
|
||
piece.ComplexityWeight = piece.Weight +
|
||
(float)wdParam1 * Math.Exp(wdParam2 * p.Complexity + wdParam3 * clearCount);
|
||
piece.Row = p.Row;
|
||
piece.Col = p.Col;
|
||
list.Add(piece);
|
||
}
|
||
} //一次性返回
|
||
});
|
||
}
|
||
ELog($"ClearCount count={clearCount}");
|
||
// StringBuilder sb;
|
||
#if UNITY_EDITOR
|
||
var sb = new StringBuilder();
|
||
foreach (var item in list)
|
||
{
|
||
sb.Append(item.MeltId + $"({item.Complexity:F3} , {item.ComplexityWeight:F3}) " );
|
||
}
|
||
ELog($"TCM:GetValidMeltPieceItem-> {sb}");
|
||
#endif
|
||
return list;
|
||
}
|
||
private int[,] ConvertListIntToShape(List<int> listInt,int gridW,int gridH)
|
||
{
|
||
// var width = _pieceDimension.x;
|
||
// var height = _pieceDimension.y;
|
||
var width = gridW;
|
||
var height = gridH;
|
||
|
||
var shape = new int[height,width];
|
||
for (var row = 0; row < height; row++)
|
||
{
|
||
for (var col = 0; col < width; col++)
|
||
{
|
||
shape[row, col] = listInt[row * width + col];
|
||
}
|
||
}
|
||
return shape;
|
||
}
|
||
|
||
// private int[,] ConvertToShape(EventCubeMeltPiece piece)
|
||
// {
|
||
// var width = _pieceDimension.x;
|
||
// var height = _pieceDimension.y;
|
||
//
|
||
// var shape = new int[height,width];
|
||
// var pieceData = piece.PieceConfig[0];
|
||
// for (var row = 0; row < height; row++)
|
||
// {
|
||
// for (var col = 0; col < width; col++)
|
||
// {
|
||
// shape[row, col] = pieceData[row * width + col];
|
||
// }
|
||
// }
|
||
// return shape;
|
||
// }
|
||
|
||
// public void PrintShape(int[,] grid, string tag )
|
||
// {
|
||
// var sb = new StringBuilder();
|
||
// sb.Append(tag);
|
||
// var height = grid.GetLength(0);
|
||
// var width = grid.GetLength(1);
|
||
// for (var i = 0; i < height; i++)
|
||
// {
|
||
// sb.Append("<color=red>");
|
||
// for (var j = 0; j < width; j++)
|
||
// {
|
||
// sb.Append((int)grid[i,j]);
|
||
// if (j < width - 1)
|
||
// sb.Append(", ");
|
||
// }
|
||
// sb.Append("</color> \n");
|
||
// }
|
||
// Debug.Log(sb.ToString());
|
||
// }
|
||
// 方形的
|
||
// private bool CanPlaceDown(int[,] grid, int [,] shape)
|
||
// {
|
||
// ELog("CanPlaceDown -> ");
|
||
// var gridSize = grid.GetLength(0);
|
||
// var shapeSize = shape.GetLength(0);
|
||
// if (shapeSize > gridSize )
|
||
// return false;
|
||
//
|
||
// List<(int row, int col)> shapePositions = new();
|
||
// for (int i = 0; i < shapeSize; i++)
|
||
// {
|
||
// for (int j = 0; j < shapeSize; j++)
|
||
// {
|
||
// if (shape[i, j] != 0 )
|
||
// {
|
||
// shapePositions.Add((i, j));
|
||
// }
|
||
// }
|
||
// }
|
||
// // 如果形状是空的,总是可以放入
|
||
// if (shapePositions.Count == 0)
|
||
// return true;
|
||
//
|
||
// for (var gridRow = 0; gridRow < gridSize; gridRow++)
|
||
// {
|
||
// for (var gridCol = 0; gridCol < gridSize; gridCol++)
|
||
// {
|
||
// // 检查是否可以把形状放在某个位置,使得所有有效格子都在网格内且为空
|
||
// if (CanPlaceShapeAtPosition(grid, shapePositions, gridRow, gridCol))
|
||
// {
|
||
// return true;
|
||
// }
|
||
// }
|
||
// }
|
||
// return false;
|
||
// }
|
||
|
||
private bool CanPlace(int[,] grid, int[,] shape, int pieceId,out ShapePlacement bestPlacementResult)
|
||
{
|
||
ELog($" CanPlace -> {pieceId}");
|
||
|
||
var gridRow = grid.GetLength(0);
|
||
var gridCol = grid.GetLength(1);
|
||
var shapeRow = shape.GetLength(0);
|
||
var shapeCol = shape.GetLength(1);
|
||
|
||
// 收集形状中所有有效格子的位置
|
||
var cells = new List<(int r, int c)>(shapeRow * shapeCol);
|
||
int minR = int.MaxValue, maxR = int.MinValue;
|
||
int minC = int.MaxValue, maxC = int.MinValue;
|
||
|
||
for (int r = 0; r < shapeRow; r++)
|
||
{
|
||
for (int c = 0; c < shapeCol; c++)
|
||
{
|
||
if (shape[r, c] != 0)
|
||
{
|
||
cells.Add((r, c));
|
||
if (r < minR) minR = r;
|
||
if (r > maxR) maxR = r;
|
||
if (c < minC) minC = c;
|
||
if (c > maxC) maxC = c;
|
||
}
|
||
}
|
||
}
|
||
|
||
bestPlacementResult = new ShapePlacement()
|
||
{
|
||
Id = pieceId,
|
||
Shape = (int[,])shape.Clone(),
|
||
Col = int.MinValue,
|
||
Row = int.MinValue,
|
||
Weight = 0,
|
||
Complexity = float.MaxValue,
|
||
};
|
||
|
||
// 若形状没有有效格子,视为可放置
|
||
if (cells.Count == 0)
|
||
{
|
||
bestPlacementResult.Col = 0;
|
||
bestPlacementResult.Row = 0;
|
||
return true;
|
||
}
|
||
|
||
// 有效格子全部进网格的必要偏移范围:
|
||
// 0 <= r + dy <= gr-1 对所有有效 r
|
||
// 0 <= c + dx <= gc-1 对所有有效 c
|
||
var minDy = -minR;
|
||
var maxDy = (gridRow - 1) - maxR;
|
||
var minDx = -minC;
|
||
var maxDx = (gridCol - 1) - maxC;
|
||
|
||
// 无可行偏移的快速剪枝
|
||
if (minDy > maxDy || minDx > maxDx)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
for (int offY = minDy; offY <= maxDy; offY++)
|
||
{
|
||
for (int offX = minDx; offX <= maxDx; offX++)
|
||
{
|
||
bool ok = true;
|
||
|
||
// 检查所有有效格子在该偏移下是否都落在空位(0)
|
||
for (int i = 0; i < cells.Count; i++)
|
||
{
|
||
var cell = cells[i];
|
||
int rr = cell.r + offY;
|
||
int cc = cell.c + offX;
|
||
|
||
// 这里不需要再做边界判断(已由范围剪枝保证)
|
||
if (grid[rr, cc] != 0)
|
||
{
|
||
ok = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (ok)
|
||
{
|
||
var p = CreateNewShapePlacement(offY,offX,shape,grid);
|
||
p.Id = pieceId;
|
||
// ELog($" CanPlace -> p = {p} best = {bestPlacementResult}");
|
||
if (p.Complexity < bestPlacementResult.Complexity)
|
||
bestPlacementResult = p;
|
||
}
|
||
}
|
||
}
|
||
|
||
// ELog($" CanPlace -> {pieceId} bestPlacementResult = {bestPlacementResult}");
|
||
if (bestPlacementResult.Complexity < float.MaxValue)
|
||
{
|
||
// ELog($" CanPlace -> {pieceId} bestPlacementResult = {bestPlacementResult}");
|
||
return true;
|
||
}
|
||
|
||
// dx = 0; dy = 0;
|
||
return false;
|
||
}
|
||
|
||
private ShapePlacement CreateNewShapePlacement(int row, int col,int[,] shape,int [,] grid)
|
||
{
|
||
var simulatedBoard = SimulatePlacement(grid,shape, row, col);
|
||
var pf1 = Calculate(grid);
|
||
var pf = Calculate(simulatedBoard);
|
||
|
||
|
||
return new ShapePlacement()
|
||
{
|
||
Row = row,
|
||
Col = col,
|
||
Shape = shape,
|
||
Weight = 1,
|
||
Complexity = pf - pf1
|
||
};
|
||
}
|
||
|
||
|
||
public static float Calculate(int[,] matrix)
|
||
{
|
||
if (matrix == null)
|
||
return 0;
|
||
|
||
int height = matrix.GetLength(0);
|
||
int width = matrix.GetLength(1);
|
||
|
||
// 创建带边框的矩阵便于计算
|
||
int[,] paddedMatrix = new int[height + 2, width + 2];
|
||
|
||
// 复制原矩阵到中心
|
||
for (int i = 0; i < height; i++)
|
||
{
|
||
for (int j = 0; j < width; j++)
|
||
{
|
||
paddedMatrix[i + 1, j + 1] = matrix[i, j];
|
||
}
|
||
}
|
||
|
||
// 计算边界长度(相邻0-1边的数量)
|
||
int boundaryEdges = 0;
|
||
|
||
for (int i = 1; i <= height; i++)
|
||
{
|
||
for (int j = 1; j <= width; j++)
|
||
{
|
||
if (paddedMatrix[i, j] != 0)
|
||
{
|
||
// 检查四个邻居
|
||
if (paddedMatrix[i - 1, j] == 0) boundaryEdges++; // 上
|
||
if (paddedMatrix[i + 1, j] == 0) boundaryEdges++; // 下
|
||
if (paddedMatrix[i, j - 1] == 0) boundaryEdges++; // 左
|
||
if (paddedMatrix[i, j + 1] == 0) boundaryEdges++; // 右
|
||
}
|
||
}
|
||
}
|
||
|
||
// 计算面积
|
||
int area = 0;
|
||
for (int i = 0; i < height; i++)
|
||
{
|
||
for (int j = 0; j < width; j++)
|
||
{
|
||
if (matrix[i, j] != 0)
|
||
area++;
|
||
}
|
||
}
|
||
|
||
var p = (float)Math.Sqrt(area)* 4F;
|
||
// var x = Math.Exp(p);
|
||
// 边界复杂度 = 边界长度 / 面积
|
||
return area > 0 ? (float)boundaryEdges / p : 0.0F;
|
||
}
|
||
|
||
private int[,] SimulatePlacement(int[,] board, int[,] shape, int row, int col)
|
||
{
|
||
// 创建棋盘的副本
|
||
int[,] simulatedBoard = (int[,])board.Clone();
|
||
|
||
var height = shape.GetLength(0);
|
||
var width = shape.GetLength(1);
|
||
|
||
var boardH = simulatedBoard.GetLength(0);
|
||
var boardW = simulatedBoard.GetLength(1);
|
||
|
||
// 放置形状
|
||
for (int i = 0; i < height; i++)
|
||
{
|
||
for (int j = 0; j < width; j++)
|
||
{
|
||
var rowI = row + i;
|
||
var colJ = col + j;
|
||
if (rowI < 0 || rowI >= boardH)
|
||
continue;
|
||
if (colJ < 0 || colJ >= boardW)
|
||
continue;
|
||
|
||
if (shape[i, j] != 0)
|
||
{
|
||
simulatedBoard[rowI, colJ] = 1; // 模拟形状,都放置成 1 先
|
||
}
|
||
}
|
||
}
|
||
return simulatedBoard;
|
||
}
|
||
|
||
private static bool CanPlaceShapeAtPosition(int[,] grid, List<(int row, int col)> validCells, int referenceRow, int referenceCol)
|
||
{
|
||
var gridSize = grid.GetLength(0);
|
||
|
||
// 我们尝试把形状的某个有效格子对齐到网格的(referenceRow, referenceCol)
|
||
// 然后检查其他有效格子是否都在网格内且为空
|
||
|
||
// 对第一个有效格子作为对齐点
|
||
var firstCell = validCells[0];
|
||
|
||
// 计算偏移量:如果要把这个有效格子放在(referenceRow, referenceCol)
|
||
// 那么形状的左上角应该在:
|
||
int startRow = referenceRow - firstCell.row;
|
||
int startCol = referenceCol - firstCell.col;
|
||
|
||
// 检查所有有效格子
|
||
foreach (var (shapeRow, shapeCol) in validCells)
|
||
{
|
||
int gridRow = startRow + shapeRow;
|
||
int gridCol = startCol + shapeCol;
|
||
|
||
// 检查是否在网格内
|
||
if (gridRow < 0 || gridRow >= gridSize || gridCol < 0 || gridCol >= gridSize)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// 检查网格位置是否为空
|
||
if (grid[gridRow, gridCol] != 0)
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
// 调试用,看看
|
||
public static List<(int row, int col)> FindAllPositions(int[,] grid, int[,] shape)
|
||
{
|
||
int M = grid.GetLength(0);
|
||
int N = shape.GetLength(0);
|
||
List<(int row, int col)> positions = new List<(int, int)>();
|
||
|
||
if (N > M) return positions;
|
||
|
||
// 预计算形状的非空位置
|
||
List<(int row, int col)> shapePositions = new List<(int, int)>();
|
||
for (int i = 0; i < N; i++)
|
||
{
|
||
for (int j = 0; j < N; j++)
|
||
{
|
||
if (shape[i, j] != 0)
|
||
{
|
||
shapePositions.Add((i, j));
|
||
}
|
||
}
|
||
}
|
||
|
||
// 遍历所有可能的放置位置
|
||
for (int i = 0; i <= M - N; i++)
|
||
{
|
||
for (int j = 0; j <= M - N; j++)
|
||
{
|
||
bool canPlace = true;
|
||
|
||
foreach (var (si, sj) in shapePositions)
|
||
{
|
||
int gi = i + si;
|
||
int gj = j + sj;
|
||
|
||
if (grid[gi, gj] != 0)
|
||
{
|
||
canPlace = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (canPlace)
|
||
{
|
||
positions.Add((i, j));
|
||
}
|
||
}
|
||
}
|
||
|
||
return positions;
|
||
}
|
||
|
||
public List<int> GetMeltPieceReal(int index,int isRepValue = 1,bool isPowerSet = false)
|
||
{
|
||
var pieceItem = CurrentPieceItems[index];
|
||
var meltPiece = EventCubeMeltPieces.FirstOrDefault(meltPiece => meltPiece.ID == pieceItem.MeltId );
|
||
ELog($"GetMeltPieceReal-> 12 {index} {meltPiece.ID} ,{meltPiece?.PieceConfig} {EventCubeMeltPieces.Count}");
|
||
|
||
var prop = EventCubeMeltCollectionData.CollectingItemProb;
|
||
|
||
var meltPieceConfig = pieceItem.PieceConfig;
|
||
var rate = meltPiece?.DoubleItemProb ?? 0;
|
||
var num = 1;
|
||
if (isPowerSet)
|
||
{
|
||
prop = new List<float> { 1 };
|
||
rate = 0;
|
||
}
|
||
if (rate > 0)
|
||
{
|
||
var r = Random.value; // [0,1)
|
||
if (r < rate)
|
||
{
|
||
num = 2;
|
||
}
|
||
}
|
||
var rand = GetRepValue();
|
||
var collectIds = GetCollectionIds();
|
||
// var randWeight = GetRepValuesWithWeight(rand);
|
||
|
||
// var thePieceData = (isRepValue == 0) ?meltPieceConfig : SlotsGenerator.GenerateSlots(num,prop,meltPieceConfig, rand);
|
||
var thePieceData2 = (isRepValue == 0) ?meltPieceConfig : SlotsGenerator.GenerateSlots2(num,prop,meltPieceConfig,rand,collectIds);
|
||
return thePieceData2;
|
||
//return meltPieceConfig;
|
||
}
|
||
|
||
public List<int> GetMeltPieceData(int index)
|
||
{
|
||
var pieceData = EventData.PieceDatas.ElementAtOrDefault(index);
|
||
return pieceData;
|
||
}
|
||
|
||
private List<int> GetCollectionIds()
|
||
{
|
||
var set = new HashSet<int>();
|
||
var collectionItems = GetCollectionItems();
|
||
foreach (var kv in collectionItems)
|
||
{
|
||
for (var i = 0; i < kv.Value.RequiredCount; ++i)
|
||
{
|
||
set.Add(kv.Key);
|
||
}
|
||
}
|
||
return set.ToList();
|
||
}
|
||
// 返回可替换的有效材料值
|
||
private List<int> GetRepValue()
|
||
{
|
||
var set = new HashSet<int>();
|
||
var collectionItems = GetCollectionItems();
|
||
foreach (var kv in collectionItems)
|
||
{
|
||
for (var i = 0; i < kv.Value.RequiredCount; ++i)
|
||
{
|
||
set.Add(kv.Key);
|
||
}
|
||
}
|
||
|
||
//
|
||
|
||
// 删除已经收集完的Item
|
||
var hasCollectItems = EventData.CollectItems;
|
||
foreach (var item in hasCollectItems.Where(item => item.Count >= item.MaxCount))
|
||
{
|
||
set.Remove(item.ItemId);
|
||
}
|
||
if (ShouldBuildELog())
|
||
{
|
||
ELog($"GetRepValue candidates={string.Join(",", set)}");
|
||
}
|
||
return set.ToList();
|
||
}
|
||
|
||
public void UpdateCurrentStage()
|
||
{
|
||
var isFirstLoop = EventData.Cycle == 0 ;
|
||
var stageList = isFirstLoop ? EventCubeMeltMainData?.StageFirstList : EventCubeMeltMainData?.StageLoopList ?? new List<int>();
|
||
|
||
var stageId = stageList?.ElementAtOrDefault(EventData.CurrentStagetId);
|
||
ELog($"UpdateCurrentStage -> {EventData.CurrentStagetId}, {stageId}");
|
||
EventCubeMeltStageData = _tables.TbEventCubeMeltStage.DataList.FirstOrDefault(data => data.ID == stageId);
|
||
EventCubeMeltCollectionData = _tables.TbEventCubeMeltCollection.DataList.FirstOrDefault(data => data.ID == stageId);
|
||
EventCubeMeltConfig = EventCubeMeltStageData?.StageConfig ?? new List<List<int>>();
|
||
|
||
EventStageList = stageList;
|
||
StageCount = EventStageList?.Count ?? 0;
|
||
var boardSize = EventCubeMeltStageData?.BoardSize;
|
||
if (boardSize == null)
|
||
{
|
||
LogError("Error Board No BoardSize ");
|
||
boardSize = new List<int>{8,8};
|
||
}
|
||
// BoardViewSize = new Vector2Int(boardSize[0], boardSize[1]);
|
||
}
|
||
|
||
private void UpdateNewCollect()
|
||
{
|
||
EventData.CollectItems.Clear();
|
||
var items = GetCollectionItems();
|
||
foreach (var kv in items)
|
||
{
|
||
EventData.CollectItems.Add(new CollectItem
|
||
{
|
||
ItemId = kv.Key,
|
||
ItemTrueId = kv.Value.TrueId,
|
||
Count = 0,
|
||
MaxCount = kv.Value.RequiredCount
|
||
});
|
||
}
|
||
}
|
||
public string GetCollectIconByType(int typeId)
|
||
{
|
||
var item = EventCubeMeltItems.FirstOrDefault(elem => elem.Type == typeId);
|
||
return item != null ? item.Icon : string.Empty;
|
||
}
|
||
|
||
public string GetCollectIconById(int typeId)
|
||
{
|
||
var item = EventCubeMeltItems.FirstOrDefault(elem => elem.ID == typeId);
|
||
return item != null ? item.Icon : string.Empty;
|
||
}
|
||
|
||
|
||
// 收集
|
||
public void AddCollect(Dictionary<int,int> values)
|
||
{
|
||
if (values is not { Count: > 0 })
|
||
{
|
||
return;
|
||
}
|
||
if (ShouldBuildELog())
|
||
{
|
||
var valueStrings = string.Join(", ", values.Select(kv => $"{kv.Key}: {kv.Value}"));
|
||
ELog($"LCM-> AddCollect -> {valueStrings}");
|
||
}
|
||
foreach (var kv in values)
|
||
{
|
||
AddItem(kv.Key, kv.Value);
|
||
}
|
||
}
|
||
public bool IsThisCollectFinished()
|
||
{
|
||
var items = EventData.CollectItems;
|
||
var isFinish = items.All(item => item.Count >= item.MaxCount);
|
||
return isFinish;
|
||
}
|
||
|
||
public bool IsGetStageReward()
|
||
{
|
||
var isGet = EventData.CollectRewardsId.Contains(EventData.CurrentStagetId);
|
||
return isGet;
|
||
}
|
||
|
||
public bool IsGetFinalReward()
|
||
{
|
||
return EventData.IsFinalRewardGet;
|
||
}
|
||
|
||
private async Task UpdateNextBoardAndPieces()
|
||
{
|
||
ELog("UpdateNextBoardAndPieces()");
|
||
CreateNewBoard();
|
||
await CreateNewPieces();
|
||
UpdateNewCollect();
|
||
SaveData();
|
||
}
|
||
|
||
public bool IsFinishAllStage() => EventData.CurrentStagetId >= StageCount - 1;
|
||
|
||
public async void UpdateToNextStage()
|
||
{
|
||
EventData.CurrentStagetId++;
|
||
if (EventData.CurrentStagetId > StageCount -1)
|
||
{
|
||
OnFinish();
|
||
return;
|
||
}
|
||
|
||
|
||
UpdateCurrentStage();
|
||
await UpdateNextBoardAndPieces();
|
||
GContext.Publish(new EventCubeMeltForNextStage());
|
||
}
|
||
|
||
public void GenerateNextStageData()
|
||
{
|
||
EventData.CurrentStagetId++;
|
||
if (EventData.CurrentStagetId > StageCount -1)
|
||
{
|
||
// ClearData();
|
||
// Init();
|
||
GenerateNewLoopFirstData();
|
||
}
|
||
UpdateCurrentStage();
|
||
_ = UpdateNextBoardAndPieces();
|
||
}
|
||
|
||
private void GenerateNewLoopFirstData()
|
||
{
|
||
var tickCount = EventData.TicketCount;
|
||
var cycle = EventData.Cycle;
|
||
ClearData();
|
||
Init();
|
||
EventData.TicketCount = tickCount;
|
||
EventData.FirstOpen = false;
|
||
EventData.Cycle = cycle + 1;
|
||
GContext.container.Resolve<FishingEventData>().SaveTransitionData(EventData.EventId, EventData.TicketCount);
|
||
SaveData();
|
||
}
|
||
|
||
public bool PlayGetStageReward()
|
||
{
|
||
ELog("AddStageRewards");
|
||
var dropId = EventCubeMeltCollectionData.CollectingReward;
|
||
var playerItemData = GContext.container.Resolve<PlayerItemData>();
|
||
|
||
var changeSource = new ChangeSource(EventData.EventId, "Event_Minigame1", "Event_Minigame1_Block", "StageReward");
|
||
playerItemData.AddItemByDropLureInflation(EventData.InflationRate,dropId,changeSource);
|
||
GContext.Publish(new ShowData());
|
||
EventData.CollectRewardsId.Add(EventData.CurrentStagetId);
|
||
SaveData();
|
||
return true;
|
||
}
|
||
|
||
// public bool PlayGetFinalRewards()
|
||
// {
|
||
// ELog("PlayGetFinalRewards-> ");
|
||
//
|
||
// var dropId = EventCubeMeltMainData.FinalReward;
|
||
// var playerItemData = GContext.container.Resolve<PlayerItemData>();
|
||
// var changeSource = new ChangeSource(EventData.EventId, "Event_Minigame1", "Event_Minigame1_Block", "StageReward");
|
||
// playerItemData.AddItemByDropLureInflation(null, dropId,changeSource);
|
||
// GContext.Publish(new ShowData());
|
||
//
|
||
// EventData.IsFinalRewardGet = true;
|
||
// SaveData();
|
||
// return true;
|
||
// }
|
||
|
||
public void OnFinish()
|
||
{
|
||
ELog("OnFinsish()");
|
||
ReOpen();
|
||
}
|
||
|
||
public void ReOpen()
|
||
{
|
||
GenerateNewLoopFirstData();
|
||
GContext.Publish(new EventCubemeltExitAct());
|
||
}
|
||
|
||
public void UpdateGridData(List<int> gridData)
|
||
{
|
||
EventData.BoardData = gridData;
|
||
SaveData();
|
||
}
|
||
|
||
//-
|
||
// private Vector2Int _boardDimension;
|
||
private Vector2Int _pieceDimension;
|
||
// public void SetBoardDimension(Vector2Int dimension)
|
||
// {
|
||
// _boardDimension = dimension;
|
||
// }
|
||
|
||
public void SetPieceDimension(Vector2Int dimension)
|
||
{
|
||
_pieceDimension = dimension;
|
||
}
|
||
|
||
|
||
private EventCubeMeltData PrevData { get; set; }
|
||
|
||
private EventCubeMeltData NextData { get; set; }
|
||
|
||
//-
|
||
private List<int> PrevBoardData { get; set; }
|
||
|
||
public List<List<int>> PrevPieceDatas { set; get; }
|
||
|
||
private List<int> CurrentBoardData { get; set; }
|
||
|
||
public List<List<int>> CurrentPieceDatas { set; get; }
|
||
|
||
// -当前的索引
|
||
public int GuideIndex { get; set; }
|
||
|
||
public void SaveDataForPrev()
|
||
{
|
||
// PrevData = EventData.ShallowClone();
|
||
//ELog($"SaveDataForPrev()-> {JsonConvert.SerializeObject(PrevData)}");
|
||
#if UNITY_EDITOR
|
||
PrevBoardData = EventData.BoardData.ToList();
|
||
PrevPieceDatas = EventData.PieceDatas.Select(innerList => new List<int>(innerList)).ToList();
|
||
#endif
|
||
}
|
||
|
||
public void SaveDataForNow()
|
||
{
|
||
#if UNITY_EDITOR
|
||
CurrentBoardData = EventData.BoardData.ToList();
|
||
CurrentPieceDatas = EventData.PieceDatas.Select(innerList => new List<int>(innerList)).ToList();
|
||
SaveData();
|
||
#endif
|
||
}
|
||
|
||
public void RestoreData()
|
||
{
|
||
EventData.BoardData = CurrentBoardData.ToList();
|
||
EventData.PieceDatas = CurrentPieceDatas.Select(innerList => new List<int>(innerList)).ToList();
|
||
SaveData();
|
||
}
|
||
|
||
public void LoadPrevData()
|
||
{
|
||
EventData.BoardData = PrevBoardData.ToList();
|
||
EventData.PieceDatas = PrevPieceDatas.Select(innerList => new List<int>(innerList)).ToList();
|
||
if (ShouldBuildELog())
|
||
{
|
||
ELog($"LoadPrevData()-> {JsonConvert.SerializeObject(EventData)}");
|
||
}
|
||
|
||
SaveData();
|
||
}
|
||
|
||
public bool IsUnCollectValue(int valueType)
|
||
{
|
||
var typeItem = EventCubeMeltItems.FirstOrDefault(elem => elem.Type == valueType);
|
||
var param = typeItem?.Param ?? 0;
|
||
return param > 1;
|
||
}
|
||
|
||
public List<int> ReplaceValue(int valueType)
|
||
{
|
||
var typeItem = EventCubeMeltItems.FirstOrDefault(elem => elem.Type == valueType);
|
||
var param = typeItem?.Param ?? 0;
|
||
if (param <= 1)
|
||
{
|
||
var values = new List<int> { valueType };
|
||
if (ShouldBuildELog())
|
||
{
|
||
ELog($"LCM-> ReplaceValue -> {valueType} -> {string.Join(", ", values)}");
|
||
}
|
||
return values;
|
||
}
|
||
// else
|
||
// {
|
||
// return new List<int>();
|
||
// }
|
||
|
||
var list = new List<int>();
|
||
var validList = GetRepValue();
|
||
for (var i = 0; i < param; i++)
|
||
{
|
||
var va = validList[Random.Range(0, validList.Count)];
|
||
list.Add(va);
|
||
}
|
||
if (ShouldBuildELog())
|
||
{
|
||
ELog($"LCM-> ReplaceValue -> {valueType} -> {string.Join(", ", list)}");
|
||
}
|
||
return list;
|
||
}
|
||
|
||
//-
|
||
public List<List<int>> GetBombValues(List<int> bombValues)
|
||
{
|
||
var p = new List<List<int>>();
|
||
foreach (var bombValue in bombValues)
|
||
{
|
||
p.Add(ReplaceValue(bombValue));
|
||
}
|
||
return p;
|
||
}
|
||
public void JumpToStage(int newStep)
|
||
{
|
||
// // var newStep = newDisStep - 1;
|
||
ELog($"JumpToStage -> {newStep }");
|
||
if (newStep < 0)
|
||
return;
|
||
|
||
EventData.CurrentStagetId = newStep - 1;
|
||
|
||
GContext.Publish(new EventCubeMeltStageFinish());
|
||
UpdateToNextStage();
|
||
|
||
// EventData.CurrentStagetId = newStep;
|
||
// if (EventData.CurrentStagetId > StageCount -1)
|
||
// {
|
||
// OnFinish();
|
||
// return;
|
||
// }
|
||
// //-
|
||
// EventData.IsFinished = false;
|
||
// UpdateCurrentStage();
|
||
// UpdateNextBoardAndPieces();
|
||
// GContext.Publish(new EventCubeMeltForNextStage());
|
||
}
|
||
//-检查当前管卡是否已经完
|
||
public bool IsOverStage()
|
||
{
|
||
return EventData.CurrentStagetId >= StageCount;
|
||
}
|
||
|
||
public void FixOverStage()
|
||
{
|
||
if (IsOverStage())
|
||
{
|
||
EventData.CurrentStagetId = StageCount - 1;
|
||
}
|
||
|
||
var isFinishThisStage = IsThisCollectFinished();
|
||
var isGetStageReward = IsGetStageReward();
|
||
if (EventData.CurrentStagetId < StageCount - 1)
|
||
{
|
||
if (isFinishThisStage && isGetStageReward)
|
||
{
|
||
GenerateNextStageData();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// var isFinalGet = IsGetFinalReward();
|
||
if (isFinishThisStage && isGetStageReward)
|
||
{
|
||
GenerateNextStageData();
|
||
}
|
||
}
|
||
}
|
||
|
||
public bool CheckCollectFinish(List<int> listItems)
|
||
{
|
||
var items = EventData.CollectItems;
|
||
return items.Any(item => listItems.Contains(item.ItemId) && item.Count == item.MaxCount);
|
||
}
|
||
|
||
public bool CheckBombFinsh(List<int> listBomb)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
public bool IsInGuideAnim()
|
||
{
|
||
return EventData?.IsInGuide ?? false ;
|
||
}
|
||
|
||
public void SetIsInGuideAnim(bool isInGuide)
|
||
{
|
||
// IsInGuide = isInGuide;
|
||
EventData.IsInGuide = isInGuide;
|
||
SaveData();
|
||
}
|
||
|
||
public int GetFinalReward()
|
||
{
|
||
ELog("GetFinalReward");
|
||
var finalStage = StageCount - 1;
|
||
// var isFirstLoop = EventData.Cycle == 0 ;
|
||
// var stageList = isFirstLoop ? EventCubeMeltMainData?.StageFirstList : EventCubeMeltMainData?.StageLoopList;
|
||
// var stageId = stageList?.ElementAtOrDefault(finalStage);
|
||
var stageId = EventStageList?.ElementAtOrDefault(finalStage);
|
||
var cubeMeltData = _tables.TbEventCubeMeltCollection.DataList.FirstOrDefault(data => data.ID == stageId);
|
||
return cubeMeltData?.CollectingReward?? 0;
|
||
}
|
||
} |