9 文件已复制
2个文件已删除
2 文件已重命名
10个文件已添加
29个文件已修改
| | |
| | | |
| | | public const string BATTLE_END = "BATTLE_END";//战斗结束 |
| | | public const string RECORDPLAYER_END = "RECORDPLAYER_END"; //战斗小片段结束 |
| | | |
| | | public const string BATTLE_TIANZI_REFRESH_HP = "BATTLE_TIANZI_REFRESH_HP";//天子考验 刷新血量 |
| | | } |
| | |
| | | switch (errorCode) |
| | | { |
| | | case 1: |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_Level", config.LimitLV) |
| | | + Language.Get("FuncLimitOpen1")); |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_Level", config.LimitLV)); |
| | | break; |
| | | case 2: |
| | | //开服多少天 一般是组合 |
| | | if (config.LimitLV != 0) |
| | | { |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_OpenDay", config.OpenDay) |
| | | + Language.Get("FuncLimitOpen2") |
| | | + Language.Get("FuncLimit_Level", config.LimitLV) |
| | | + Language.Get("FuncLimitOpen1")); |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_OpenDay_LV", |
| | | config.LimitLV, TimeUtility.OpenDay + 1, config.OpenDay)); |
| | | |
| | | } |
| | | else if (config.LimitMissionID != 0) |
| | | { |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_OpenDay", config.OpenDay) |
| | | + Language.Get("FuncLimitOpen2") |
| | | + Language.Get("FuncLimit_Mission", TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID)) |
| | | + Language.Get("FuncLimitOpen1")); |
| | | { |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_OpenDay_Mission", |
| | | TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID), TimeUtility.OpenDay + 1, config.OpenDay)); |
| | | } |
| | | else if (config.LimiRealmLV != 0) |
| | | { |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_OpenDay_Realm", |
| | | RealmConfig.Get(config.LimiRealmLV).Name, TimeUtility.OpenDay + 1, config.OpenDay)); |
| | | } |
| | | else |
| | | { |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_OpenDay", config.OpenDay) |
| | | + Language.Get("FuncLimitOpen1")); |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_OpenDay", config.OpenDay)); |
| | | } |
| | | break; |
| | | case 3: |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_Realm", RealmConfig.Get(config.LimiRealmLV).Name) |
| | | + Language.Get("FuncLimitOpen1")); |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_Realm", RealmConfig.Get(config.LimiRealmLV).Name)); |
| | | break; |
| | | case 4: |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_Mission", TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID)) |
| | | + Language.Get("FuncLimitOpen1")); |
| | | SysNotifyMgr.Instance.ShowStringTip(Language.Get("FuncLimit_Mission", TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID))); |
| | | break; |
| | | } |
| | | } |
| | |
| | | switch (errorCode) |
| | | { |
| | | case 1: |
| | | return StringUtility.Contact( |
| | | Language.Get("FuncLimit_Level", config.LimitLV), |
| | | Language.Get("FuncLimitOpen1")); |
| | | return Language.Get("FuncLimit_Level", config.LimitLV); |
| | | case 2: |
| | | //开服多少天 一般是组合 |
| | | if (config.LimitLV != 0) |
| | | { |
| | | return StringUtility.Contact( |
| | | Language.Get("FuncLimit_OpenDay", config.OpenDay), |
| | | Language.Get("FuncLimitOpen2"), |
| | | Language.Get("FuncLimit_Level", config.LimitLV), |
| | | Language.Get("FuncLimitOpen1")); |
| | | return Language.Get("FuncLimit_OpenDay_LV", config.LimitLV, TimeUtility.OpenDay + 1, config.OpenDay); |
| | | |
| | | } |
| | | else if (config.LimitMissionID != 0) |
| | | { |
| | | return StringUtility.Contact( |
| | | Language.Get("FuncLimit_OpenDay", config.OpenDay), |
| | | Language.Get("FuncLimitOpen2"), |
| | | Language.Get("FuncLimit_Mission", |
| | | TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID)), |
| | | Language.Get("FuncLimitOpen1")); |
| | | return Language.Get("FuncLimit_OpenDay_Mission", TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID), TimeUtility.OpenDay + 1, config.OpenDay); |
| | | } |
| | | else if (config.LimiRealmLV != 0) |
| | | { |
| | | return Language.Get("FuncLimit_OpenDay_Realm", RealmConfig.Get(config.LimiRealmLV).Name, TimeUtility.OpenDay + 1, config.OpenDay); |
| | | } |
| | | else |
| | | { |
| | | return StringUtility.Contact( |
| | | Language.Get("FuncLimit_OpenDay", config.OpenDay), |
| | | Language.Get("FuncLimitOpen1")); |
| | | return Language.Get("FuncLimit_OpenDay", config.OpenDay); |
| | | } |
| | | case 3: |
| | | return StringUtility.Contact( |
| | | Language.Get("FuncLimit_Realm", RealmConfig.Get(config.LimiRealmLV).Name), |
| | | Language.Get("FuncLimitOpen1")); |
| | | return Language.Get("FuncLimit_Realm", RealmConfig.Get(config.LimiRealmLV).Name); |
| | | case 4: |
| | | return StringUtility.Contact( |
| | | Language.Get("FuncLimit_Mission", TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID)), |
| | | Language.Get("FuncLimitOpen1")); |
| | | return Language.Get("FuncLimit_Mission", TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID)); |
| | | } |
| | | } |
| | | return string.Empty; |
| | |
| | | typeof(TreasureSetConfig),
|
| | | typeof(TreeLVConfig),
|
| | | typeof(WindowSearchConfig),
|
| | | typeof(XBGetItemConfig)
|
| | | typeof(XBGetItemConfig),
|
| | | typeof(ZhanlingConfig)
|
| | | };
|
| | |
|
| | | #if UNITY_EDITOR
|
| | |
| | | ClearConfigDictionary<WindowSearchConfig>();
|
| | | // 清空 XBGetItemConfig 字典
|
| | | ClearConfigDictionary<XBGetItemConfig>();
|
| | | // 清空 ZhanlingConfig 字典
|
| | | ClearConfigDictionary<ZhanlingConfig>();
|
| | | }
|
| | |
|
| | | #if UNITY_EDITOR
|
| New file |
| | |
| | | //--------------------------------------------------------
|
| | | // [Author]: YYL
|
| | | // [ Date ]: Tuesday, November 4, 2025
|
| | | //--------------------------------------------------------
|
| | |
|
| | | using System.Collections.Generic;
|
| | | using System;
|
| | | using UnityEngine;
|
| | | using LitJson;
|
| | |
|
| | | public partial class ZhanlingConfig : ConfigBase<int, ZhanlingConfig>
|
| | | {
|
| | | static ZhanlingConfig()
|
| | | {
|
| | | // 访问过静态构造函数
|
| | | visit = true; |
| | | }
|
| | |
|
| | | public int ZhanlingId;
|
| | | public int ZhanlingType;
|
| | | public int NeedValue;
|
| | | public int RewardIndex;
|
| | | public int[][] FreeRewardItemList;
|
| | | public int[][] ZLRewardItemList;
|
| | | public int[][] ZLRewardItemListH;
|
| | |
|
| | | public override int LoadKey(string _key)
|
| | | {
|
| | | int key = GetKey(_key);
|
| | | return key;
|
| | | }
|
| | |
|
| | | public override void LoadConfig(string input)
|
| | | {
|
| | | try {
|
| | | string[] tables = input.Split('\t');
|
| | | int.TryParse(tables[0],out ZhanlingId); |
| | |
|
| | | int.TryParse(tables[1],out ZhanlingType); |
| | |
|
| | | int.TryParse(tables[2],out NeedValue); |
| | |
|
| | | int.TryParse(tables[3],out RewardIndex); |
| | |
|
| | | FreeRewardItemList = JsonMapper.ToObject<int[][]>(tables[4].Replace("(", "[").Replace(")", "]")); |
| | |
|
| | | ZLRewardItemList = JsonMapper.ToObject<int[][]>(tables[5].Replace("(", "[").Replace(")", "]")); |
| | |
|
| | | ZLRewardItemListH = JsonMapper.ToObject<int[][]>(tables[6].Replace("(", "[").Replace(")", "]")); |
| | | }
|
| | | catch (Exception exception)
|
| | | {
|
| | | Debug.LogError(exception);
|
| | | }
|
| | | }
|
| | | }
|
copy from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta
copy to Main/Config/Configs/ZhanlingConfig.cs.meta
| File was copied from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta |
| | |
| | | fileFormatVersion: 2 |
| | | guid: a6484a8278af59643850fd9225f7338d |
| | | guid: 0a982bd9a3eaef84fa25269ec4301050 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| New file |
| | |
| | | using System.Collections.Generic; |
| | | public partial class ZhanlingConfig : ConfigBase<int, ZhanlingConfig> |
| | | { |
| | | //战令类型: 所需值 :ZhanlingId |
| | | static Dictionary<int, Dictionary<int, int>> typeToIDDict = new Dictionary<int, Dictionary<int, int>>(); |
| | | |
| | | protected override void OnConfigParseCompleted() |
| | | { |
| | | if (!typeToIDDict.ContainsKey(ZhanlingType)) |
| | | { |
| | | typeToIDDict[ZhanlingType] = new Dictionary<int, int>(); |
| | | } |
| | | typeToIDDict[ZhanlingType][NeedValue] = ZhanlingId; |
| | | } |
| | | |
| | | public static Dictionary<int, int> GetTypeToIDDict(int zhanLingType) |
| | | { |
| | | return typeToIDDict[zhanLingType]; |
| | | } |
| | | |
| | | public static Dictionary<int, Dictionary<int, int>> GetAllTypeToIDListDict() |
| | | { |
| | | return typeToIDDict; |
| | | } |
| | | } |
| File was renamed from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta |
| | |
| | | fileFormatVersion: 2 |
| | | guid: a6484a8278af59643850fd9225f7338d |
| | | guid: 8aa62178ddc66b2479b841083ee2b290 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | |
| | | using UnityEngine; |
| | | using System.Collections; |
| | | using System.Collections.Generic; |
| | | |
| | | //04 18 周围对象刷新#tagObjInfoRefresh |
| | | |
| | | public class DTC0418_tagObjInfoRefresh : DtcBasic { |
| | | static ulong lastPackUID = 0; |
| | | //类型 |
| | | static Dictionary<int, ulong> lastPackUIDDict = new Dictionary<int, ulong>() |
| | | { |
| | | {(int)PlayerDataType.ExAttr1, 0}, |
| | | {(int)PlayerDataType.ExAttr2, 0}, |
| | | {(int)PlayerDataType.default26, 0}, |
| | | }; |
| | | public override void Done(GameNetPackBasic vNetPack) |
| | | { |
| | | base.Done(vNetPack); |
| | |
| | | switch (vNetData.ObjType) |
| | | { |
| | | case 1: |
| | | if (vNetData.packUID > DTC0102_tagCDBPlayer.loginPackUID && vNetData.packUID > lastPackUID) |
| | | if (vNetData.packUID > DTC0102_tagCDBPlayer.loginPackUID) |
| | | { |
| | | lastPackUID = vNetData.packUID; |
| | | if (lastPackUIDDict.ContainsKey(vNetData.RefreshType)) |
| | | { |
| | | if (vNetData.packUID < lastPackUIDDict[vNetData.RefreshType]) |
| | | { |
| | | return; |
| | | } |
| | | lastPackUIDDict[vNetData.RefreshType] = vNetData.packUID; |
| | | } |
| | | //防范断线重连时,战斗中的旧包影响数据 |
| | | Update0418(vNetData); |
| | | } |
| New file |
| | |
| | | using UnityEngine;
|
| | | using System.Collections;
|
| | |
|
| | | // A1 03 同步开服天数 #tagMCOpenServerDay
|
| | |
|
| | | public class DTCA103_tagMCOpenServerDay : DtcBasic {
|
| | | public override void Done(GameNetPackBasic vNetPack) {
|
| | | base.Done(vNetPack);
|
| | | HA103_tagMCOpenServerDay vNetData = vNetPack as HA103_tagMCOpenServerDay;
|
| | | TimeUtility.OnRefreshServerOpenDay(vNetData);
|
| | | }
|
| | | }
|
copy from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta
copy to Main/Core/NetworkPackage/DTCFile/ServerPack/HA1_Sys/DTCA103_tagMCOpenServerDay.cs.meta
| File was copied from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta |
| | |
| | | fileFormatVersion: 2 |
| | | guid: a6484a8278af59643850fd9225f7338d |
| | | guid: 639049f3084500b42bd546a764c4ef94 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | |
| | | using UnityEngine; |
| | | using System.Collections; |
| | | |
| | | using UnityEngine;
|
| | | using System.Collections;
|
| | |
|
| | | // B1 20 战令信息 #tagMCZhanlingInfo
|
| | |
|
| | | public class DTCB120_tagMCZhanlingInfo : DtcBasic {
|
| | | public override void Done(GameNetPackBasic vNetPack) {
|
| | | base.Done(vNetPack);
|
| | | HB120_tagMCZhanlingInfo vNetData = vNetPack as HB120_tagMCZhanlingInfo;
|
| | | BattlePassManager.Instance.UpdateBattlePassInfo(vNetData);
|
| | | }
|
| | | }
|
| New file |
| | |
| | | using UnityEngine; |
| | | using System.Collections; |
| | | |
| | | // B4 19 对象最新生命刷新 #tagSCObjHPRefresh |
| | | |
| | | public class DTCB419_tagSCObjHPRefresh : DtcBasic { |
| | | public override void Done(GameNetPackBasic vNetPack) { |
| | | base.Done(vNetPack); |
| | | HB419_tagSCObjHPRefresh vNetData = vNetPack as HB419_tagSCObjHPRefresh; |
| | | |
| | | BattleField battleField = BattleManager.Instance.GetBattleField(vNetData.packUID); |
| | | if (null != battleField) |
| | | { |
| | | battleField.OnRefreshObjHP(vNetData); |
| | | battleField.DistributeNextPackage(); |
| | | } |
| | | } |
| | | } |
copy from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta
copy to Main/Core/NetworkPackage/DTCFile/ServerPack/HB4_FightDefine/DTCB419_tagSCObjHPRefresh.cs.meta
| File was copied from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta |
| | |
| | | fileFormatVersion: 2 |
| | | guid: a6484a8278af59643850fd9225f7338d |
| | | guid: 3d2361817f6a81a4ea0d05eaf7b8f59e |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | |
| | | // 登记相应的数据体及对应的数据转逻辑类(去重后) |
| | | Register(typeof(H0102_tagCDBPlayer), typeof(DTC0102_tagCDBPlayer)); |
| | | Register(typeof(HA004_tagServerDateTime), typeof(DTCA004_tagServerDateTime)); |
| | | Register(typeof(HA005_tagOpenServerDay), typeof(DTCA005_tagOpenServerDay)); |
| | | Register(typeof(HA103_tagMCOpenServerDay), typeof(DTCA103_tagMCOpenServerDay)); |
| | | Register(typeof(H0403_tagPlayerLoginLoadOK), typeof(DTC0403_tagPlayerLoginLoadOK)); |
| | | Register(typeof(H0101_tagServerPrepared), typeof(DTC0101_tagServerPrepared)); |
| | | Register(typeof(H0104_tagServerDisconnect), typeof(DTC0104_tagServerDisconnect)); |
| | |
| | | Register(typeof(HA921_tagUpdatePlayerNameResult), typeof(DTCA921_tagUpdatePlayerNameResult)); |
| | | Register(typeof(H3202_tagServerResponse), typeof(DTC3202_tagServerResponse)); |
| | | Register(typeof(HA130_tagMCViewBillboardRet), typeof(DTCA130_tagMCViewBillboardRet)); |
| | | Register(typeof(HB419_tagSCObjHPRefresh), typeof(DTCB419_tagSCObjHPRefresh)); |
| | | Register(typeof(HB420_tagMCTurnFightState), typeof(DTCB420_tagMCTurnFightState)); |
| | | Register(typeof(HB421_tagMCTurnFightObjAction), typeof(DTCB421_tagMCTurnFightObjAction)); |
| | | Register(typeof(HB422_tagMCTurnFightObjDead), typeof(DTCB422_tagMCTurnFightObjDead)); |
| File was renamed from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs |
| | |
| | | using UnityEngine; |
| | | using System.Collections; |
| | | |
| | | //A0 05 同步开服天数 #tagOpenServerDay
|
| | | // A1 03 同步开服天数 #tagMCOpenServerDay
|
| | |
|
| | | public class HA005_tagOpenServerDay : GameNetPackBasic {
|
| | | public class HA103_tagMCOpenServerDay : GameNetPackBasic {
|
| | | public ushort Day; // 已开服天数,从0开始
|
| | | public byte IsMixServer; //是否是合服服务器
|
| | | public ushort MixDay; // 已合服天数,从0开始
|
| | |
| | | public uint NowMicSecond;
|
| | | public byte WeekOfYear; //一年中的第几周
|
| | |
|
| | | public HA005_tagOpenServerDay () {
|
| | | _cmd = (ushort)0xA005;
|
| | | public HA103_tagMCOpenServerDay () {
|
| | | _cmd = (ushort)0xA103;
|
| | | }
|
| | |
|
| | | public override void ReadFromBytes (byte[] vBytes) {
|
copy from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta
copy to Main/Core/NetworkPackage/ServerPack/HA1_Sys/HA103_tagMCOpenServerDay.cs.meta
| File was copied from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta |
| | |
| | | fileFormatVersion: 2 |
| | | guid: a6484a8278af59643850fd9225f7338d |
| | | guid: e092a0db076d7f04f8113dd4269bd9e0 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| New file |
| | |
| | | using UnityEngine; |
| | | using System.Collections; |
| | | |
| | | // B4 19 对象最新生命刷新 #tagSCObjHPRefresh |
| | | |
| | | public class HB419_tagSCObjHPRefresh : GameNetPackBasic { |
| | | public uint ObjID; |
| | | public uint HP; // 当前血量,求余20亿部分 |
| | | public uint HPEx; // 当前血量,整除20亿部分 |
| | | public uint MaxHP; // 最大血量,求余20亿部分 |
| | | public uint MaxHPEx; // 最大血量,整除20亿部分 |
| | | |
| | | public HB419_tagSCObjHPRefresh () { |
| | | _cmd = (ushort)0xB419; |
| | | } |
| | | |
| | | public override void ReadFromBytes (byte[] vBytes) { |
| | | TransBytes (out ObjID, vBytes, NetDataType.DWORD); |
| | | TransBytes (out HP, vBytes, NetDataType.DWORD); |
| | | TransBytes (out HPEx, vBytes, NetDataType.DWORD); |
| | | TransBytes (out MaxHP, vBytes, NetDataType.DWORD); |
| | | TransBytes (out MaxHPEx, vBytes, NetDataType.DWORD); |
| | | } |
| | | |
| | | } |
copy from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta
copy to Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB419_tagSCObjHPRefresh.cs.meta
| File was copied from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta |
| | |
| | | fileFormatVersion: 2 |
| | | guid: a6484a8278af59643850fd9225f7338d |
| | | guid: 4d172d7090e7f3b42958b6ce5bf20dc3 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | |
| | | managers.Add(BoneFieldManager.Instance);
|
| | | managers.Add(ArenaManager.Instance);
|
| | | managers.Add(DayMissionManager.Instance);
|
| | | managers.Add(BattlePassManager.Instance);
|
| | |
|
| | | foreach (var manager in managers)
|
| | | {
|
| | |
| | | [SerializeField] protected Button btnSpeed; // 速度控制 |
| | | [SerializeField] protected Text textSpeed; // 速度显示 |
| | | [SerializeField] protected Button btnPass; // 跳过战斗 |
| | | [SerializeField] protected Button btnPause; // 暂停按钮 (BattleWin中的btnStop可对应此按钮) |
| | | |
| | | [Header("战斗UI组件")] |
| | | [SerializeField] protected TotalDamageDisplayer totalDamageDisplayer; // 伤害统计 |
| | |
| | | |
| | | if (btnPass != null) |
| | | btnPass.AddListener(OnClickPass); |
| | | |
| | | if (btnPause != null) |
| | | btnPause.AddListener(OnClickPause); |
| | | } |
| | | |
| | | protected override void OnPreOpen() |
| | |
| | | |
| | | |
| | | /// <summary> |
| | | /// 暂停/继续 |
| | | /// </summary> |
| | | protected virtual void OnClickPause() |
| | | { |
| | | if (null == battleField) |
| | | return; |
| | | battleField.IsPause = !battleField.IsPause; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 跳过战斗 |
| | | /// </summary> |
| | | protected virtual void OnClickPass() |
| | |
| | | { |
| | | if (txtBattleRound != null) |
| | | { |
| | | txtBattleRound.text = string.Format("{0}/{1}", round, maxRound); |
| | | txtBattleRound.text = Language.Get("RoundText", round, maxRound); |
| | | } |
| | | } |
| | | |
| | |
| | | { |
| | | return null; |
| | | } |
| | | |
| | | public void OnRefreshObjHP(HB419_tagSCObjHPRefresh vNetData) |
| | | { |
| | | BattleObject battleObj = battleObjMgr.GetBattleObject((int)vNetData.ObjID); |
| | | if (null != battleObj) |
| | | { |
| | | // battleObj.teamHero.curHp = GeneralDefine.GetFactValue(vNetData.HP, vNetData.HPEx); |
| | | // battleObj.teamHero.maxHp = GeneralDefine.GetFactValue(vNetData.MaxHP, vNetData.MaxHPEx); |
| | | EventBroadcast.Instance.Broadcast<HB419_tagSCObjHPRefresh>( |
| | | EventName.BATTLE_TIANZI_REFRESH_HP, vNetData); |
| | | |
| | | //battleObj.teamHero.curHp, battleObj.teamHero.maxHp |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| | |
| | | BattleObject deadObj = battleField.battleObjMgr.GetBattleObject((int)deadPack.ObjID); |
| | | if (null != deadObj) |
| | | { |
| | | PerformDrop(deadObj); |
| | | deadObj.OnDeath(() => |
| | | { |
| | | index++; |
| | | |
| | | isLastOne = index >= total; |
| | | |
| | | OnDeathAnimationEnd(deadObj); |
| | | |
| | | if (isLastOne) |
| | | { |
| | |
| | | BattleObject deadObj = battleField.battleObjMgr.GetBattleObject((int)deadPack.ObjID); |
| | | if (null != deadObj) |
| | | { |
| | | OnDeathAnimationEnd(deadObj); |
| | | PerformDrop(deadObj); |
| | | } |
| | | } |
| | | |
| | | base.ForceFinish(); |
| | | } |
| | | |
| | | private void OnDeathAnimationEnd(BattleObject deadObj) |
| | | private void PerformDrop(BattleObject deadObj) |
| | | { |
| | | // 只有主线掉落物品 |
| | | if (battleField.MapID == 1 || battleField.MapID == 2) |
| | |
| | | return true; |
| | | } |
| | | |
| | | public virtual void Hurt(List<long> damageValues, long _totalDamage, |
| | | HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, SkillConfig skillConfig, int hitIndex, |
| | | BattleDrops battleDrops, HB422_tagMCTurnFightObjDead deadPack) |
| | | public virtual void Hurt(BattleHurtParam battleHurtParam) |
| | | { |
| | | bool isLastHit = hitIndex >= skillConfig.DamageDivide.Length - 1; |
| | | bool firstHit = hitIndex == 0; |
| | | BattleDmgInfo dmgInfo = PopDamage(damageValues, _totalDamage, hurt, skillConfig, isLastHit); |
| | | bool isLastHit = battleHurtParam.hitIndex >= battleHurtParam.skillConfig.DamageDivide.Length - 1; |
| | | bool firstHit = battleHurtParam.hitIndex == 0; |
| | | BattleDmgInfo dmgInfo = PopDamage(battleHurtParam); |
| | | |
| | | |
| | | // 这里 |
| | |
| | | |
| | | |
| | | |
| | | bool isFatalAttack = (null != deadPack) && isLastHit; |
| | | bool isFatalAttack = (null != battleHurtParam.deadPack) && isLastHit; |
| | | |
| | | if (isFatalAttack) |
| | | { |
| | |
| | | { |
| | | PushDropItems(battleDrops); |
| | | } |
| | | battleField.OnObjsDead(new List<HB422_tagMCTurnFightObjDead>() { deadPack }); |
| | | battleField.OnObjsDead(new List<HB422_tagMCTurnFightObjDead>() { battleHurtParam.deadPack }); |
| | | |
| | | } |
| | | else |
| | |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | public void SuckHp(uint suckHP, SkillConfig skillConfig) |
| | | { |
| | | teamHero.curHp = Math.Min(teamHero.maxHp, teamHero.curHp + (int)suckHP); |
| | | // teamHero.curHp = Math.Min(teamHero.maxHp, teamHero.curHp + (int)suckHP); |
| | | } |
| | | |
| | | public void HurtByReflect(uint bounceHP, SkillConfig skillConfig) |
| | | { |
| | | teamHero.curHp = Math.Max(0, teamHero.curHp - (int)bounceHP); |
| | | // teamHero.curHp = Math.Max(0, teamHero.curHp - (int)bounceHP); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | // 伤害还要看 是否闪避 暴击 and so on 需要有一个DamageType 服务器应该会给 |
| | | protected virtual BattleDmgInfo PopDamage(List<long> damageValues, long _totalDamage, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, SkillConfig skillConfig, bool isLastHit) |
| | | protected virtual BattleDmgInfo PopDamage(BattleHurtParam battleHurtParam) |
| | | { |
| | | BattleDmgInfo battleDmgInfo = new BattleDmgInfo(battleField.guid, damageValues, this, hurt, skillConfig, isLastHit); |
| | | BattleDmgInfo battleDmgInfo = new BattleDmgInfo(battleField.guid, battleHurtParam); |
| | | |
| | | int currentHurtHp = 0; |
| | | for (int i = 0; i < damageValues.Count; i++) |
| | | { |
| | | currentHurtHp += (int)damageValues[i]; |
| | | } |
| | | |
| | | bool isRecovery = battleDmgInfo.IsType(DamageType.Recovery); |
| | | |
| | | long toHp = Math.Max(0, teamHero.curHp + (isRecovery ? currentHurtHp : -currentHurtHp)); |
| | | |
| | | heroInfoBar.UpdateHP(teamHero.curHp, toHp, teamHero.maxHp); |
| | | teamHero.curHp = toHp; |
| | | // 使用传入的 fromHp 和 toHp 更新血条显示 |
| | | heroInfoBar.UpdateHP(battleHurtParam.fromHp, battleHurtParam.toHp, teamHero.maxHp); |
| | | |
| | | // YYL TODO 是否需要挂在在自身的follow点上 |
| | | EventBroadcast.Instance.Broadcast(EventName.BATTLE_DAMAGE_TAKEN, battleDmgInfo); |
| | |
| | | break; |
| | | case 1: |
| | | // 1 对位: |
| | | // 默认只选1个,对位规则为A1优先打B1,A2优先打B2,A3优先打B3,对位目标死亡时,优先前排,比如B2已经死亡,那么A2将优先打B1,前排1、2、3号位置全部死亡之后才开始选择后排4、5、6号位置,对位只可选1个目标,即主目标 |
| | | // 默认只选1个,对位规则为A1优先打B1,A2优先打B2,A3优先打B3,对位目标死亡时,优先前排,比如B2已经死亡,那么A2将优先打B |
| | | if (targetList.Count > 0) |
| | | { |
| | | BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)targetList[0].ObjID); |
| | |
| | | |
| | | public static int GetDamageNumKey(DamageNumConfig config, int _num) |
| | | { |
| | | if (_num == 46) return config.nums[10]; // '.' |
| | | if (_num == 46) return config.nums[10]; // '.' |
| | | else if (_num == 107) return config.nums[11]; // 'k' |
| | | else if (_num == 109) return config.nums[12]; // 'm' |
| | | else if (_num == 98) return config.nums[13]; // 'b' |
| | | else if (_num == 98) return config.nums[13]; // 'b' |
| | | else if (_num == 116) return config.nums[14]; // 't' |
| | | int targetNum = _num - 48; |
| | | if (targetNum >= config.nums.Length || targetNum < 0) |
| | | { |
| | | Debug.LogError("damage config " + config.TypeID + " _num is " + _num + " out of range"); |
| | | Debug.LogError("damage config " + config.TypeID + " _num is " + _num + " out of range"); |
| | | return _num; |
| | | } |
| | | return config.nums[_num - 48]; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 将整个技能的总伤害按命中次数和分段配置分配 |
| | | /// </summary> |
| | | /// <param name="damageDivideList">整个技能的所有命中分段配置</param> |
| | | /// <param name="hitIndex">当前是第几击(从0开始)</param> |
| | | /// <param name="totalDamage">整个技能的总伤害</param> |
| | | /// <returns>这一击内每一段的伤害值列表</returns> |
| | | public static List<long> DivideDamageToList(int[][] damageDivideList, int hitIndex, long totalDamage) |
| | | { |
| | | if (totalDamage <= 0) |
| | | { |
| | | return new List<long>{}; |
| | | } |
| | | |
| | | if (damageDivideList == null || damageDivideList.Length == 0) |
| | | { |
| | | Debug.LogError("damageDivideList 为空或长度为0"); |
| | | return new List<long> { totalDamage }; |
| | | } |
| | | |
| | | if (hitIndex < 0 || hitIndex >= damageDivideList.Length) |
| | | { |
| | | Debug.LogError($"hitIndex={hitIndex} 超出范围, damageDivideList.Length={damageDivideList.Length}"); |
| | | return new List<long> { totalDamage }; |
| | | } |
| | | |
| | | int[] currentHitDivide = damageDivideList[hitIndex]; |
| | | if (currentHitDivide == null || currentHitDivide.Length == 0) |
| | | { |
| | | Debug.LogError($"damageDivide[{hitIndex}] 为空或长度为0"); |
| | | return new List<long> { totalDamage }; |
| | | } |
| | | |
| | | // ============ 第一步: 计算每一击应该造成的伤害 ============ |
| | | // 先计算所有击的总权重 |
| | | int totalWeight = 0; |
| | | for (int i = 0; i < damageDivideList.Length; i++) |
| | | { |
| | | if (damageDivideList[i] != null && damageDivideList[i].Length > 0) |
| | | { |
| | | // 每一击的权重是其所有分段之和 |
| | | for (int j = 0; j < damageDivideList[i].Length; j++) |
| | | { |
| | | totalWeight += damageDivideList[i][j]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (totalWeight == 0) |
| | | { |
| | | Debug.LogError("totalWeight 为 0"); |
| | | return new List<long> { totalDamage }; |
| | | } |
| | | |
| | | // 计算当前这一击的权重 |
| | | int currentHitWeight = 0; |
| | | for (int i = 0; i < currentHitDivide.Length; i++) |
| | | { |
| | | currentHitWeight += currentHitDivide[i]; |
| | | } |
| | | |
| | | // 计算当前这一击应该造成的总伤害 |
| | | long currentHitTotalDamage; |
| | | bool isLastHit = hitIndex >= damageDivideList.Length - 1; |
| | | |
| | | if (isLastHit) |
| | | { |
| | | // 最后一击: 计算前面所有击已经造成的伤害,剩余的全部给最后一击 |
| | | long previousHitsDamage = 0; |
| | | for (int i = 0; i < hitIndex; i++) |
| | | { |
| | | if (damageDivideList[i] != null) |
| | | { |
| | | int hitWeight = 0; |
| | | for (int j = 0; j < damageDivideList[i].Length; j++) |
| | | { |
| | | hitWeight += damageDivideList[i][j]; |
| | | } |
| | | previousHitsDamage += (long)((float)totalDamage * (float)hitWeight / (float)totalWeight); |
| | | } |
| | | } |
| | | currentHitTotalDamage = totalDamage - previousHitsDamage; |
| | | } |
| | | else |
| | | { |
| | | // 非最后一击: 按权重计算 |
| | | currentHitTotalDamage = (long)((float)totalDamage * (float)currentHitWeight / (float)totalWeight); |
| | | } |
| | | |
| | | // ============ 第二步: 将当前这一击的伤害分配到各分段 ============ |
| | | List<long> fixedDamageList = new List<long>(); |
| | | long accumulatedDamage = 0; |
| | | |
| | | for (int i = 0; i < currentHitDivide.Length; i++) |
| | | { |
| | | long damage; |
| | | |
| | | // 当前击的最后一段进行误差补偿 |
| | | if (i == currentHitDivide.Length - 1) |
| | | { |
| | | damage = currentHitTotalDamage - accumulatedDamage; |
| | | } |
| | | else |
| | | { |
| | | // 按当前击的权重分配 |
| | | damage = (long)((float)currentHitTotalDamage * (float)currentHitDivide[i] / (float)currentHitWeight); |
| | | accumulatedDamage += damage; |
| | | } |
| | | |
| | | fixedDamageList.Add(damage); |
| | | } |
| | | |
| | | return fixedDamageList; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// </summary> |
| | | public static List<long> DivideDamageToList(int[] damageDivide, long totalDamage) |
| | | { |
| | | if (damageDivide == null || damageDivide.Length == 0) |
| | | { |
| | | Debug.LogError("damageDivide 为空或长度为0"); |
| | | return new List<long> { totalDamage }; |
| | | } |
| | | |
| | | List<long> fixedDamageList = new List<long>(); |
| | | long accumulatedDamage = 0; // 累计已分配的伤害 |
| | | |
| | | for (int i = 0; i < damageDivide.Length; i++) |
| | | { |
| | | float fixedDamage = (float)totalDamage * (float)damageDivide[i] / 10000f; |
| | | fixedDamageList.Add((int)fixedDamage); |
| | | long damage; |
| | | |
| | | // 最后一次分配:用总伤害减去已分配的伤害,确保总和精确 |
| | | if (i == damageDivide.Length - 1) |
| | | { |
| | | damage = totalDamage - accumulatedDamage; |
| | | } |
| | | else |
| | | { |
| | | // 计算当前分段伤害(向下取整) |
| | | damage = (long)((float)totalDamage * (float)damageDivide[i] / 10000f); |
| | | accumulatedDamage += damage; |
| | | } |
| | | |
| | | fixedDamageList.Add(damage); |
| | | } |
| | | |
| | | |
| | | return fixedDamageList; |
| | | } |
| | | |
| | | public static HB419_tagSCObjHPRefresh FindObjHPRefreshPack(List<GameNetPackBasic> packList) |
| | | { |
| | | for (int i = 0; i < packList.Count; i++) |
| | | { |
| | | var pack = packList[i]; |
| | | if (pack is HB419_tagSCObjHPRefresh hpRefreshPack) |
| | | { |
| | | return hpRefreshPack; |
| | | } |
| | | else if (pack is CustomHB426CombinePack) |
| | | { |
| | | break; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public static List<HB422_tagMCTurnFightObjDead> FindDeadPack(List<GameNetPackBasic> packList) |
| | | { |
| | |
| | | { |
| | | |
| | | public string battleFieldGuid { get; private set; } |
| | | public List<long> damageList { get; private set; } |
| | | public BattleObject hurtObj { get; private set; } |
| | | |
| | | public HB427_tagSCUseSkill.tagSCUseSkillHurt hurt { get; private set; } |
| | | public BattleHurtParam battleHurtParam { get; private set; } |
| | | public List<long> damageList { get { return battleHurtParam.damageList; } } |
| | | public BattleObject hurtObj { get { return battleHurtParam.hurtObj; } } |
| | | |
| | | public SkillConfig skillConfig { get; private set; } |
| | | public HB427_tagSCUseSkill.tagSCUseSkillHurt hurt { get { return battleHurtParam.hurt; } } |
| | | |
| | | public SkillConfig skillConfig { get { return battleHurtParam.skillConfig; } } |
| | | |
| | | // 是否被格挡了 |
| | | public bool isBlocked = false; |
| | |
| | | |
| | | public List<BattleDmg> battleDamageList = new List<BattleDmg>(); |
| | | |
| | | public BattleDmgInfo(string battleFieldGuid, List<long> damageList, BattleObject hurtObj, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, SkillConfig skillConfig, bool isLastHit) |
| | | public BattleDmgInfo(string battleFieldGuid, BattleHurtParam battleHurtParam) |
| | | { |
| | | this.battleFieldGuid = battleFieldGuid; |
| | | this.damageList = damageList; |
| | | this.hurtObj = hurtObj; |
| | | this.hurt = hurt; |
| | | this.skillConfig = skillConfig; |
| | | this.isLastHit = isLastHit; |
| | | this.battleHurtParam = battleHurtParam; |
| | | this.isLastHit = battleHurtParam.hitIndex >= battleHurtParam.skillConfig.DamageDivide.Length - 1; |
| | | HandleDamageType(); |
| | | HandleAttackTypeAndDamage(); |
| | | } |
| | |
| | | int rawAttackType = (int)hurt.AttackTypes; |
| | | float blockRatio = GeneralDefine.blockRatio; // 格挡减伤率 |
| | | |
| | | // 处理每一段伤害及其对应的反伤和吸血 |
| | | for (int i = 0; i < damageList.Count; i++) |
| | | { |
| | | long actualDamage = damageList[i]; |
| | | |
| | | // ============ 1. 先处理当前段对应的反伤 ============ |
| | | if (battleHurtParam.reflectHpList != null && i < battleHurtParam.reflectHpList.Count) |
| | | { |
| | | long reflectHp = battleHurtParam.reflectHpList[i]; |
| | | if (reflectHp > 0) |
| | | { |
| | | battleDamageList.Add(new BattleDmg |
| | | { |
| | | damage = reflectHp, |
| | | attackType = (int)DamageType.Reflect |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // ============ 2. 然后处理当前段对应的吸血 ============ |
| | | if (battleHurtParam.suckHpList != null && i < battleHurtParam.suckHpList.Count) |
| | | { |
| | | long suckHp = battleHurtParam.suckHpList[i]; |
| | | if (suckHp > 0) |
| | | { |
| | | battleDamageList.Add(new BattleDmg |
| | | { |
| | | damage = suckHp, |
| | | attackType = (int)DamageType.SuckHP |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // ============ 3. 最后处理主要伤害 ============ |
| | | // 格挡处理 |
| | | if (isBlocked) |
| | | { |
| | |
| | | { |
| | | int showAttackType = (int)DamageType.Realdamage + (IsCrit() ? (int)DamageType.Crit : 0); |
| | | battleDamageList.Add(new BattleDmg { damage = actualDamage, attackType = showAttackType }); |
| | | continue; |
| | | } |
| | | |
| | | // 普通伤害/治疗处理 |
| | | if (DamageNumConfig.Get(attackType) == null) |
| | | else |
| | | { |
| | | UnityEngine.Debug.LogError($"服务器给的伤害类型不对,强制转换为普通伤害/治疗, attackType: {attackType}"); |
| | | if ((attackType & (int)DamageType.Damage) != 0) |
| | | attackType = (int)DamageType.Damage; |
| | | else if ((attackType & (int)DamageType.Recovery) != 0) |
| | | attackType = (int)DamageType.Recovery; |
| | | else |
| | | UnityEngine.Debug.LogError($"强制转换失败,该类型不是治疗也不是伤害 {attackType}"); |
| | | // 普通伤害/治疗处理 |
| | | if (DamageNumConfig.Get(attackType) == null) |
| | | { |
| | | UnityEngine.Debug.LogError($"服务器给的伤害类型不对,强制转换为普通伤害/治疗, attackType: {attackType}"); |
| | | if ((attackType & (int)DamageType.Damage) != 0) |
| | | attackType = (int)DamageType.Damage; |
| | | else if ((attackType & (int)DamageType.Recovery) != 0) |
| | | attackType = (int)DamageType.Recovery; |
| | | else |
| | | UnityEngine.Debug.LogError($"强制转换失败,该类型不是治疗也不是伤害 {attackType}"); |
| | | } |
| | | battleDamageList.Add(new BattleDmg { damage = actualDamage, attackType = attackType }); |
| | | } |
| | | battleDamageList.Add(new BattleDmg { damage = actualDamage, attackType = attackType }); |
| | | } |
| | | else |
| | | { |
| | |
| | | { |
| | | int showAttackType = (int)DamageType.Realdamage + (IsCrit() ? (int)DamageType.Crit : 0); |
| | | battleDamageList.Add(new BattleDmg { damage = actualDamage, attackType = showAttackType }); |
| | | continue; |
| | | } |
| | | |
| | | // 普通伤害/治疗处理 |
| | | if (DamageNumConfig.Get(attackType) == null) |
| | | else |
| | | { |
| | | UnityEngine.Debug.LogError($"服务器给的伤害类型不对,强制转换为普通伤害/治疗, attackType: {attackType}"); |
| | | if ((attackType & (int)DamageType.Damage) != 0) |
| | | attackType = (int)DamageType.Damage; |
| | | else if ((attackType & (int)DamageType.Recovery) != 0) |
| | | attackType = (int)DamageType.Recovery; |
| | | else |
| | | UnityEngine.Debug.LogError($"强制转换失败,该类型不是治疗也不是伤害 {attackType}"); |
| | | // 普通伤害/治疗处理 |
| | | if (DamageNumConfig.Get(attackType) == null) |
| | | { |
| | | UnityEngine.Debug.LogError($"服务器给的伤害类型不对,强制转换为普通伤害/治疗, attackType: {attackType}"); |
| | | if ((attackType & (int)DamageType.Damage) != 0) |
| | | attackType = (int)DamageType.Damage; |
| | | else if ((attackType & (int)DamageType.Recovery) != 0) |
| | | attackType = (int)DamageType.Recovery; |
| | | else |
| | | UnityEngine.Debug.LogError($"强制转换失败,该类型不是治疗也不是伤害 {attackType}"); |
| | | } |
| | | battleDamageList.Add(new BattleDmg { damage = actualDamage, attackType = attackType }); |
| | | } |
| | | battleDamageList.Add(new BattleDmg { damage = actualDamage, attackType = attackType }); |
| | | } |
| | | } |
| | | } |
| | |
| | | return skillConfig.HurtType / 10 == 1; |
| | | } |
| | | |
| | | } |
| | | |
| | | public class BattleHurtParam |
| | | { |
| | | public BattleObject casterObj; |
| | | public BattleObject hurtObj; |
| | | public List<long> damageList; |
| | | public List<long> suckHpList; |
| | | public List<long> reflectHpList; |
| | | |
| | | public long fromHp; |
| | | |
| | | public long toHp; |
| | | |
| | | public BattleDrops battleDrops; |
| | | |
| | | public HB427_tagSCUseSkill.tagSCUseSkillHurt hurt; |
| | | |
| | | public int hitIndex; |
| | | |
| | | public HB422_tagMCTurnFightObjDead deadPack; |
| | | |
| | | public SkillConfig skillConfig; |
| | | } |
| | |
| | | protected Spine.Skeleton skeleton; |
| | | protected float defaultMixDuration = 0f; |
| | | private Spine.TrackEntry currentTrack; |
| | | private Dictionary<int, Spine.TrackEntry> activeSkillTracks = new Dictionary<int, Spine.TrackEntry>(); // 改为字典:trackIndex -> TrackEntry |
| | | private Dictionary<int, Spine.TrackEntry> activeSkillTracks = new Dictionary<int, Spine.TrackEntry>(); |
| | | |
| | | // 子技能轨道池管理(在Init中初始化,不要在这里初始化) |
| | | private Queue<int> availableSubTracks; |
| | | private Dictionary<SkillBase, int> subSkillTrackMap = new Dictionary<SkillBase, int>(); |
| | | |
| | | private SkeletonIllusionShadow illusionShadow; |
| | | private bool playingSkillAnim = false; |
| | | |
| | |
| | | if (animState != null) |
| | | animState.Data.DefaultMix = defaultMixDuration; |
| | | |
| | | // 初始化子技能轨道池 |
| | | availableSubTracks = new Queue<int>(); |
| | | for (int i = 1; i <= 8; i++) |
| | | availableSubTracks.Enqueue(i); |
| | | |
| | | PlayAnimation(MotionName.idle, true); |
| | | SetupAnimationHandlers(); |
| | | |
| | |
| | | { |
| | | trackEntryCallbacks.Clear(); |
| | | activeSkillTracks.Clear(); |
| | | availableSubTracks?.Clear(); |
| | | subSkillTrackMap.Clear(); |
| | | if (animState != null) |
| | | { |
| | | animState.Complete -= OnAnimationComplete; |
| | |
| | | return null; |
| | | } |
| | | |
| | | // 子技能强制使用无动画模式,或者如果没有动画名称 |
| | | if (isSubSkill || string.IsNullOrEmpty(skillConfig.SkillMotionName)) |
| | | // 如果没有动画名称,使用无动画模式 |
| | | if (string.IsNullOrEmpty(skillConfig.SkillMotionName)) |
| | | { |
| | | PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill); |
| | | return null; |
| | |
| | | int frameCount = activeFrames.Length; |
| | | float recoveryFrame = skillConfig.RecoveryFrames; |
| | | |
| | | // 主技能用 track 0,子技能用 track 1 |
| | | int trackIndex = isSubSkill ? 1 : 0; |
| | | // 轨道分配策略:主技能用 track 0,子技能从轨道池分配 |
| | | int trackIndex = 0; |
| | | if (isSubSkill) |
| | | { |
| | | if (availableSubTracks != null && availableSubTracks.Count > 0) |
| | | { |
| | | trackIndex = availableSubTracks.Dequeue(); |
| | | subSkillTrackMap[skillBase] = trackIndex; |
| | | } |
| | | else |
| | | { |
| | | // 轨道池耗尽或未初始化,回退到无动画模式 |
| | | Debug.LogWarning($"子技能轨道池已满或未初始化,技能{skillConfig.SkillID}使用无动画模式"); |
| | | PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | Spine.TrackEntry skillTrack = null; |
| | | |
| | | if (hasAnim) |
| | | { |
| | | skillTrack = animState.SetAnimation(trackIndex, targetAnim, false); |
| | | if (null == skillTrack) |
| | | { |
| | | Debug.LogError($"技能 {skillConfig.SkillID} 动画设置失败"); |
| | | // 如果是子技能且分配了轨道,需要回收 |
| | | if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase)) |
| | | { |
| | | if (availableSubTracks != null) |
| | | availableSubTracks.Enqueue(subSkillTrackMap[skillBase]); |
| | | subSkillTrackMap.Remove(skillBase); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | // 只有主技能才更新 currentTrack |
| | | if (!isSubSkill) |
| | |
| | | { |
| | | if (activeSkillTracks[trackIndex] == skillTrack) |
| | | activeSkillTracks.Remove(trackIndex); |
| | | } |
| | | |
| | | // 回收子技能轨道 |
| | | if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase)) |
| | | { |
| | | if (availableSubTracks != null) |
| | | availableSubTracks.Enqueue(subSkillTrackMap[skillBase]); |
| | | subSkillTrackMap.Remove(skillBase); |
| | | } |
| | | |
| | | // 只有当没有其他活跃技能时才复位 playingSkillAnim |
| | |
| | | |
| | | // 清理并确保状态复位 |
| | | RemoveAction(frameHandler); |
| | | |
| | | // 回收子技能轨道 |
| | | if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase)) |
| | | { |
| | | if (availableSubTracks != null) |
| | | availableSubTracks.Enqueue(subSkillTrackMap[skillBase]); |
| | | subSkillTrackMap.Remove(skillBase); |
| | | } |
| | | |
| | | if (activeSkillTracks.Count == 0) |
| | | playingSkillAnim = false; |
| | | return; |
| | |
| | | RemoveAction(frameHandler); |
| | | if (activeSkillTracks.ContainsKey(trackIndex)) |
| | | activeSkillTracks.Remove(trackIndex); |
| | | |
| | | // 回收子技能轨道 |
| | | if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase)) |
| | | { |
| | | if (availableSubTracks != null) |
| | | availableSubTracks.Enqueue(subSkillTrackMap[skillBase]); |
| | | subSkillTrackMap.Remove(skillBase); |
| | | } |
| | | |
| | | if (activeSkillTracks.Count == 0) |
| | | playingSkillAnim = false; |
| | | return; |
| | |
| | | { |
| | | if (activeSkillTracks[trackIndex] == skillTrack) |
| | | activeSkillTracks.Remove(trackIndex); |
| | | } |
| | | |
| | | // 回收子技能轨道 |
| | | if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase)) |
| | | { |
| | | if (availableSubTracks != null) |
| | | availableSubTracks.Enqueue(subSkillTrackMap[skillBase]); |
| | | subSkillTrackMap.Remove(skillBase); |
| | | } |
| | | |
| | | // 只有当没有其他活跃技能时才复位 playingSkillAnim |
| | |
| | | trackEntryCallbacks.Clear(); |
| | | runningActions.Clear(); |
| | | activeSkillTracks.Clear(); |
| | | |
| | | // 重置子技能轨道池 |
| | | if (availableSubTracks == null) |
| | | availableSubTracks = new Queue<int>(); |
| | | else |
| | | availableSubTracks.Clear(); |
| | | |
| | | subSkillTrackMap.Clear(); |
| | | for (int i = 1; i <= 8; i++) |
| | | availableSubTracks.Enqueue(i); |
| | | |
| | | playingSkillAnim = false; |
| | | PlayAnimation(MotionName.idle, true); |
| | | } |
| | |
| | | public void OnSkillStart() |
| | | { |
| | | HandleDead(); |
| | | |
| | | skillEffect = SkillEffectFactory.CreateSkillEffect(caster, skillConfig, tagUseSkillAttack); |
| | | skillEffect.Play(OnHitTargets); |
| | | foreach (var subSkillPack in tagUseSkillAttack.subSkillList) |
| | |
| | | // 技能后摇结束回调:通知技能效果处理后摇结束 |
| | | public virtual void OnFinalFrameEnd() |
| | | { |
| | | |
| | | skillEffect?.OnFinalFrameEnd(); // 修复:添加空值检查 |
| | | } |
| | | |
| | |
| | | // 命中目标回调:处理所有被命中的目标 |
| | | protected virtual void OnHitTargets(int _hitIndex, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> hitList) |
| | | { |
| | | // 造成伤害前先处理血量刷新包 |
| | | HandleRefreshHP(); |
| | | |
| | | foreach (var hurt in hitList) |
| | | { |
| | | BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID); |
| | |
| | | } |
| | | } |
| | | |
| | | // 处理单个目标被命中:应用伤害和施法者效果 |
| | | // 处理单个目标被命中:应用伤害和施法者效果 |
| | | protected virtual void OnHitEachTarget(int _hitIndex, BattleObject target, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt) |
| | | { |
| | | // ============ 第一步:计算伤害分布 ============ |
| | | List<int> damageDivide = new List<int>(); |
| | | if (_hitIndex == 0 && skillConfig.DamageDivide.Length <= 0) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | // 伤害分布计算和应用 |
| | | // 计算总伤害和分段伤害列表 |
| | | long totalDamage = GeneralDefine.GetFactValue(hurt.HurtHP, hurt.HurtHPEx); |
| | | List<long> damageList = BattleUtility.DivideDamageToList(damageDivide.ToArray(), totalDamage); |
| | | List<long> damageList = BattleUtility.DivideDamageToList(skillConfig.DamageDivide, _hitIndex, totalDamage); |
| | | |
| | | // 获取临时数据并应用伤害 |
| | | // ============ 第二步:刷新实际血量 ============ |
| | | long fromHp = target.teamHero.curHp; |
| | | |
| | | |
| | | |
| | | // ============处理吸血跟反伤 =============== |
| | | // 也要按每一击平均算 最后要补齐伤害 |
| | | long suckHp = hurt.SuckHP; |
| | | long reflectHp = hurt.BounceHP; |
| | | |
| | | List<long> suckHpList = BattleUtility.DivideDamageToList(skillConfig.DamageDivide, _hitIndex, suckHp); |
| | | |
| | | List<long> reflectHpList = BattleUtility.DivideDamageToList(skillConfig.DamageDivide, _hitIndex, hurt.BounceHP); |
| | | // long currentSuckHp = suckHp / tagUseSkillAttack.HurtCount; |
| | | |
| | | // 计算当前这一击的实际伤害(所有分段伤害之和) |
| | | long currentHitDamage = 0; |
| | | foreach (long dmg in damageList) |
| | | { |
| | | currentHitDamage += dmg; |
| | | } |
| | | |
| | | long currentHitSuckHp = 0; |
| | | foreach (long suck in suckHpList) |
| | | { |
| | | currentHitSuckHp += suck; |
| | | } |
| | | |
| | | long currentHitReflectHp = 0; |
| | | foreach (long reflect in reflectHpList) |
| | | { |
| | | currentHitReflectHp += reflect; |
| | | } |
| | | |
| | | long toHp = Math.Max(0, fromHp - currentHitDamage + currentHitSuckHp - currentHitReflectHp); |
| | | |
| | | |
| | | // 更新目标血量 |
| | | target.teamHero.curHp = toHp; |
| | | |
| | | #if UNITY_EDITOR |
| | | BattleDebug.LogError( |
| | | (caster.Camp == BattleCamp.Red ? "【红方行动】" : "【蓝方行动】") + "\n" + |
| | | $"攻击者: {caster.teamHero.name}\n" + |
| | | $"目标: {target.teamHero.name}\n" + |
| | | $"技能: {skillConfig.SkillName} (第{_hitIndex}击)\n" + |
| | | $"伤害: {currentHitDamage} (总伤害: {totalDamage})\n" + |
| | | $"吸血: {currentHitSuckHp}\n" + |
| | | $"反伤: {currentHitReflectHp}\n" + |
| | | $"血量变化: {fromHp} -> {toHp}" |
| | | ); |
| | | #endif |
| | | |
| | | |
| | | bool isLastHit = _hitIndex >= skillConfig.DamageDivide.Length - 1; |
| | | |
| | | // ============ 第三步:获取临时数据(掉落、死亡等) ============ |
| | | int objID = (int)target.ObjID; |
| | | tempDropList.TryGetValue(objID, out BattleDrops battleDrops); |
| | | tempDeadPackList.TryGetValue(objID, out HB422_tagMCTurnFightObjDead deadPack); |
| | | target.Hurt(damageList, totalDamage, hurt, skillConfig, _hitIndex, battleDrops, deadPack); |
| | | |
| | | // 处理施法者相关效果 |
| | | caster.SuckHp(hurt.SuckHP, skillConfig); |
| | | caster.HurtByReflect(hurt.BounceHP, skillConfig); |
| | | |
| | | // 参数打包 |
| | | BattleHurtParam hurtParam = new BattleHurtParam() |
| | | { |
| | | casterObj = caster, |
| | | hurtObj = target, |
| | | damageList = damageList, |
| | | suckHpList = suckHpList, |
| | | reflectHpList = reflectHpList, |
| | | fromHp = fromHp, |
| | | toHp = toHp, |
| | | battleDrops = battleDrops, |
| | | hurt = hurt, |
| | | hitIndex = _hitIndex, |
| | | deadPack = deadPack, |
| | | skillConfig = skillConfig |
| | | }; |
| | | |
| | | // ============ 第四步:执行表现(飘字、动画等) ============ |
| | | target.Hurt(hurtParam); |
| | | |
| | | |
| | | } |
| | | |
| | | // 处理HP刷新包(简化逻辑) |
| | | private void HandleRefreshHP() |
| | | { |
| | | // 查找HP刷新包 |
| | | HB419_tagSCObjHPRefresh refreshPack = BattleUtility.FindObjHPRefreshPack(packList); |
| | | |
| | | if (refreshPack != null) |
| | | { |
| | | // 分发HP刷新包 |
| | | PackageRegedit.Distribute(refreshPack); |
| | | packList.Remove(refreshPack); |
| | | } |
| | | } |
| | | |
| | | // 处理死亡相关逻辑:分配掉落和经验 |
| | |
| | | long assignExp = avgExp + (i < remain ? 1 : 0); |
| | | var newPack = new HB405_tagMCAddExp |
| | | { |
| | | Exp = (uint)(assignExp % 100000000), |
| | | ExpPoint = (uint)(assignExp / 100000000), |
| | | Exp = (uint)(assignExp % Constants.ExpPointValue), |
| | | ExpPoint = (uint)(assignExp / Constants.ExpPointValue), |
| | | Source = expPack.Source |
| | | }; |
| | | expAssign[i].Add(newPack); |
| | |
| | | { |
| | | KillTween(ref hpTween); |
| | | |
| | | float fromValue = (float)fromHp / (float)maxHp; |
| | | float targetValue = (float)toHp / (float)maxHp; |
| | | |
| | | if (tween) |
| | | { |
| | | hpTween = sliderHp.DOValue(targetValue, 0.3f); |
| | | // 关键修复:先设置起始值,再播放动画到目标值 |
| | | sliderHp.value = fromValue; // ← 这行是关键! |
| | | hpTween = sliderHp.DOValue(targetValue, 0.3f).SetAutoKill(false); |
| | | battleObject.battleField.battleTweenMgr.OnPlayTween(hpTween); |
| | | } |
| | | else |
| | |
| | | { |
| | | KillTween(ref xpTween); |
| | | |
| | | float fromValue = (float)fromXp / (float)maxXp; |
| | | float targetValue = (float)toXp / (float)maxXp; |
| | | |
| | | if (tween) |
| | | { |
| | | xpTween = sliderXp.DOValue(targetValue, 0.2f); |
| | | // 同样的修复 |
| | | sliderXp.value = fromValue; // ← 这行是关键! |
| | | xpTween = sliderXp.DOValue(targetValue, 0.2f).SetAutoKill(false); |
| | | battleObject.battleField.battleTweenMgr.OnPlayTween(xpTween); |
| | | } |
| | | else |
| New file |
| | |
| | | fileFormatVersion: 2 |
| | | guid: 7f66ce03cd8564847bcbc69378d900d9 |
| | | folderAsset: yes |
| | | DefaultImporter: |
| | | externalObjects: {} |
| | | userData: |
| | | assetBundleName: |
| | | assetBundleVariant: |
| New file |
| | |
| | | using System.Collections; |
| | | using System.Collections.Generic; |
| | | using UnityEngine; |
| | | using System; |
| | | using System.Linq; |
| | | |
| | | //周战令 |
| | | public partial class BattlePassManager : GameSystemManager<BattlePassManager> |
| | | { |
| | | public const int WeekBattlePassType = 6; |
| | | |
| | | Redpoint redpoint = new Redpoint(MainRedDot.RedPoint_DailyKey, MainRedDot.RedPoint_WeekBPFuncKey); |
| | | void UpdateWeekRedPoint() |
| | | { |
| | | redpoint.state = RedPointState.None; |
| | | //购买,活跃 |
| | | battlePassDataDict.TryGetValue(WeekBattlePassType, out BattlePassData battlePassData); |
| | | if (battlePassData == null) return; |
| | | |
| | | |
| | | if (HasAnyAward(WeekBattlePassType, (int)battlePassData.value1)) |
| | | { |
| | | redpoint.state = RedPointState.Simple; |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | | |
copy from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta
copy to Main/System/BattlePass/BattlePassManager.Week.cs.meta
| File was copied from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta |
| | |
| | | fileFormatVersion: 2 |
| | | guid: a6484a8278af59643850fd9225f7338d |
| | | guid: ed678a9060fddbf41adb9d9102d62514 |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| New file |
| | |
| | | using System.Collections; |
| | | using System.Collections.Generic; |
| | | using UnityEngine; |
| | | using System; |
| | | using System.Linq; |
| | | |
| | | |
| | | public partial class BattlePassManager : GameSystemManager<BattlePassManager> |
| | | { |
| | | //战令类型:战令数据 |
| | | Dictionary<int, BattlePassData> battlePassDataDict = new Dictionary<int, BattlePassData>(); |
| | | public event Action<int> BattlePassDataUpdateEvent; |
| | | |
| | | Dictionary<int, int[]> buyZhanlingTypeDict = new Dictionary<int, int[]>(); |
| | | |
| | | public override void Init() |
| | | { |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitialize; |
| | | ParseConfig(); |
| | | } |
| | | |
| | | public override void Release() |
| | | { |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitialize; |
| | | } |
| | | |
| | | void OnBeforePlayerDataInitialize() |
| | | { |
| | | battlePassDataDict.Clear(); |
| | | } |
| | | |
| | | void ParseConfig() |
| | | { |
| | | var config = FuncConfigConfig.Get("Zhanling"); |
| | | buyZhanlingTypeDict = ConfigParse.ParseIntArrayDict(config.Numerical1); |
| | | } |
| | | |
| | | |
| | | public void UpdateBattlePassInfo(HB120_tagMCZhanlingInfo netPack) |
| | | { |
| | | if (!battlePassDataDict.ContainsKey(netPack.ZhanlingType)) |
| | | { |
| | | battlePassDataDict[netPack.ZhanlingType] = new BattlePassData(); |
| | | } |
| | | |
| | | BattlePassData battlePassData = battlePassDataDict[netPack.ZhanlingType]; |
| | | battlePassData.isActivite = netPack.IsActivite; |
| | | battlePassData.isActiviteH = netPack.IsActiviteH; |
| | | battlePassData.allFinishTime = netPack.AllFinishTime; |
| | | battlePassData.value1 = netPack.Value1; |
| | | |
| | | for (int i = 0; i < netPack.RewardCount; i++) |
| | | { |
| | | HB120_tagMCZhanlingInfo.tagMCZhanling reward = netPack.RewardList[i]; |
| | | if (!battlePassData.battlePassCellDict.ContainsKey((int)reward.NeedValue)) |
| | | { |
| | | battlePassData.battlePassCellDict[(int)reward.NeedValue] = new BattlePassCell(); |
| | | } |
| | | |
| | | BattlePassCell battlePassCell = battlePassData.battlePassCellDict[(int)reward.NeedValue]; |
| | | battlePassCell.freeRewardState = reward.FreeRewardState; |
| | | battlePassCell.zlRewardState = reward.ZLRewardState; |
| | | battlePassCell.zlRewardStateH = reward.ZLRewardStateH; |
| | | } |
| | | |
| | | UpdateRedpoint(netPack.ZhanlingType); |
| | | BattlePassDataUpdateEvent?.Invoke(netPack.ZhanlingType); |
| | | } |
| | | |
| | | |
| | | void UpdateRedpoint(int type) |
| | | { |
| | | switch (type) |
| | | { |
| | | case WeekBattlePassType: |
| | | { |
| | | UpdateWeekRedPoint(); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | //是否有任何奖励可以领取 |
| | | public bool HasAnyAward(int type, int totalValue) |
| | | { |
| | | battlePassDataDict.TryGetValue(type, out BattlePassData battlePassData); |
| | | if (battlePassData == null) |
| | | return false; |
| | | if (battlePassData.allFinishTime != 0) |
| | | return false; |
| | | var allZhanling = ZhanlingConfig.GetTypeToIDDict(type); |
| | | |
| | | var keys = allZhanling.Keys.ToList(); |
| | | keys.Sort(); |
| | | foreach (var needValue in keys) |
| | | { |
| | | if (totalValue < needValue) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | if (battlePassData.battlePassCellDict.ContainsKey(needValue)) |
| | | { |
| | | if (battlePassData.battlePassCellDict[needValue].freeRewardState == 0) |
| | | { |
| | | return true; |
| | | } |
| | | else if (battlePassData.isActivite != 0 && battlePassData.battlePassCellDict[needValue].zlRewardState == 0) |
| | | { |
| | | return true; |
| | | } |
| | | else if (battlePassData.isActiviteH != 0 && battlePassData.battlePassCellDict[needValue].zlRewardStateH == 0) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 是否有某个奖励可以领取 |
| | | /// </summary> |
| | | /// <param name="battlePassData"></param> |
| | | /// <param name="totalValue"></param> |
| | | /// <param name="needValue"></param> |
| | | /// <param name="awardType">0 免费 1 普通 2 高级</param> |
| | | /// <returns>0 未达标 1 可领取 2 已领取</returns> |
| | | public int GetBPCellAwardState(BattlePassData battlePassData, int totalValue, int needValue, int awardType) |
| | | { |
| | | if (totalValue < needValue) |
| | | { |
| | | return 0; |
| | | } |
| | | |
| | | if (battlePassData.battlePassCellDict.ContainsKey(needValue)) |
| | | { |
| | | switch (awardType) |
| | | { |
| | | case 0: |
| | | { |
| | | return battlePassData.battlePassCellDict[needValue].freeRewardState == 0 ? 1 : 2; |
| | | } |
| | | case 1: |
| | | { |
| | | if (battlePassData.isActivite != 0) |
| | | { |
| | | return battlePassData.battlePassCellDict[needValue].zlRewardState == 0 ? 1 : 2; |
| | | } |
| | | break; |
| | | } |
| | | case 2: |
| | | { |
| | | if (battlePassData.isActiviteH != 0) |
| | | { |
| | | return battlePassData.battlePassCellDict[needValue].zlRewardStateH == 0 ? 1 : 2; |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | public int GetCTGIDByType(int type) |
| | | { |
| | | if (buyZhanlingTypeDict.ContainsKey(type)) |
| | | { |
| | | return buyZhanlingTypeDict[type][0]; |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | public BattlePassData GetBattlePassData(int type) |
| | | { |
| | | if (battlePassDataDict.ContainsKey(type)) |
| | | { |
| | | return battlePassDataDict[type]; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | |
| | | //发包 type 0-免费;1-普通战令;2-高级战令 |
| | | public void SendGetGift(int zhanLingType, int needValue, int type) |
| | | { |
| | | var pak = new CA504_tagCMPlayerGetReward(); |
| | | string dataExStr = (needValue * 10 + type).ToString(); |
| | | pak.RewardType = (byte)65; |
| | | pak.DataEx = (uint)zhanLingType; |
| | | pak.DataExStrLen = (byte)dataExStr.Length; |
| | | pak.DataExStr = dataExStr; |
| | | GameNetSystem.Instance.SendInfo(pak); |
| | | } |
| | | |
| | | //一次性全领取 |
| | | public void GetAllAward(BattlePassData battlePassData, int zhanLingType, int totalValue) |
| | | { |
| | | //简单判断背包 |
| | | if (PackManager.Instance.GetEmptyGridCount(PackType.Item) <= 1) |
| | | { |
| | | SysNotifyMgr.Instance.ShowTip("GeRen_lhs_202580"); |
| | | return; |
| | | } |
| | | var ids = ZhanlingConfig.GetTypeToIDDict(zhanLingType).Values.ToList(); |
| | | ids.Sort(); |
| | | foreach (var id in ids) |
| | | { |
| | | var config = ZhanlingConfig.Get(id); |
| | | if (config.NeedValue > totalValue) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | for (int i = 0; i < 3; i++) |
| | | { |
| | | |
| | | var state = GetBPCellAwardState(battlePassData, totalValue, config.NeedValue, i); |
| | | if (state == 1) |
| | | { |
| | | SendGetGift(zhanLingType, config.NeedValue, i); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | public int JumpIndex(BattlePassData battlePassData, int zhanLingType, int totalValue) |
| | | { |
| | | |
| | | var ids = ZhanlingConfig.GetTypeToIDDict(zhanLingType).Values.ToList(); |
| | | ids.Sort(); |
| | | int index = -1; |
| | | foreach (var id in ids) |
| | | { |
| | | index++; |
| | | var config = ZhanlingConfig.Get(id); |
| | | if (config.NeedValue > totalValue) |
| | | { |
| | | return index - 1; |
| | | } |
| | | |
| | | for (int i = 0; i < 3; i++) |
| | | { |
| | | var state = GetBPCellAwardState(battlePassData, totalValue, config.NeedValue, i); |
| | | if (state == 1) |
| | | { |
| | | return index; |
| | | } |
| | | } |
| | | } |
| | | return index; |
| | | } |
| | | } |
| | | |
| | | |
| | | public class BattlePassCell |
| | | { |
| | | public byte freeRewardState; // 免费战令奖励是否已领取 |
| | | public byte zlRewardState; // 普通战令奖励是否已领取 |
| | | public byte zlRewardStateH; // 高级战令奖励是否已领取 |
| | | } |
| | | |
| | | |
| | | public class BattlePassData |
| | | { |
| | | public byte isActivite; // 普通战令是否已激活 |
| | | public byte isActiviteH; // 高级战令是否已激活 |
| | | public uint allFinishTime; // 全部奖励领取完毕的时间戳,未完毕时该值为0,后端会在0点过天时检查可否重置,前端自行做倒计时表现即可 |
| | | public uint value1; // 战令对应的自定义值,可选,如登录战令代表开始计算日期时间戳 |
| | | |
| | | public Dictionary<int, BattlePassCell> battlePassCellDict = new Dictionary<int, BattlePassCell>(); |
| | | } |
copy from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta
copy to Main/System/BattlePass/BattlePassManager.cs.meta
| File was copied from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta |
| | |
| | | fileFormatVersion: 2 |
| | | guid: a6484a8278af59643850fd9225f7338d |
| | | guid: 973e17d74c0fddf43b8085d369f35feb |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | |
| | | break;
|
| | | case 1:
|
| | | //周奖励
|
| | | // currentSubUI = UIManager.Instance.OpenWindow<HeroCollectionWin>();
|
| | | currentSubUI = UIManager.Instance.OpenWindow<WeekBattlePassWin>();
|
| | | titleText.text = Language.Get("DayMission3");
|
| | | break;
|
| | | case 2:
|
| | | //主线任务(英雄之路)
|
| | | currentSubUI = UIManager.Instance.OpenWindow<DayMissionWin>();
|
| | | titleText.text = Language.Get("DayMission4");
|
| | | break;
|
| | | default:
|
| | |
| | | public override void Init() |
| | | { |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitialize; |
| | | GlobalTimeEvent.Instance.secondEvent += OnSecondEvent; |
| | | GlobalTimeEvent.Instance.MS100Event += OnMSEvent; |
| | | |
| | | ParseConfig(); |
| | | } |
| | |
| | | public override void Release() |
| | | { |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitialize; |
| | | GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent; |
| | | GlobalTimeEvent.Instance.MS100Event -= OnMSEvent; |
| | | } |
| | | |
| | | void OnBeforePlayerDataInitialize() |
| | |
| | | taskProcessDict.Clear(); |
| | | } |
| | | |
| | | void OnSecondEvent() |
| | | void OnMSEvent() |
| | | { |
| | | if (isRefreshDayMission) |
| | | { |
| New file |
| | |
| | | using System; |
| | | using System.Linq; |
| | | using UnityEngine; |
| | | using UnityEngine.UI; |
| | | |
| | | |
| | | public class WeekBattlePassCell : CellView |
| | | { |
| | | [SerializeField] ItemCell baseAward; |
| | | [SerializeField] Transform baseGotRect; |
| | | [SerializeField] Transform baseCanGetAwardRect; |
| | | [SerializeField] Transform upProcssBGRect; |
| | | [SerializeField] Transform upProcessRect; |
| | | [SerializeField] Transform downProcssBGRect; |
| | | [SerializeField] Transform downProcessRect; |
| | | [SerializeField] Text valueText; |
| | | [SerializeField] Image valueBGImg; |
| | | [SerializeField] ItemCell[] betterAwards; |
| | | [SerializeField] Transform[] betterGotRects; |
| | | [SerializeField] Transform[] betterCanGetAwardRects; |
| | | [SerializeField] Transform[] betterLockRects; |
| | | |
| | | [SerializeField] Transform mask; |
| | | |
| | | |
| | | public void Display(int id, BattlePassData battlePassData) |
| | | { |
| | | var config = ZhanlingConfig.Get(id); |
| | | int freeItemID = config.FreeRewardItemList[0][0]; |
| | | baseAward.Init(new ItemCellModel(freeItemID, false, config.FreeRewardItemList[0][1])); |
| | | var baseAwardState = BattlePassManager.Instance.GetBPCellAwardState(battlePassData, (int)battlePassData.value1, config.NeedValue, 0); |
| | | baseAward.button.AddListener(() => |
| | | { |
| | | GetAward(battlePassData, baseAwardState, freeItemID); |
| | | }); |
| | | |
| | | |
| | | baseGotRect.SetActive(baseAwardState == 2); |
| | | baseCanGetAwardRect.SetActive(baseAwardState == 1); |
| | | mask.SetActive(baseAwardState == 0); |
| | | |
| | | var ids = ZhanlingConfig.GetTypeToIDDict(BattlePassManager.WeekBattlePassType).Values.ToList(); |
| | | ids.Sort(); |
| | | upProcssBGRect.SetActive(ids[0] != id); |
| | | upProcessRect.SetActive(baseAwardState != 0); |
| | | |
| | | downProcssBGRect.SetActive(ids[ids.Count - 1] != id); |
| | | var nextConfig = ZhanlingConfig.Get(id + 1); |
| | | if (nextConfig != null) |
| | | { |
| | | downProcessRect.SetActive((int)battlePassData.value1 >= nextConfig.NeedValue); |
| | | } |
| | | else |
| | | { |
| | | downProcessRect.SetActive(false); |
| | | } |
| | | |
| | | valueText.text = config.NeedValue.ToString(); |
| | | valueBGImg.SetOrgSprite(baseAwardState == 0 ? "DayMission_img_99" : "DayMission_img_100", "DayMission"); |
| | | |
| | | var betterAwardState = BattlePassManager.Instance.GetBPCellAwardState(battlePassData, (int)battlePassData.value1, config.NeedValue, 1); |
| | | for (int i = 0; i < betterAwards.Length; i++) |
| | | { |
| | | int itemID = config.ZLRewardItemList[i][0]; |
| | | betterAwards[i].Init(new ItemCellModel(itemID, false, config.ZLRewardItemList[i][1])); |
| | | betterAwards[i].button.AddListener(() => |
| | | { |
| | | GetAward(battlePassData, betterAwardState, itemID); |
| | | }); |
| | | betterGotRects[i].SetActive(betterAwardState == 2); |
| | | betterCanGetAwardRects[i].SetActive(betterAwardState == 1); |
| | | betterLockRects[i].SetActive(battlePassData.isActivite == 0); |
| | | } |
| | | } |
| | | |
| | | void GetAward(BattlePassData battlePassData, int awardState, int itemID) |
| | | { |
| | | if (awardState != 1) |
| | | { |
| | | ItemTipUtility.Show(itemID); |
| | | return; |
| | | } |
| | | |
| | | BattlePassManager.Instance.GetAllAward(battlePassData, BattlePassManager.WeekBattlePassType, (int)battlePassData.value1); |
| | | } |
| | | } |
| | | |
| | | |
copy from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta
copy to Main/System/DayMission/WeekBattlePassCell.cs.meta
| File was copied from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta |
| | |
| | | fileFormatVersion: 2 |
| | | guid: a6484a8278af59643850fd9225f7338d |
| | | guid: 22ee6f5381c87b443a607448c096a1af |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| New file |
| | |
| | | using System.Collections.Generic;
|
| | | using System.Linq;
|
| | | using UnityEngine;
|
| | | using UnityEngine.UI;
|
| | |
|
| | | //周战令
|
| | | public class WeekBattlePassWin : UIBase
|
| | | {
|
| | | [SerializeField] Text totalActivityText;
|
| | | [SerializeField] Text timeText;
|
| | | [SerializeField] ScrollerController scroller;
|
| | | [SerializeField] Transform lockRect;
|
| | | [SerializeField] Button buyBtn;
|
| | | [SerializeField] Text buyText;
|
| | |
|
| | | BattlePassData battlePassData;
|
| | |
|
| | |
|
| | | protected override void InitComponent()
|
| | | {
|
| | | buyBtn.AddListener(() =>
|
| | | {
|
| | | RechargeManager.Instance.CTG(BattlePassManager.Instance.GetCTGIDByType(BattlePassManager.WeekBattlePassType));
|
| | | });
|
| | | }
|
| | | protected override void OnPreOpen()
|
| | | {
|
| | | battlePassData = BattlePassManager.Instance.GetBattlePassData(BattlePassManager.WeekBattlePassType);
|
| | | if (battlePassData == null) return;
|
| | | scroller.OnRefreshCell += OnRefreshCell;
|
| | | GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
|
| | | BattlePassManager.Instance.BattlePassDataUpdateEvent += BattlePassDataUpdateEvent;
|
| | | CreateScroller();
|
| | | Display();
|
| | |
|
| | |
|
| | | }
|
| | |
|
| | | protected override void OnPreClose()
|
| | | {
|
| | | scroller.OnRefreshCell -= OnRefreshCell;
|
| | | GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
|
| | | BattlePassManager.Instance.BattlePassDataUpdateEvent -= BattlePassDataUpdateEvent;
|
| | |
|
| | | }
|
| | |
|
| | | void OnSecondEvent()
|
| | | {
|
| | | //按开服天 7天一个循环
|
| | | var day = 7 - (TimeUtility.OpenDay % 7) - 1;
|
| | | if (day == 0)
|
| | | {
|
| | | timeText.text = Language.Get("GoldRush29") + TimeUtility.SecondsToShortDHMS((int)(TimeUtility.GetTodayEndTime() - TimeUtility.ServerNow).TotalSeconds);
|
| | | }
|
| | | else
|
| | | {
|
| | | timeText.text = Language.Get("GoldRush29") + day + Language.Get("L1074");
|
| | | }
|
| | | }
|
| | |
|
| | | void BattlePassDataUpdateEvent(int type)
|
| | | {
|
| | | if (type == BattlePassManager.WeekBattlePassType)
|
| | | {
|
| | | Display();
|
| | | }
|
| | | }
|
| | |
|
| | |
|
| | | void Display()
|
| | | {
|
| | | totalActivityText.text = battlePassData.value1.ToString();
|
| | | lockRect.SetActive(battlePassData.isActivite == 0);
|
| | | scroller.m_Scorller.RefreshActiveCellViews();
|
| | |
|
| | | if (battlePassData.isActivite == 0)
|
| | | {
|
| | | var ctgID = BattlePassManager.Instance.GetCTGIDByType(BattlePassManager.WeekBattlePassType);
|
| | | RechargeManager.Instance.TryGetOrderInfo(ctgID, out var orderInfoConfig);
|
| | | buyText.text = Language.Get("PayMoneyNum", orderInfoConfig.PayRMBNumOnSale);
|
| | | buyBtn.SetInteractable(true);
|
| | | }
|
| | | else
|
| | | {
|
| | | buyText.text = Language.Get("L1133");
|
| | | buyBtn.SetInteractable(false);
|
| | | }
|
| | | }
|
| | |
|
| | |
|
| | | void CreateScroller()
|
| | | {
|
| | | scroller.Refresh();
|
| | | var values = ZhanlingConfig.GetTypeToIDDict(BattlePassManager.WeekBattlePassType).Values.ToList();
|
| | | values.Sort();
|
| | | for (int i = 0; i < values.Count; i++)
|
| | | {
|
| | | scroller.AddCell(ScrollerDataType.Header, values[i]);
|
| | | }
|
| | | scroller.Restart();
|
| | |
|
| | | scroller.JumpIndex(BattlePassManager.Instance.JumpIndex(battlePassData, BattlePassManager.WeekBattlePassType, (int)battlePassData.value1));
|
| | | }
|
| | |
|
| | |
|
| | | void OnRefreshCell(ScrollerDataType type, CellView cell)
|
| | | {
|
| | | var _cell = cell as WeekBattlePassCell;
|
| | | _cell.Display(cell.index, battlePassData);
|
| | | }
|
| | | }
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
copy from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta
copy to Main/System/DayMission/WeekBattlePassWin.cs.meta
| File was copied from Main/Core/NetworkPackage/ServerPack/HA0_Sys/HA005_tagOpenServerDay.cs.meta |
| | |
| | | fileFormatVersion: 2 |
| | | guid: a6484a8278af59643850fd9225f7338d |
| | | guid: e87e9af324b150d4fb0c3f0732593f2b |
| | | MonoImporter: |
| | | externalObjects: {} |
| | | serializedVersion: 2 |
| | |
| | | using DG.Tweening;
|
| | | using Cysharp.Threading.Tasks;
|
| | | using DG.Tweening;
|
| | | using System;
|
| | | using System.Linq;
|
| | | using UnityEngine;
|
| | |
| | | /// </summary>
|
| | | /// <param name="index">掉落背包索引</param>
|
| | | /// <param name="isAnimate">是否播放掉落动画</param>
|
| | | public void Display(int index, bool isAnimate, RectTransform rect)
|
| | | public async UniTask Display(int index, bool isAnimate, RectTransform rect)
|
| | | {
|
| | | await UniTask.Delay(300);
|
| | | itemIndex = index;
|
| | | float duration = 0.5f / AutoFightModel.Instance.fightSpeed; //掉落时间
|
| | | var item = PackManager.Instance.GetItemByIndex(PackType.DropItem, index);
|
| | |
| | | this.transform.SetActive(false);
|
| | | return;
|
| | | }
|
| | | this.transform.SetActive(true);
|
| | | itemImage.SetOrgSprite(item.config.IconKey);
|
| | | int effectID = EquipModel.Instance.equipUIEffectLights[Math.Min(item.config.ItemColor, EquipModel.Instance.equipUIEffectLights.Length) - 1];
|
| | | if (effectID == 0)
|
| | |
| | | continue;
|
| | | }
|
| | |
|
| | | item.SetActive(true);
|
| | | |
| | | item.Display(i, isAnimate, rect == null ? defaultDropRect : rect);
|
| | | }
|
| | | }
|
| | |
| | | HeroUIManager.Instance.selectCallIndex = 1; |
| | | HappyXBModel.Instance.SendXBManyQuest((int)HeroUIManager.Instance.selectCallType); |
| | | }); |
| | | showNextlhOrCloseBtn.AddListener(RefreshLihui); |
| | | showNextlhOrCloseBtn.AddListener(()=> |
| | | { |
| | | if (Time.time - lastShowLHTime < 0.5f) |
| | | { |
| | | return; |
| | | } |
| | | RefreshLihui(); |
| | | }); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | float lastShowLHTime = 0; //上次显示立绘的时间 设置点击间隔 |
| | | void RefreshLihui() |
| | | { |
| | | lastShowLHTime = Time.time; |
| | | //汇总品质传说及以上的立绘 |
| | | int heroID = 0; |
| | | if (showLHHeroIDList.Count > 0) |
| | |
| | | deleteBtn.AddListener(DeleteHero); |
| | | awakeBtn.AddListener(() => |
| | | { |
| | | if (!FuncOpen.Instance.IsFuncOpen(38, true)) |
| | | { |
| | | return; |
| | | } |
| | | HeroUIManager.Instance.selectAwakeHeroGuid = guid; |
| | | UIManager.Instance.OpenWindow<HeroAwakeWin>(); |
| | | }); |
| | |
| | | fullGoldRush.SetActive(GoldRushManager.Instance.GetFinishGoldRushCount() >= GoldRushManager.Instance.warehouseMaxCnt); |
| | | RefreshGoldRushMoney(); |
| | | autoText.text = Language.Get(GoldRushManager.Instance.isAutoWorking ? "GoldRush34" : "GoldRush24"); |
| | | |
| | | if (FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.GoldRush)) |
| | | { |
| | | autoBtn.SetActive(true); |
| | | goldRushItemBtn.SetActive(true); |
| | | } |
| | | else |
| | | { |
| | | autoBtn.SetActive(false); |
| | | goldRushItemBtn.SetActive(false); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | leaderWord.SetActive(true); |
| | | leaderWord.Play(); |
| | | leaderText.text = Language.Get(!pathPosEvent.m_IsRandom ? pathPosEvent.m_Text1 : |
| | | leaderText.text = Language.Get(!pathPosEvent.m_IsRandom ? pathPosEvent.m_Text1 : |
| | | pathPosEvent.m_Text1 + UnityEngine.Random.Range((int)pathPosEvent.m_Value1, (int)pathPosEvent.m_Value2 + 1)); |
| | | ForceRefreshLayout(); |
| | | } |
| | | else if (pathPosEvent.m_PosEvent == PosEvent.TargetWord) |
| | | { |
| | |
| | | |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 强制刷新Layout,解决嵌套Layout和ContentSizeFitter的重叠问题 |
| | | /// </summary> |
| | | async UniTask ForceRefreshLayout() |
| | | { |
| | | await UniTask.DelayFrame(2); |
| | | LayoutRebuilder.ForceRebuildLayoutImmediate(leaderWord.GetComponent<RectTransform>()); |
| | | } |
| | | } |
| | | |
| | |
| | | using DG.Tweening; |
| | | using System.Linq; |
| | | using System; |
| | | using Cysharp.Threading.Tasks; |
| | | |
| | | //工人是固定的跟随模式,监工是随机分配的,场上的监工数量会比实际更多 |
| | | //分配监工 |
| | |
| | | wordArr[index].SetActive(true); |
| | | wordArr[index].Play(); |
| | | textArr[index].text = Language.Get(content); |
| | | ForceRefreshLayout(); |
| | | } |
| | | else if (posEvent == PosEvent.TargetAction) |
| | | { |
| | |
| | | |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 强制刷新Layout,解决嵌套Layout和ContentSizeFitter的重叠问题 |
| | | /// </summary> |
| | | async UniTask ForceRefreshLayout() |
| | | { |
| | | await UniTask.DelayFrame(2); |
| | | foreach (var word in wordArr) |
| | | { |
| | | LayoutRebuilder.ForceRebuildLayoutImmediate(word.GetComponent<RectTransform>()); |
| | | } |
| | | } |
| | | |
| | | |
| | | void AssignLeader(int addCount) |
| | |
| | | // 如果后续想做:不想要蒙版 又想要点击引导的位置才有效 则可以是在勾选clickAnyWhereComplete情况下,改变mask的alpha值即可配合提示 |
| | | public bool clickAnyWhereComplete = false; |
| | | public bool clickCompleteNoMask = false; //非强制引导,任意点击关闭,勾选此项会隐藏蒙版,且点击其他区域不会响应按钮事件 |
| | | |
| | | public int delayTime = 0; //展示时间(毫秒),期间不可点击 |
| | | |
| | | // 引导的文本的箭头位置 |
| | | public enum ArrowPosition |
| | |
| | | GuideConfig config;
|
| | | NewBieGuideScriptableObject stepConfig; //引导步骤
|
| | |
|
| | | float lastShowTime;
|
| | |
|
| | | #region Built-in
|
| | |
|
| | | protected override void InitComponent()
|
| | | {
|
| | | m_ClickTalk.AddListener(()=>
|
| | | m_ClickTalk.AddListener(() =>
|
| | | {
|
| | | ReportStepOver();
|
| | | });
|
| | |
| | | CloseWindow();
|
| | | return;
|
| | | }
|
| | | lastShowTime = Time.time;
|
| | |
|
| | | if (config.WinName != "EquipExchangeWin" && UIManager.Instance.IsOpened<EquipExchangeWin>())
|
| | | {
|
| | |
| | | }
|
| | |
|
| | | m_ClickEffect.effectId = stepConfig.effect; //如果需要点击特效也增加偏移量
|
| | | m_ClickEffect.SetActive(true);
|
| | | m_ClickEffect.Play();
|
| | | m_ClickEffect.transform.position = m_ClickTarget.position;
|
| | | m_ClickEffect.transform.localPosition = m_ClickEffect.transform.localPosition + (Vector3)stepConfig.usherPosition;
|
| | | m_ClickEffect.SetActive(false);
|
| | | DelayShowClickEffect().Forget();
|
| | |
|
| | | if (stepConfig.clickCompleteNoMask)
|
| | | {
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | async UniTask DelayShowClickEffect()
|
| | | {
|
| | | await UniTask.Delay(stepConfig.delayTime);
|
| | | m_ClickEffect.SetActive(true);
|
| | | m_ClickEffect.Play();
|
| | | m_ClickEffect.transform.position = m_ClickTarget.position;
|
| | | m_ClickEffect.transform.localPosition = m_ClickEffect.transform.localPosition + (Vector3)stepConfig.usherPosition;
|
| | |
|
| | | }
|
| | |
|
| | | void LateUpdate()
|
| | | {
|
| | | if (Input.GetMouseButtonUp(0))
|
| | |
| | | }
|
| | | if (stepConfig.clickAnyWhereComplete || m_NewBieMask.mask.IsInCirleArea(Input.mousePosition, CameraManager.uiCamera))
|
| | | {
|
| | | if (stepConfig.delayTime > 0 && (Time.time - lastShowTime)*1000 < stepConfig.delayTime)
|
| | | {
|
| | | return;
|
| | | }
|
| | | if (m_ClickTarget == null)
|
| | | {
|
| | | Debug.LogError("引导 m_ClickTarget == null; step = " + NewBieCenter.Instance.guideStep);
|
| | |
| | | |
| | | |
| | | public class GlobalTimeEvent : SingletonMonobehaviour<GlobalTimeEvent> |
| | | |
| | | { |
| | | public event Action MS100Event; |
| | | public event Action secondEvent; |
| | | public event Action fiveSecondEvent; |
| | | public event Action minuteEvent; |
| | |
| | | public event Action hourEvent; |
| | | public event Action halfMinuteEvent; |
| | | |
| | | float msBuf = 0f; |
| | | int secondBuf = -1; |
| | | int fiveSecondBuf = -1; |
| | | int minuteBuf = -1; |
| | |
| | | |
| | | private void Update() |
| | | { |
| | | var ms = Time.time; |
| | | if (ms - msBuf >= 0.1f) |
| | | { |
| | | if (MS100Event != null) |
| | | { |
| | | MS100Event(); |
| | | } |
| | | msBuf = ms; |
| | | } |
| | | |
| | | |
| | | var second = DateTime.Now.Second; |
| | | if (second != secondBuf) |
| | | { |
| | |
| | | } |
| | | |
| | | public static event Action OnServerOpenDayRefresh; |
| | | public static void OnRefreshServerOpenDay(HA005_tagOpenServerDay package) |
| | | public static void OnRefreshServerOpenDay(HA103_tagMCOpenServerDay package) |
| | | { |
| | | { |
| | | OpenDay = package.Day; |