hch
2 天以前 1898a5f28dfffa7bbecf5d2bf024f20b8d0490e7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using System.Linq;
using EnhancedUI.EnhancedScroller;
 
public class HeroDebutCallWin : UIBase
{
    [SerializeField] ImageEx bgImage;
    [SerializeField] RectTransform changeRect;
    [SerializeField] UIEffectPlayer changeUIEffect;
 
    [SerializeField] OwnItemCell ownItemCell;
    [SerializeField] ButtonEx closeBtn;
    [SerializeField] Toggle skipToggle;
    [SerializeField] HeroDebutCallButton xbButton1;
    [SerializeField] HeroDebutCallButton xbButton10;
    [SerializeField] TextEx resMoneyCallCntText;
    [SerializeField] GradientText nextBigAwardCntText;
    [SerializeField] GradientText heroQualityText;
    [SerializeField] GradientText heroNameText;
 
    [SerializeField] TextEx timeText;
 
    [SerializeField] TextEx nameText;
    [SerializeField] TextEx descText;
    [SerializeField] ImageEx countryImage;
    [SerializeField] ImageEx jobImage;
    [SerializeField] ButtonEx changeHeroButton;//更换英雄
    [SerializeField] ButtonEx previewButton;//满级预览
    [SerializeField] ButtonEx closeButton;
    [SerializeField] ButtonEx shopButton; // 兑换商店
    [SerializeField] RedpointBehaviour shopRedpoint;
    [SerializeField] ButtonEx giftButton; // 皇权礼包
    [SerializeField] RedpointBehaviour giftRedpoint;
 
    [SerializeField] ButtonEx rankButton;
    [SerializeField] TextEx[] top3NameText;
    [SerializeField] TextEx rankTipText;
    [SerializeField] ButtonEx rateButton;
    [SerializeField] ScrollerController scroller;
    [SerializeField] ButtonEx historyButton;
    [SerializeField] UIHeroController lhController;
    [SerializeField] UIHeroController uiHeroController;
    [SerializeField] HeroDebutCallBubbleCell[] bubbleCell;
 
    [SerializeField] float modleSize = 1f;
    HeroDebutManager manager => HeroDebutManager.Instance;
 
