using System.Collections.Generic;
|
using UnityEngine;
|
using LitJson;
|
using System;
|
|
public class ArenaManager : GameSystemManager<ArenaManager>
|
{
|
public readonly int rankType = 1; // 榜单类型
|
public readonly int funcId = 27; // 功能Id
|
public readonly int recType = 308; // 演武场玩家挑战记录类型 308
|
public readonly int ChallengeMoneyType = 53;
|
public readonly int NeedChallengeMoneyCnt = 1;
|
public readonly int RecordType = 308; // 演武场玩家挑战记录
|
public int initialPoints; // 玩家初始积分
|
public int challengeRecordCount; // 被挑战记录条数(不超过50)
|
public int challengeTicketLimit; // 挑战券基础存储上限
|
public int[][] fixedChallengeRewards; // 固定挑战奖励 [[物品ID,个数], ...]
|
public int[][] matchVictoryPoints; // 匹配位置挑战胜利对应增减积分 [[挑战方增加积分, 防守方扣除积分], ...],长度即为匹配的人数,从最高分开始配置
|
public int lowerRankStart; // 从比自己低几个段的名次开始匹配
|
public int rankStep; // 每个匹配段跨x名,如配置 2|10,即代表从自己名次向后20名开始匹配,每跨10名匹配1人
|
public Dictionary<int, int[]> robotMatchCounts; // 玩家所在小于等于该名次对应匹配机器人数 {名次:[匹配机器人数下限, 上限], ...}
|
public int currencyType; // 刷新匹配固定消耗货币类型
|
public int currencyValue; // 刷新匹配固定消耗货币值
|
public Dictionary<int, int[][]> dailyRankRewards; // 每日排行奖励 {"名次":[[物品ID, 个数,是否拍品], ...], ...} 配置的名次key,自动按小于等于对应名次给奖励
|
public Dictionary<int, int[][]> seasonRankRewards; // 赛季排行奖励 {"名次":[[物品ID, 个数,是否拍品], ...], ...}
|
|
public uint score; // 当前积分
|
|
public List<ArenaMatchInfo> matchInfoList = new List<ArenaMatchInfo>();
|
//用于用来拿战斗胜利失败的头像信息
|
public Dictionary<uint, ArenaMatchInfo> allFaceInfoDict = new Dictionary<uint, ArenaMatchInfo>();
|
public Dictionary<uint, List<ArenaGameRec>> gameRecDict = new Dictionary<uint, List<ArenaGameRec>>(); // <RecID,ArenaGameRec>
|
public uint atkPlayerId;
|
public Redpoint parentRedpoint = new Redpoint(MainRedDot.MainChallengeRedpoint, MainRedDot.ArenaRepoint);
|
public Redpoint challengeButtonRedpoint;
|
public int nowAwardTabIndex = 0;
|
public event Action OnArenaMatchListEvent;
|
public event Action OnUpdateArenaPlayerInfo;
|
public event Action OnUpdateGameRecInfo;
|
public override void Init()
|
{
|
DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitializeEvent;
|
PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefresh;
|
InitTable();
|
InitRedpoint();
|
}
|
|
public override void Release()
|
{
|
DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitializeEvent;
|
PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefresh;
|
}
|
|
public void OnBeforePlayerDataInitializeEvent()
|
{
|
matchInfoList.Clear();
|
gameRecDict.Clear();
|
allFaceInfoDict.Clear();
|
}
|
|
void InitRedpoint()
|
{
|
challengeButtonRedpoint = new Redpoint(MainRedDot.ArenaRepoint, GetRedPonitId(1));
|
}
|
|
void InitTable()
|
{
|
FuncConfigConfig config = FuncConfigConfig.Get("ArenaSet");
|
initialPoints = int.Parse(config.Numerical1);
|
challengeRecordCount = int.Parse(config.Numerical2);
|
challengeTicketLimit = int.Parse(config.Numerical3);
|
fixedChallengeRewards = JsonMapper.ToObject<int[][]>(config.Numerical4);
|
|
config = FuncConfigConfig.Get("ArenaMatch");
|
matchVictoryPoints = JsonMapper.ToObject<int[][]>(config.Numerical1);
|
string[] matchParams = config.Numerical2.Split('|');
|
lowerRankStart = int.Parse(matchParams[0]);
|
rankStep = int.Parse(matchParams[1]);
|
robotMatchCounts = ConfigParse.GetDic<int, int[]>(config.Numerical3);
|
string[] costParams = config.Numerical4.Split('|');
|
currencyType = int.Parse(costParams[0]);
|
currencyValue = int.Parse(costParams[1]);
|
|
config = FuncConfigConfig.Get("ArenaBillboradAward");
|
dailyRankRewards = ConfigParse.ParseIntArray2Dict(config.Numerical1);
|
seasonRankRewards = ConfigParse.ParseIntArray2Dict(config.Numerical2);
|
}
|
public void UpdateRedPonit()
|
{
|
parentRedpoint.state = RedPointState.None;
|
challengeButtonRedpoint.state = RedPointState.None;
|
|
if (!FuncOpen.Instance.IsFuncOpen(funcId))
|
return;
|
|
if (UIHelper.GetMoneyCnt(ChallengeMoneyType) > 0)
|
{
|
challengeButtonRedpoint.state = RedPointState.Simple;
|
}
|
}
|
|
public bool TryGetPlayerInfo(uint playerID, out ArenaMatchInfo info)
|
{
|
return allFaceInfoDict.TryGetValue(playerID, out info);
|
}
|
|
// 1 挑战按钮
|
public int GetRedPonitId(int num)
|
{
|
return MainRedDot.ArenaRepoint * 10 + num;
|
}
|
|
private void PlayerDataRefresh(PlayerDataType type)
|
{
|
if (type != PlayerDataType.ChallengeVoucher)
|
return;
|
UpdateRedPonit();
|
}
|
|
public int GetMaxChallengeCount()
|
{
|
return challengeTicketLimit;
|
}
|
|
public void OnArenaMatchList(HA922_tagSCArenaMatchList vNetData)
|
{
|
if (vNetData == null || vNetData.MatchList.IsNullOrEmpty())
|
return;
|
|
matchInfoList.Clear();
|
|
foreach (var item in vNetData.MatchList)
|
{
|
var matchInfo = new ArenaMatchInfo
|
{
|
PlayerID = item.PlayerID,
|
PlayerName = item.PlayerName,
|
Lv = item.LV,
|
RealmLV = item.RealmLV,
|
FightPower = (ulong)item.FightPowerEx * 100000000 + (ulong)item.FightPower,
|
Face = item.Face,
|
FacePic = item.FacePic
|
};
|
matchInfoList.Add(matchInfo);
|
allFaceInfoDict[item.PlayerID] = matchInfo;
|
}
|
matchInfoList.Reverse();
|
OnArenaMatchListEvent?.Invoke();
|
}
|
|
|
public void UpdateArenaPlayerInfo(HA923_tagSCArenaPlayerInfo vNetData)
|
{
|
if (vNetData == null)
|
return;
|
this.score = vNetData.Score;
|
OnUpdateArenaPlayerInfo?.Invoke();
|
}
|
public void UpdateGameRecInfo(HA009_tagSCGameRecInfo vNetData)
|
{
|
if (vNetData == null || vNetData.RecType != recType)
|
return;
|
gameRecDict.Clear();
|
uint recID = vNetData.RecID;
|
if (!gameRecDict.ContainsKey(recID))
|
gameRecDict[recID] = new List<ArenaGameRec>();
|
foreach (var rec in vNetData.RecList)
|
{
|
try
|
{
|
var userData = JsonMapper.ToObject(rec.UserData);
|
string name = userData["Name"].ToString();
|
int addScore = int.Parse(userData["AddScore"].ToString());
|
ulong fightPower = ulong.Parse(userData["FightPower"].ToString());
|
|
var arenaGameRec = new ArenaGameRec
|
{
|
Time = rec.Time,
|
Value1 = rec.Value1,
|
Value2 = rec.Value2,
|
Value3 = rec.Value3,
|
Value4 = rec.Value4,
|
Value5 = rec.Value5,
|
Value6 = rec.Value6,
|
Value7 = rec.Value7,
|
Value8 = rec.Value8,
|
Name = name,
|
AddScore = addScore,
|
FightPower = fightPower
|
};
|
|
gameRecDict[recID].Add(arenaGameRec);
|
|
if (recID == PlayerDatas.Instance.baseData.PlayerID)
|
{
|
allFaceInfoDict[rec.Value3] = new ArenaMatchInfo
|
{
|
Face = rec.Value5,
|
FacePic = rec.Value6,
|
RealmLV = (ushort)rec.Value7,
|
Lv = (ushort)rec.Value8,
|
PlayerName = name,
|
FightPower = fightPower,
|
};
|
}
|
|
}
|
catch (Exception ex)
|
{
|
Debug.LogError($"JSON解析错误: {ex.Message}, UserData: {rec.UserData}");
|
continue;
|
}
|
}
|
OnUpdateGameRecInfo?.Invoke();
|
}
|
|
|
public Dictionary<int, int[][]> GetArenaAwardDict(int functionOrder)
|
{
|
return functionOrder == 0 ? dailyRankRewards : seasonRankRewards;
|
}
|
|
public void SendViewGameRecPack()
|
{
|
CA008_tagCSViewGameRec pack = new CA008_tagCSViewGameRec();
|
pack.RecType = (ushort)RecordType;
|
GameNetSystem.Instance.SendInfo(pack);
|
}
|
|
public void SendArenaMatch(bool isRefresh = false)
|
{
|
CB209_tagCSArenaMatch pack = new CB209_tagCSArenaMatch();
|
pack.IsRefresh = isRefresh ? (byte)1 : (byte)0;
|
GameNetSystem.Instance.SendInfo(pack);
|
}
|
|
public void SendTurnFight(uint playerID)
|
{
|
CB410_tagCMTurnFight pack = new CB410_tagCMTurnFight();
|
pack.MapID = 3;
|
pack.TagType = 1;
|
pack.TagID = playerID;
|
GameNetSystem.Instance.SendInfo(pack);
|
}
|
|
public bool IsTimeInvalid(uint time)
|
{
|
DateTime dateTime = TimeUtility.GetTime(time);
|
GetCurrentSeasonDates(out DateTime seasonStartDate, out DateTime seasonEndDate);
|
return dateTime < seasonStartDate || dateTime > seasonEndDate;
|
}
|
|
/// <summary>
|
/// 根据索引和排序方向获取积分
|
/// </summary>
|
/// <param name="index">索引位置(从0开始)</param>
|
/// <param name="isAscending">true-正序,false-倒序</param>
|
/// <param name="isChallenger">true-挑战方增加积分,false-防守方扣除积分</param>
|
/// <returns>对应的积分值</returns>
|
public int GetChallengePoints(int index, bool isAscending = false, bool isChallenger = true)
|
{
|
// 检查索引是否在有效范围内
|
if (matchVictoryPoints.IsNullOrEmpty() || index < 0 || index >= matchVictoryPoints.Length)
|
return 0;
|
int targetIndex = isAscending ? index : matchVictoryPoints.Length - 1 - index;
|
return matchVictoryPoints[targetIndex][isChallenger ? 0 : 1];
|
}
|
|
/// <summary>
|
/// 获得当前赛季的起止日期。赛季从周一 00:00:00 开始,到周日 23:59:59 结束。
|
/// 服务端定义周一为每周的第一天。
|
/// </summary>
|
/// <param name="seasonStartDate">输出参数:赛季的起始日期(本周一 00:00:00)</param>
|
/// <param name="seasonEndDate">输出参数:赛季的结束日期(本周日 23:59:59)</param>
|
public void GetCurrentSeasonDates(out DateTime seasonStartDate, out DateTime seasonEndDate)
|
{
|
DateTime now = TimeUtility.ServerNow;
|
// 在 .NET 中,DayOfWeek 枚举 Sunday = 0, Monday = 1, ..., Saturday = 6。
|
// 为了符合周一是一周第一天的计算标准,我们将周日视为一周的第7天。
|
int currentDayOfWeek = (int)now.DayOfWeek;
|
if (currentDayOfWeek == 0) // 如果是周日 (Sunday = 0)
|
{
|
currentDayOfWeek = 7;
|
}
|
|
// 从当前日期减去相应的天数,得到周一的日期。
|
// 例如,如果是周三(3),则需要减去 3-1=2 天。
|
// 如果是周日(7),则需要减去 7-1=6 天。
|
DateTime monday = now.AddDays(-(currentDayOfWeek - 1));
|
// 设置赛季的起始时间为周一的 0点0分0秒
|
seasonStartDate = new DateTime(monday.Year, monday.Month, monday.Day, 0, 0, 0);
|
// 赛季的结束日期是开始日期(周一)加上6天,即周日
|
DateTime sunday = seasonStartDate.AddDays(6);
|
// 设置赛季的结束时间为周日的 23点59分59秒
|
seasonEndDate = new DateTime(sunday.Year, sunday.Month, sunday.Day, 23, 59, 59);
|
}
|
|
/// <summary>
|
/// 根据recID获取按时间从大到小排序的List<ArenaGameRec>
|
/// </summary>
|
/// <param name="recID">记录ID</param>
|
/// <param name="sortedList">输出参数:按时间从大到小排序的ArenaGameRec列表</param>
|
/// <returns>如果recID存在且成功获取列表返回true,否则返回false</returns>
|
public bool TryGetSortedArenaGameRecList(uint recID, out List<ArenaGameRec> sortedList)
|
{
|
sortedList = null;
|
if (!gameRecDict.ContainsKey(recID))
|
return false;
|
sortedList = new List<ArenaGameRec>(gameRecDict[recID]);
|
sortedList.Sort((a, b) => b.Time.CompareTo(a.Time)); // 按时间从大到小排序
|
return true;
|
}
|
}
|
|
|
|
|
public class ArenaMatchInfo
|
{
|
public uint PlayerID; //目标玩家ID
|
public string PlayerName;
|
public ushort Lv; //等级
|
public ushort RealmLV; //境界,机器人读境界表取等级对应境界
|
public uint TitleID;
|
public ulong FightPower; //战力
|
public uint Face; //基本脸型
|
public uint FacePic; //头像框
|
|
}
|
|
public class ArenaGameRec
|
{
|
public uint Time; //战斗时间戳
|
public uint Value1; //更新积分,战斗后的最终积分
|
public uint Value2; //攻击类型 1-发起攻击的,2-被攻击的
|
public uint Value3; //相对攻击类型的目标玩家ID
|
public uint Value4; //是否获胜 1-获胜;2-失败
|
public uint Value5; //目标头像
|
public uint Value6; //目标头像框
|
public uint Value7; //目标官职
|
public uint Value8; //目标等级
|
public string Name; //目标名称
|
public int AddScore; //本次自己变更的积分,有正负
|
public ulong FightPower; //目标战力
|
public int TitileId; //未来接入
|
|
}
|