Main/Config/Configs/SuccessConfig.cs
@@ -1,6 +1,6 @@ //-------------------------------------------------------- // [Author]: YYL // [ Date ]: 2025年8月5日 // [ Date ]: 2025年11月6日 //-------------------------------------------------------- using System.Collections.Generic; @@ -18,24 +18,9 @@ public int ID; public int Type; public int Group; public int NeedCnt; public int[] Condition; public string Condition2; public int Condition3; public string AwardItemList; public string AwardItemList2; public string Money; public int Exp; public int[] AwardAttribute; public int RedPacketID; public int MagicWeaponID; public string MagicWeaponExp; public string Describe; public int NeedGoto; public int Jump; public int ReOrder; public int RealmPracticeID; public int[][] AwardItemList; public override int LoadKey(string _key) { @@ -51,17 +36,15 @@ int.TryParse(tables[1],out Type); int.TryParse(tables[2],out Group); int.TryParse(tables[2],out NeedCnt); int.TryParse(tables[3],out NeedCnt); if (tables[4].Contains("[")) if (tables[3].Contains("[")) { Condition = JsonMapper.ToObject<int[]>(tables[4]); Condition = JsonMapper.ToObject<int[]>(tables[3]); } else { string[] ConditionStringArray = tables[4].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries); string[] ConditionStringArray = tables[3].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries); Condition = new int[ConditionStringArray.Length]; for (int i=0;i<ConditionStringArray.Length;i++) { @@ -69,47 +52,7 @@ } } Condition2 = tables[5]; int.TryParse(tables[6],out Condition3); AwardItemList = tables[7]; AwardItemList2 = tables[8]; Money = tables[9]; int.TryParse(tables[10],out Exp); if (tables[11].Contains("[")) { AwardAttribute = JsonMapper.ToObject<int[]>(tables[11]); } else { string[] AwardAttributeStringArray = tables[11].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries); AwardAttribute = new int[AwardAttributeStringArray.Length]; for (int i=0;i<AwardAttributeStringArray.Length;i++) { int.TryParse(AwardAttributeStringArray[i],out AwardAttribute[i]); } } int.TryParse(tables[12],out RedPacketID); int.TryParse(tables[13],out MagicWeaponID); MagicWeaponExp = tables[14]; Describe = tables[15]; int.TryParse(tables[16],out NeedGoto); int.TryParse(tables[17],out Jump); int.TryParse(tables[18],out ReOrder); int.TryParse(tables[19],out RealmPracticeID); AwardItemList = JsonMapper.ToObject<int[][]>(tables[4].Replace("(", "[").Replace(")", "]")); } catch (Exception exception) { Main/Config/PartialConfigs/MainLevelConfig.cs
@@ -46,5 +46,13 @@ return waveLineupLists.Count(list => list.Length > 0); } // 获取目标关卡的索引 public static int GetToTargetLevelIndex(int targetLevel) { var levels = GetKeys(); levels.Sort(); return levels.IndexOf(targetLevel); } } Main/Config/PartialConfigs/SuccessConfig.cs
New file @@ -0,0 +1,33 @@ using System.Collections.Generic; public partial class SuccessConfig : ConfigBase<int, SuccessConfig> { public static Dictionary<int, List<int>> typeToIDsDict = new Dictionary<int, List<int>>(); protected override void OnConfigParseCompleted() { if (!typeToIDsDict.ContainsKey(Type)) { typeToIDsDict[Type] = new List<int>(); } typeToIDsDict[Type].Add(ID); } public static List<int> GetTypeToIDDict(int type) { if (typeToIDsDict.ContainsKey(type)) { return typeToIDsDict[type]; } return null; } //获得成就条件,默认一个类型只有一种条件 public static string GetConditionString(int type) { if (typeToIDsDict.ContainsKey(type)) { var conds = Get(typeToIDsDict[type][0]).Condition; return conds.IsNullOrEmpty() ? "" : conds.ToString(); } return ""; } } Main/Config/PartialConfigs/SuccessConfig.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: 5c9f079829a75b84587ebbbd29a56119 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA340_tagSCSuccessInfoList.cs
New file @@ -0,0 +1,12 @@ using UnityEngine; using System.Collections; // A3 40 成就信息列表 #tagSCSuccessInfoList public class DTCA340_tagSCSuccessInfoList : DtcBasic { public override void Done(GameNetPackBasic vNetPack) { base.Done(vNetPack); HA340_tagSCSuccessInfoList vNetData = vNetPack as HA340_tagSCSuccessInfoList; AchievementManager.Instance.UpdateAchievement(vNetData); } } Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA340_tagSCSuccessInfoList.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: 2349866a7124b0c488485ddc575a80b9 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA342_tagSCSuccessAwardRecordList.cs
New file @@ -0,0 +1,12 @@ using UnityEngine; using System.Collections; // A3 42 成就领奖记录列表 #tagSCSuccessAwardRecordList public class DTCA342_tagSCSuccessAwardRecordList : DtcBasic { public override void Done(GameNetPackBasic vNetPack) { base.Done(vNetPack); HA342_tagSCSuccessAwardRecordList vNetData = vNetPack as HA342_tagSCSuccessAwardRecordList; AchievementManager.Instance.UpdateAchievementAward(vNetData); } } Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA342_tagSCSuccessAwardRecordList.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: b0b463773ed6e62448f3b7158f1ab2a5 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs
@@ -120,6 +120,8 @@ Register(typeof(HA923_tagSCArenaPlayerInfo), typeof(DTCA923_tagSCArenaPlayerInfo)); Register(typeof(HB109_tagSCDailyTaskInfo), typeof(DTCB109_tagSCDailyTaskInfo)); Register(typeof(HB201_tagSCTianziKYInfo), typeof(DTCB201_tagSCTianziKYInfo)); Register(typeof(HA340_tagSCSuccessInfoList), typeof(DTCA340_tagSCSuccessInfoList)); Register(typeof(HA342_tagSCSuccessAwardRecordList), typeof(DTCA342_tagSCSuccessAwardRecordList)); } //主工程注册封包 Main/Core/NetworkPackage/ServerPack/HA3_Function/HA340_tagSCSuccessInfoList.cs
New file @@ -0,0 +1,33 @@ using UnityEngine; using System.Collections; // A3 40 成就信息列表 #tagSCSuccessInfoList public class HA340_tagSCSuccessInfoList : GameNetPackBasic { public ushort Count; //信息个数 public tagSCSuccessInfo[] SuccessInfoList; public HA340_tagSCSuccessInfoList () { _cmd = (ushort)0xA340; } public override void ReadFromBytes (byte[] vBytes) { TransBytes (out Count, vBytes, NetDataType.WORD); SuccessInfoList = new tagSCSuccessInfo[Count]; for (int i = 0; i < Count; i ++) { SuccessInfoList[i] = new tagSCSuccessInfo(); TransBytes (out SuccessInfoList[i].SuccType, vBytes, NetDataType.WORD); TransBytes (out SuccessInfoList[i].CLen, vBytes, NetDataType.BYTE); TransBytes (out SuccessInfoList[i].Conds, vBytes, NetDataType.DWORD, SuccessInfoList[i].CLen); TransBytes (out SuccessInfoList[i].CurValue, vBytes, NetDataType.DWORD); } } public class tagSCSuccessInfo { public ushort SuccType; //成就类型 public byte CLen; public uint[] Conds; // 条件列表 public uint CurValue; // 进度值,相同任务类型条件的进度值共享 } } Main/Core/NetworkPackage/ServerPack/HA3_Function/HA340_tagSCSuccessInfoList.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: 0da6e6a7f64979d4e9d2e102f68fef21 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/Core/NetworkPackage/ServerPack/HA3_Function/HA342_tagSCSuccessAwardRecordList.cs
New file @@ -0,0 +1,29 @@ using UnityEngine; using System.Collections; // A3 42 成就领奖记录列表 #tagSCSuccessAwardRecordList public class HA342_tagSCSuccessAwardRecordList : GameNetPackBasic { public ushort RecordCnt; //记录个数 public tagSCSuccessAwardRecord[] RecordList; //记录列表 public HA342_tagSCSuccessAwardRecordList () { _cmd = (ushort)0xA342; } public override void ReadFromBytes (byte[] vBytes) { TransBytes (out RecordCnt, vBytes, NetDataType.WORD); RecordList = new tagSCSuccessAwardRecord[RecordCnt]; for (int i = 0; i < RecordCnt; i ++) { RecordList[i] = new tagSCSuccessAwardRecord(); TransBytes (out RecordList[i].RecordIndex, vBytes, NetDataType.WORD); TransBytes (out RecordList[i].Record, vBytes, NetDataType.DWORD); } } public class tagSCSuccessAwardRecord { public ushort RecordIndex; //第几个记录值 每个key存31个succid 0-30为0, 31-61为1.. public uint Record; //根据成就ID位判断是否已领取 } } Main/Core/NetworkPackage/ServerPack/HA3_Function/HA342_tagSCSuccessAwardRecordList.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: be0a52fd85a2e37429a2ed249d0fa74f MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/System/Achievement.meta
New file @@ -0,0 +1,8 @@ fileFormatVersion: 2 guid: 3793503c7ba33204da1ca91f1bb6aacd folderAsset: yes DefaultImporter: externalObjects: {} userData: assetBundleName: assetBundleVariant: Main/System/Achievement/AchievementManager.cs
New file @@ -0,0 +1,196 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.Linq; public partial class AchievementManager : GameSystemManager<AchievementManager> { //成就类型:条件(可以是空):进度 Dictionary<int, Dictionary<string, int>> achivementDict = new Dictionary<int, Dictionary<string, int>>(); public event Action<int> OnAchievementUpdateEvent; //key:第几个记录值 每个key存31个succid 0-30为0, 31-61为1..; value: 根据成就ID位判断是否已领取 Dictionary<int, int> achivementAwardDict = new Dictionary<int, int>(); public override void Init() { DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitialize; } public override void Release() { DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitialize; } void OnBeforePlayerDataInitialize() { } public void UpdateAchievement(HA340_tagSCSuccessInfoList netPack) { List<int> types = new List<int>(); for (int i = 0; i < netPack.Count; i++) { var info = netPack.SuccessInfoList[i]; if (!achivementDict.ContainsKey(info.SuccType)) { achivementDict[info.SuccType] = new Dictionary<string, int>(); } string key = info.CLen > 0 ? info.Conds.ToString() : ""; achivementDict[info.SuccType][key] = (int)info.CurValue; OnAchievementUpdateEvent?.Invoke(info.SuccType); if (!types.Contains(info.SuccType)) { types.Add(info.SuccType); } } UpdateRedpoint(types); } public int GetAchievementProgress(int type) { if (achivementDict.ContainsKey(type)) { var condKey = SuccessConfig.GetConditionString(type); if (achivementDict[type].ContainsKey(condKey)) { return achivementDict[type][condKey]; } } return 0; } public void UpdateAchievementAward(HA342_tagSCSuccessAwardRecordList netPack) { List<int> types = new List<int>(); for (int i = 0; i < netPack.RecordCnt; i++) { var record = netPack.RecordList[i]; achivementAwardDict[record.RecordIndex] = (int)record.Record; var startID = record.RecordIndex * 31; var endID = startID + 30; for (int j = startID; j <= endID; j++) { if (SuccessConfig.HasKey(j)) { var type = SuccessConfig.Get(j).Type; if (!types.Contains(type)) { types.Add(type); } } } } OnAchievementUpdateEvent?.Invoke(-1); UpdateRedpoint(types); } //成就是否已领取 //每个key存31个succid 0-30为0, 31-61为1..; 根据成就ID位判断是否已领取 public bool IsAchievementAwarded(int id) { var index = id / 31; var bit = id % 31; if (achivementAwardDict.ContainsKey(index)) { return (achivementAwardDict[index] & (1 << bit)) != 0; } return false; } //获取成就状态 0: 未领取 1: 未达成 2: 已领取 public int GetAchievementState(int id) { var process = GetAchievementProgress(id); var config = SuccessConfig.Get(id); if (process < config.NeedCnt) { return 1; } if (IsAchievementAwarded(id)) { return 2; } return 0; } //主线章节 Redpoint mainLevelRedpoint = new Redpoint(MainRedDot.RedPoint_DailyKey, MainRedDot.RedPoint_MainMissionKey); //类型:红点id Dictionary<int, int> redpointDict = new Dictionary<int, int>() { {1, MainRedDot.RedPoint_MainMissionKey} }; void UpdateRedpoint(List<int> _types) { if (_types.IsNullOrEmpty()) { _types = redpointDict.Keys.ToList(); } foreach (var type in _types) { var redpoint = RedpointCenter.Instance.GetRedpoint(redpointDict[type]); redpoint.state = RedPointState.None; //根据ID判断是否有可领取的 var allAchivement = SuccessConfig.GetTypeToIDDict(type); var process = GetAchievementProgress(type); foreach (var id in allAchivement) { var config = SuccessConfig.Get(id); if (config.NeedCnt <= process) { if (!IsAchievementAwarded(id)) { redpoint.state = RedPointState.Simple; break; } } } } } //根据类型获取所有成就ID, 且是排序后的 未领取>未达成>已领取 public List<int> GetAchievementIDs(int type) { var ids = SuccessConfig.GetTypeToIDDict(type); ids.Sort(CmpIds); return ids; } int CmpIds(int a, int b) { var stateA = GetAchievementState(a); var stateB = GetAchievementState(b); if (stateA != stateB) { return stateA - stateB; } return a - b; } public void SendGetAward(int id) { var config = SuccessConfig.Get(id); //简单判断背包 if (PackManager.Instance.GetEmptyGridCount(PackType.Item) < config.AwardItemList.Length) { SysNotifyMgr.Instance.ShowTip("GeRen_lhs_202580"); return; } var pack = new CA504_tagCMPlayerGetReward(); pack.RewardType = 59; pack.DataEx = (uint)id; GameNetSystem.Instance.SendInfo(pack); } } Main/System/Achievement/AchievementManager.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: cf5275bc4183a394c83cbfa9707c3f13 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/System/DayMission/DayMissionBaseWin.cs
@@ -27,7 +27,7 @@ break; case 2: //主线任务(英雄之路) currentSubUI = UIManager.Instance.OpenWindow<DayMissionWin>(); currentSubUI = UIManager.Instance.OpenWindow<MissionHeroRoadWin>(); titleText.text = Language.Get("DayMission4"); break; default: Main/System/DayMission/MissionHeroRoadCell.cs
New file @@ -0,0 +1,68 @@ using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; public class MissionHeroRoadCell : CellView { [SerializeField] Text nameText; [SerializeField] Image processImg; [SerializeField] Text processText; [SerializeField] ItemCell[] itemCells; [SerializeField] Transform[] gotRects; [SerializeField] Button getBtn; [SerializeField] Button gotoBtn; [SerializeField] Transform gotRect; [SerializeField] Transform mask; public void Display(int id) { var config = SuccessConfig.Get(id); nameText.text = Language.Get("Achievement1", config.NeedCnt / 100, config.NeedCnt % 100); var targetLevel = MainLevelConfig.GetToTargetLevelIndex(config.NeedCnt) + 1; var curLevel = MainLevelConfig.GetToTargetLevelIndex(AchievementManager.Instance.GetAchievementProgress(config.Type)) + 1; processImg.fillAmount = (float)curLevel / targetLevel; processText.text = Math.Min(targetLevel, curLevel) + "/" + targetLevel; var state = AchievementManager.Instance.GetAchievementState(id); for (int i = 0; i < itemCells.Length; i++) { if (i < config.AwardItemList.Length) { itemCells[i].SetActive(true); int itemID = config.AwardItemList[i][0]; itemCells[i].Init(new ItemCellModel(itemID, false, config.AwardItemList[i][1])); itemCells[i].button.AddListener(() => { ItemTipUtility.Show(itemID); }); gotRects[i].SetActive(state == 2); } else { itemCells[i].SetActive(false); } } getBtn.SetActive(state == 0); gotoBtn.SetActive(state == 1); gotRect.SetActive(state == 2); mask.SetActive(state == 2); getBtn.AddListener(() => { AchievementManager.Instance.SendGetAward(id); }); } } Main/System/DayMission/MissionHeroRoadCell.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: e5424536ae280184192560cd8373d771 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/System/DayMission/MissionHeroRoadWin.cs
New file @@ -0,0 +1,66 @@ using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; //主线任务:英雄之路 public class MissionHeroRoadWin : UIBase { [SerializeField] ScrollerController scroller; List<int> ids = new List<int>(); protected override void OnPreOpen() { scroller.OnRefreshCell += OnRefreshCell; AchievementManager.Instance.OnAchievementUpdateEvent += OnAchievementUpdateEvent; CreateScroller(); } protected override void OnPreClose() { scroller.OnRefreshCell -= OnRefreshCell; AchievementManager.Instance.OnAchievementUpdateEvent -= OnAchievementUpdateEvent; } void OnAchievementUpdateEvent(int type) { if (type == 1 || type == -1) { ids = AchievementManager.Instance.GetAchievementIDs(1); scroller.m_Scorller.RefreshActiveCellViews(); } } void CreateScroller() { ids = AchievementManager.Instance.GetAchievementIDs(1); var count = ids.Count; scroller.Refresh(); for (int i = 0; i < count; i++) { scroller.AddCell(ScrollerDataType.Header, i); } scroller.Restart(); } void OnRefreshCell(ScrollerDataType type, CellView cell) { var _cell = cell as MissionHeroRoadCell; _cell.Display(ids[cell.index]); } } Main/System/DayMission/MissionHeroRoadWin.cs.meta
New file @@ -0,0 +1,11 @@ fileFormatVersion: 2 guid: 803a78750ea407f49b5ddf73889160d9 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: assetBundleName: assetBundleVariant: Main/System/Message/RichTableEvent.cs
@@ -224,19 +224,19 @@ // } } break; case "success": { var _id = 0; if (_dict.ContainsKey("id") && int.TryParse(_dict["id"], out _id)) { var _cfg = SuccessConfig.Get(_id); if (_cfg != null) { return _cfg.Describe; } } } break; // case "success": // { // var _id = 0; // if (_dict.ContainsKey("id") && int.TryParse(_dict["id"], out _id)) // { // var _cfg = SuccessConfig.Get(_id); // if (_cfg != null) // { // return _cfg.Describe; // } // } // } // break; case "treasureprivilege": { Main/System/Redpoint/RedpointCenter.cs
@@ -176,4 +176,14 @@ } } public Redpoint GetRedpoint(int _id) { Redpoint redpoint = null; if (this.redpoints.TryGetValue(_id, out redpoint)) { return redpoint; } return null; } }