    protected override void InitComponent()
    {
        closeButton.SetListener(CloseWindow);
        shopButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutShopWin>());
        giftButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutGiftWin>());
        changeHeroButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutCallChangeWin>());
        rankButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutRankWin>());
        rateButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutCallRateWin>());
        historyButton.SetListener(() => UIManager.Instance.OpenWindow<HeroDebutCallHistoryWin>());
        previewButton.SetListener(OnClickPreview);
        skipToggle.AddListener((value) =>
        {
            manager.SaveCallSkipData(config.CfgID, act.startDate, act.endDate, value);
        });
    }
 
 
    protected override void OnPreOpen()
    {
        scroller.lockType = EnhanceLockType.LockVerticalBottom;
        RankModel.Instance.ResetQueryParam();
        RankModel.Instance.QueryRankByPage(manager.sendRankType, watchID: (int)PlayerDatas.Instance.baseData.PlayerID, groupValue1: manager.actNum);
 
        HappyXBModel.Instance.RefreshXBTypeInfoAct += OnRefreshXBTypeInfoAct;
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        RankModel.Instance.onRankRefresh += OnRankRefresh;
        PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefresh;
        PackManager.Instance.RefreshItemEvent += RefreshItemEvent;
        scroller.OnRefreshCell += OnRefreshCell;
        manager.OnUpdateGameRecInfo += OnUpdateGameRecInfo;
 
        if (manager.isSendFirst)
        {
            act = manager.GetOperationHeroAppearInfo();
            if (act == null) return;
 
            config = ActHeroAppearConfig.Get(act.CfgID);
            if (config == null) return;
 
            int treasureType = config.ActTreasureType;
            manager.SendViewGameRecPack(treasureType);
        }
 
        InitRedpoint();
        CreateScroller();
        Display();
    }
 
    protected override void OnPreClose()
    {
        HappyXBModel.Instance.RefreshXBTypeInfoAct -= OnRefreshXBTypeInfoAct;
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
        RankModel.Instance.onRankRefresh -= OnRankRefresh;
        PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefresh;
        PackManager.Instance.RefreshItemEvent -= RefreshItemEvent;
        scroller.OnRefreshCell -= OnRefreshCell;
        manager.OnUpdateGameRecInfo -= OnUpdateGameRecInfo;
        manager.OnUpdateHeroAppearPlayerInfoEvent -= OnUpdateHeroAppearPlayerInfoEvent;
    }
 
 
 
    // 1. 在类中声明一个全局的 Sequence 变量,用于统一管控动画
    private Sequence heroAnimSeq;
 
    private void OnUpdateHeroAppearPlayerInfoEvent(int actNum)
    {
        changeRect.SetActive(false);
 
        // 2. 彻底杀死之前的 Sequence,防止快速连点造成内部 Tween 复用错乱
        if (heroAnimSeq != null)
        {
            heroAnimSeq.Kill();
            heroAnimSeq = null;
        }
 
        // 刷新界面数据和英雄模型(这里面会调用 lhController.Create)
        Display();
 
        Transform targetTrans = lhController.transform;
 
        // 停止 Transform 上可能残留的单独动画
        targetTrans.DOKill();
 
        int heroID = manager.GetCurrentDisplayCallHeroId();
        int skinID = manager.GetDefaultSkinID(heroID);
        var skinConfig = HeroSkinConfig.Get(skinID);
 
        float baseScaleValue = 1f; // 默认缩放
        // 检查是否有配置专属的立绘缩放参数(TachieParam[2])
        if (skinConfig != null && skinConfig.TachieParam != null && skinConfig.TachieParam.Length == 4)
        {
            baseScaleValue = skinConfig.TachieParam[2];
        }
 
        Vector3 baseScale = Vector3.one * baseScaleValue;
 
        // 【强制复位!】解决 UIHeroController 内部 return 导致的缩放未复位问题
        targetTrans.localScale = baseScale;
 
        // 获取或添加 CanvasGroup 用于透明度控制
        CanvasGroup cg = lhController.GetComponent<CanvasGroup>();
        if (cg == null) cg = lhController.gameObject.AddComponent<CanvasGroup>();
        cg.DOKill();
        cg.alpha = 0.8f;
 
        changeUIEffect.Play();
 
        // 4. 创建新的 Sequence 并赋值给成员变量
        heroAnimSeq = DOTween.Sequence();
 
        // 缩放动画基于正确的 baseScale 进行计算(变大1.1倍后再还原)
        heroAnimSeq.Append(targetTrans.DOScale(baseScale * 1.1f, 0.3f).SetEase(Ease.OutQuad));
        heroAnimSeq.Append(targetTrans.DOScale(baseScale, 0.3f).SetEase(Ease.InQuad));
 
        // 透明度
        heroAnimSeq.Join(cg.DOFade(1f, 0.3f).SetEase(Ease.Linear));
 
        // 动画完成后显示 changeRect,并清空引用
        heroAnimSeq.OnComplete(() =>
        {
            changeRect.SetActive(true);
            heroAnimSeq = null;
        });
    }
 
    private void OnUpdateGameRecInfo()
    {
        CreateScroller();
    }
 
    public void RefreshItemEvent(PackType packType, int index, int itemID)
    {
        if (packType != PackType.Item && treasureSetConfig?.CostItemID != itemID) return;
        Display();
    }
    private void PlayerDataRefresh(PlayerDataType type)
    {
        if (type != PlayerDataType.Gold) return;
        Display();
    }
 
    private void OnRankRefresh(int type)
    {
        if (type != manager.sendRankType) return;
        ShowTop3();
    }
 
    private void OnSecondEvent()
    {
        manager.GetActTimeStr(timeText);
    }
 
    private void OnRefreshXBTypeInfoAct()
    {
        Display();
    }
 
    public void InitRedpoint()
    {
        shopRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.Shop);
        giftRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.Gift);
    }
 
    private void OnClickPreview()
    {
        if (heroConfig == null) return;
        HeroUIManager.Instance.selectForPreviewHeroID = heroConfig.HeroID;
        UIManager.Instance.OpenWindow<HeroBestBaseWin>();
    }
    OperationHeroAppearInfo act;
    ActHeroAppearConfig config;
    HeroConfig heroConfig;
    TreasureSetConfig treasureSetConfig;
    XBTypeInfo xbTypeInfo;
    private void Display()
    {
        act = manager.GetOperationHeroAppearInfo();
        if (act == null) return;
 
        config = ActHeroAppearConfig.Get(act.CfgID);
        if (config == null) return;
 
        int heroID = manager.GetCurrentDisplayCallHeroId();
        heroConfig = HeroConfig.Get(heroID);
        if (heroConfig == null) return;
 
        int skinID = manager.GetDefaultSkinID(heroID);
        var skinConfig = HeroSkinConfig.Get(skinID);
        if (skinConfig == null) return;
 
        var artConfig = ActHeroAppearArtConfig.Get(heroID);
        if (artConfig == null || artConfig.CallBubbleItems == null) return;
 
        int treasureType = config.ActTreasureType;
        treasureSetConfig = TreasureSetConfig.Get(treasureType);
        if (treasureSetConfig == null) return;
 
        xbTypeInfo = HappyXBModel.Instance.GetXBInfoByType(treasureType);
        if (xbTypeInfo == null) return;
 
        bgImage.SetSprite(artConfig.MainBgImage);
 
        lhController.Create(skinID, 1, motionName: "", isLh: true);
        uiHeroController.Create(skinID, modleSize);
        uiHeroController.transform.localScale = new Vector3(modleSize, modleSize, modleSize);
 
        ownItemCell.itemID = treasureSetConfig.CostItemID;
        skipToggle.isOn = manager.LoadCallSkipData(config.CfgID, act.startDate, act.endDate);
 
        xbButton1.Display(config.ActTreasureType, 0);
        xbButton10.Display(config.ActTreasureType, 1);
        resMoneyCallCntText.text = Language.Get("HeroDebut24", Mathf.Max(treasureSetConfig.DailyMaxCountMoney - xbTypeInfo.treasureCountTodayGold, 0));
 
        var needCount = GetNextXBCountForBigAward(treasureType);
        nextBigAwardCntText.text = needCount.ToString();
 
        heroQualityText.text = Language.Get($"heroCallQaulity{heroConfig.Quality}");
        manager.SetheroQaulityColor(heroQualityText, heroConfig.Quality);
 
        nameText.text = heroConfig.Name;
        nameText.color = UIHelper.GetUIColorByFunc(heroConfig.Quality);
        descText.text = heroConfig.Desc;
        countryImage.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroConfig.Country));
        jobImage.SetSprite(HeroUIManager.Instance.GetJobIconName(heroConfig.Class));
 
        heroNameText.text = heroConfig.Name;
        manager.SetGradientTextColor(heroNameText, artConfig.HeroNameColor);
 
        for (int i = 0; i < bubbleCell.Length; i++)
        {
            if (i < artConfig.CallBubbleItems.Length)
            {
                bubbleCell[i].SetActive(true);
                bubbleCell[i].Display(artConfig.CallBubbleItems[i][0], artConfig.CallBubbleItems[i][1]);
            }
            else
            {
                bubbleCell[i].SetActive(false);
            }
        }
 
        ShowTop3();
        OnSecondEvent();
    }
 
    public int GetNextXBCountForBigAward(int type)
    {
        XBTypeInfo typeInfo = HappyXBModel.Instance.GetXBInfoByType(type);
        if (typeInfo == null) return 0;
 
        var xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(type);
        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
        luckList.Sort();
        for (int i = 0; i < luckList.Count; i++)
        {
            var luckyValue = typeInfo.luckValue;
            if (luckyValue < luckList[i])
            {
                return luckList[i] - luckyValue;
            }
        }
        return 0;
    }
    void ShowTop3()
    {
        for (int i = 0; i < top3NameText.Length; i++)
        {
            var rankData = RankModel.Instance.GetRankDataByRank(manager.loadRankType, i + 1);
            top3NameText[i].text = rankData == null ? Language.Get("L1124") : rankData.name1;
        }
        int billTempID = config.BillTempID;
        rankTipText.text = Language.Get("HeroDebut27", ActBillboardAwardConfig.GetTop3MinCalNeedValue(billTempID));
    }
    public List<HeroDebutGameRec> list;
    void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as HeroDebutCallHistoryOutCell;
        _cell.Display(cell.index, list);
    }
 
    float autoScrollInterval = 2f;
    private float autoScrollTimer = 0f;
    private int currentScrollerIndex = 0;
    private bool isScrollerReady = false; // 判定标志
    void CreateScroller()
    {
        list = manager.GetGameRecList();
        scroller.Refresh();
 
        int listCount = list?.Count ?? 0;
        if (list != null)
        {
            for (int i = 0; i < listCount; i++)
            {
                scroller.AddCell(ScrollerDataType.Header, i);
            }
        }
 
 
        bool canScroll = listCount > 4;// 只有数量 > 4 时才开启 Loop 和计时器
        scroller.m_Scorller.Loop = canScroll;
        isScrollerReady = canScroll;
 
        scroller.vertical = false;
        scroller.horizontal = false;
        scroller.Restart();
 
        // 如果是循环模式,确保初始位置正确
        if (canScroll)
        {
            scroller.m_Scorller.JumpToDataIndex(0,
            tweenType: EnhancedScroller.TweenType.immediate);
        }
        autoScrollTimer = 0f;
        currentScrollerIndex = 0;
    }
 
    private void LateUpdate()
    {
        // 只有在数据就绪且超过 4 个时,才执行计时逻辑
        if (isScrollerReady)
        {
            autoScrollTimer += Time.deltaTime;
            if (autoScrollTimer >= autoScrollInterval)
            {
                autoScrollTimer = 0f;
                AutoScrollNext();
            }
        }
    }
 
    private void AutoScrollNext()
    {
        if (list?.Count <= 4)
        {
            isScrollerReady = false;
            return;
        }
 
        currentScrollerIndex++;
        // 在 Loop 模式下进行平滑跳转
        scroller.m_Scorller.JumpToDataIndex(
            currentScrollerIndex % list.Count,
            tweenType: EnhancedScroller.TweenType.easeInOutQuad,
            tweenTime: 0.5f);
    }
}