Commit d20b6d9e authored by Senator John's avatar Senator John 💬

Merge branch 'patch' into 'master'

Patch

See merge request !32
parents b3287b74 eea6cdcb
...@@ -954,7 +954,7 @@ MonoBehaviour: ...@@ -954,7 +954,7 @@ MonoBehaviour:
- id: 1003003 - id: 1003003
m_name: m_name:
m_description: m_description:
path: Mate/M13670_Model path: Mate/M13671_Model
secondFace: 1 secondFace: 1
diy: 0 diy: 0
notReady: 0 notReady: 0
...@@ -965,6 +965,13 @@ MonoBehaviour: ...@@ -965,6 +965,13 @@ MonoBehaviour:
secondFace: 1 secondFace: 1
diy: 0 diy: 0
notReady: 0 notReady: 0
- id: 1003203
m_name:
m_description:
path: Mate/M13670_Model
secondFace: 1
diy: 0
notReady: 0
- id: 1003004 - id: 1003004
m_name: m_name:
m_description: m_description:
...@@ -8133,4 +8140,4 @@ MonoBehaviour: ...@@ -8133,4 +8140,4 @@ MonoBehaviour:
path: Wallpaper/88177324 path: Wallpaper/88177324
secondFace: 0 secondFace: 0
diy: 1 diy: 1
notReady: 0 notReady: 0
\ No newline at end of file
using System.Collections.Generic;
using System.Linq;
namespace MDPro3.Duel
{
public enum PremiumMateBehavior
{
LaundryBattlePhaseRoundTrip,
GaiaExtraDeckPermanent,
ShuraigLpThreshold,
RayeBattlePhaseAndDirectAttack,
FiendsmithExtraDeckOrEquipPermanent,
IpSpTurnParity
}
public sealed class PremiumMateRule
{
public int BaseId { get; }
public int SubId { get; }
public IReadOnlyList<int> VariantIds { get; }
public PremiumMateBehavior Behavior { get; }
public int LpThreshold { get; }
public PremiumMateRule(
int baseId,
int subId,
PremiumMateBehavior behavior,
int lpThreshold = 0,
IReadOnlyList<int> extraVariantIds = null)
{
BaseId = baseId;
SubId = subId;
Behavior = behavior;
LpThreshold = lpThreshold;
var variants = new List<int> { subId };
if (extraVariantIds != null)
foreach (var variantId in extraVariantIds)
if (variantId > 0 && variantId != baseId && !variants.Contains(variantId))
variants.Add(variantId);
VariantIds = variants;
}
}
public static class PremiumMateRules
{
private static readonly List<PremiumMateRule> _rules = new()
{
new PremiumMateRule(1000020, 1000021, PremiumMateBehavior.LaundryBattlePhaseRoundTrip),
new PremiumMateRule(1003001, 1003101, PremiumMateBehavior.GaiaExtraDeckPermanent),
new PremiumMateRule(1003002, 1003102, PremiumMateBehavior.ShuraigLpThreshold, 3000),
new PremiumMateRule(1003003, 1003203, PremiumMateBehavior.RayeBattlePhaseAndDirectAttack, 0, new[] { 1003103 }),
new PremiumMateRule(1003004, 1003104, PremiumMateBehavior.FiendsmithExtraDeckOrEquipPermanent),
new PremiumMateRule(1003005, 1003105, PremiumMateBehavior.IpSpTurnParity),
};
private static readonly Dictionary<int, PremiumMateRule> _ruleByAnyId = _rules
.SelectMany(rule => rule.VariantIds
.Select(id => new KeyValuePair<int, PremiumMateRule>(id, rule))
.Prepend(new KeyValuePair<int, PremiumMateRule>(rule.BaseId, rule)))
.ToDictionary(pair => pair.Key, pair => pair.Value);
private static readonly Dictionary<int, PremiumMateRule> _ruleByBaseId = _rules
.ToDictionary(rule => rule.BaseId, rule => rule);
public static IReadOnlyList<PremiumMateRule> All => _rules;
public static bool TryGetRule(int mateId, out PremiumMateRule rule)
{
return _ruleByAnyId.TryGetValue(mateId, out rule);
}
public static bool TryGetRuleByBaseId(int mateId, out PremiumMateRule rule)
{
return _ruleByBaseId.TryGetValue(mateId, out rule);
}
public static bool IsPremiumMateId(int mateId)
{
return _ruleByAnyId.ContainsKey(mateId);
}
public static bool IsPremiumBaseId(int mateId)
{
return _ruleByBaseId.ContainsKey(mateId);
}
public static bool IsPremiumVariantId(int mateId)
{
return TryGetRule(mateId, out var rule) && rule.VariantIds.Contains(mateId);
}
public static int GetBaseMateId(int mateId)
{
return TryGetRule(mateId, out var rule) ? rule.BaseId : mateId;
}
public static int GetSubMateId(int mateId)
{
return TryGetRule(mateId, out var rule) ? rule.SubId : mateId;
}
public static List<Items.Item> FilterAppearanceMateItems(IEnumerable<Items.Item> source)
{
return source.Where(item => !IsPremiumVariantId(item.id)).ToList();
}
}
}
fileFormatVersion: 2
guid: 555a55c03fd6e3d45bc341e9808a721c
\ No newline at end of file
This diff is collapsed.
fileFormatVersion: 2
guid: fd603fb2afd594547a10c88eda27f8dd
\ No newline at end of file
...@@ -920,6 +920,13 @@ namespace MDPro3.Duel ...@@ -920,6 +920,13 @@ namespace MDPro3.Duel
card.AnimationPositon(); card.AnimationPositon();
ES_hint = InterString.Get("「[?]」特殊召唤宣言时", card.GetData().Name); ES_hint = InterString.Get("「[?]」特殊召唤宣言时", card.GetData().Name);
var isExtraDeckMonster = card.GetData().HasType(CardType.Fusion)
|| card.GetData().HasType(CardType.Synchro)
|| card.GetData().HasType(CardType.Xyz)
|| card.GetData().HasType(CardType.Link);
if (isExtraDeckMonster)
duelBGManager.OnSpecialSummonFromExtra(gps.InMyControl() ? 0 : 1);
if(materialCards.Count > 0) if(materialCards.Count > 0)
{ {
if (card.GetData().HasType(CardType.Link)) if (card.GetData().HasType(CardType.Link))
...@@ -1315,6 +1322,9 @@ namespace MDPro3.Duel ...@@ -1315,6 +1322,9 @@ namespace MDPro3.Duel
else else
attackedPosition = attackedCard.model.transform.position; attackedPosition = attackedCard.model.transform.position;
if (directAttack != 0)
duelBGManager.OnDirectAttack(from.InMyControl() ? 0 : 1);
var isFinalAttack = duelBGManager.IsFinalBlow(); var isFinalAttack = duelBGManager.IsFinalBlow();
duelBGManager.HideAttackLine(); duelBGManager.HideAttackLine();
duelBGManager.HideDuelFinalBlowText(); duelBGManager.HideDuelFinalBlowText();
...@@ -1516,7 +1526,12 @@ namespace MDPro3.Duel ...@@ -1516,7 +1526,12 @@ namespace MDPro3.Duel
if(life0 <= 0 || life1 <= 0) if(life0 <= 0 || life1 <= 0)
duelBGManager.FinishDamageEffect(); duelBGManager.FinishDamageEffect();
if (currentMessage == GameMessage.Damage)
duelBGManager.OnPlayerDamaged(player, Mathf.Max(value, 0));
duelBGManager.UpdateBgEffects(player); duelBGManager.UpdateBgEffects(player);
duelBGManager.OnLifePointsChanged(0, life0);
duelBGManager.OnLifePointsChanged(1, life1);
AudioManager.PlaySE("SE_COST_DAMAGE"); AudioManager.PlaySE("SE_COST_DAMAGE");
Core.SetLP(player, -value); Core.SetLP(player, -value);
await UniTask.WaitForSeconds(0.5f); await UniTask.WaitForSeconds(0.5f);
...@@ -1543,6 +1558,8 @@ namespace MDPro3.Duel ...@@ -1543,6 +1558,8 @@ namespace MDPro3.Duel
ES_hint = InterString.Get("对方生命值回复时"); ES_hint = InterString.Get("对方生命值回复时");
} }
duelBGManager.OnLifePointsChanged(0, life0);
duelBGManager.OnLifePointsChanged(1, life1);
Core.SetLP(player, value); Core.SetLP(player, value);
await UniTask.WaitForSeconds(0.5f); await UniTask.WaitForSeconds(0.5f);
} }
...@@ -1568,6 +1585,10 @@ namespace MDPro3.Duel ...@@ -1568,6 +1585,10 @@ namespace MDPro3.Duel
duelBGManager.FinishDamageEffect(); duelBGManager.FinishDamageEffect();
duelBGManager.UpdateBgEffects(player); duelBGManager.UpdateBgEffects(player);
if (diff < 0)
duelBGManager.OnPlayerDamaged(player, -diff);
duelBGManager.OnLifePointsChanged(0, life0);
duelBGManager.OnLifePointsChanged(1, life1);
if(diff < 0) if(diff < 0)
AudioManager.PlaySE("SE_COST_DAMAGE"); AudioManager.PlaySE("SE_COST_DAMAGE");
Core.SetLP(player, diff); Core.SetLP(player, diff);
...@@ -1947,6 +1968,7 @@ namespace MDPro3.Duel ...@@ -1947,6 +1968,7 @@ namespace MDPro3.Duel
opSpSummonCount = 0; opSpSummonCount = 0;
turns++; turns++;
myTurn = isFirst ? (turns % 2 != 0) : (turns % 2 == 0); myTurn = isFirst ? (turns % 2 != 0) : (turns % 2 == 0);
duelBGManager.OnNewTurn(myTurn, turns);
PhaseButtonHandler.TurnChange(myTurn, turns); PhaseButtonHandler.TurnChange(myTurn, turns);
PhaseButtonHandler.SetTextMain(string.Empty); PhaseButtonHandler.SetTextMain(string.Empty);
...@@ -1997,6 +2019,7 @@ namespace MDPro3.Duel ...@@ -1997,6 +2019,7 @@ namespace MDPro3.Duel
else if (duelPhase == DuelPhase.End) else if (duelPhase == DuelPhase.End)
PhaseButtonHandler.SetTextMain("End"); PhaseButtonHandler.SetTextMain("End");
duelBGManager.OnNewPhase(player, duelPhase);
await duelBGManager.ShowPhaseBanner(player, duelPhase); await duelBGManager.ShowPhaseBanner(player, duelPhase);
} }
...@@ -2296,7 +2319,10 @@ namespace MDPro3.Duel ...@@ -2296,7 +2319,10 @@ namespace MDPro3.Duel
if (currentMessage == GameMessage.CardTarget) if (currentMessage == GameMessage.CardTarget)
cardFrom.AddTarget(cardTo); cardFrom.AddTarget(cardTo);
else if (currentMessage == GameMessage.Equip) else if (currentMessage == GameMessage.Equip)
{
cardFrom.equipedCard = cardTo; cardFrom.equipedCard = cardTo;
duelBGManager.OnEquipApplied(from.InMyControl() ? 0 : 1);
}
return UniTask.CompletedTask; return UniTask.CompletedTask;
} }
......
This diff is collapsed.
...@@ -55,7 +55,23 @@ namespace MDPro3 ...@@ -55,7 +55,23 @@ namespace MDPro3
Animator[] animators = animationContainer.GetComponentsInChildren<Animator>(); Animator[] animators = animationContainer.GetComponentsInChildren<Animator>();
foreach (Animator animator in animators) foreach (Animator animator in animators)
{ {
animator.SetTrigger(animationName); if (animator == null || string.IsNullOrEmpty(animationName))
continue;
var hasTrigger = false;
var parameters = animator.parameters;
for (var i = 0; i < parameters.Length; i++)
{
var param = parameters[i];
if (param.type == AnimatorControllerParameterType.Trigger && param.name == animationName)
{
hasTrigger = true;
break;
}
}
if (hasTrigger)
animator.SetTrigger(animationName);
} }
} }
...@@ -224,7 +240,7 @@ namespace MDPro3 ...@@ -224,7 +240,7 @@ namespace MDPro3
} }
else else
{ {
UnityEngine.Debug.LogErrorFormat($"Image [{0}]: {1}", url, request.error); UnityEngine.Debug.LogErrorFormat("Image [{0}]: {1}", url, request.error);
return null; return null;
} }
} }
...@@ -384,4 +400,4 @@ namespace MDPro3 ...@@ -384,4 +400,4 @@ namespace MDPro3
#endregion #endregion
} }
} }
\ No newline at end of file
...@@ -69,23 +69,36 @@ namespace MDPro3 ...@@ -69,23 +69,36 @@ namespace MDPro3
} }
AssetBundle ab = await AssetBundle.LoadFromFileAsync(Program.root + path); AssetBundle ab = await AssetBundle.LoadFromFileAsync(Program.root + path);
var assets = ab.LoadAllAssets(); var expectedName = Path.GetFileName(path);
if (!string.IsNullOrEmpty(expectedName))
{
var assetRequest = ab.LoadAssetAsync<GameObject>(expectedName);
await assetRequest;
returnValue = assetRequest.asset as GameObject;
}
foreach (UnityEngine.Object asset in assets) if (returnValue == null)
{ {
if (typeof(GameObject).IsInstanceOfType(asset)) var assets = ab.LoadAllAssets();
foreach (UnityEngine.Object asset in assets)
{ {
if (cache) if (!typeof(GameObject).IsInstanceOfType(asset))
{ continue;
if (!cachedAB.TryAdd(path, asset as GameObject))
Debug.LogWarning($"Failed to cache {path}"); var candidate = asset as GameObject;
} returnValue = candidate;
returnValue = asset as GameObject; if (candidate != null && candidate.name == expectedName)
//break; break;
} }
} }
ab.Unload(false); ab.Unload(false);
if (cache && returnValue != null)
{
if (!cachedAB.TryAdd(path, returnValue))
Debug.LogWarning($"Failed to cache {path}");
}
if (instantiate && returnValue != null) if (instantiate && returnValue != null)
return UnityEngine.Object.Instantiate(returnValue); return UnityEngine.Object.Instantiate(returnValue);
else else
...@@ -590,4 +603,4 @@ namespace MDPro3 ...@@ -590,4 +603,4 @@ namespace MDPro3
#endregion #endregion
} }
} }
\ No newline at end of file
...@@ -100,7 +100,8 @@ namespace MDPro3 ...@@ -100,7 +100,8 @@ namespace MDPro3
public List<Item> wallpapers; // 113 public List<Item> wallpapers; // 113
public List<List<Item>> kinds; public List<List<Item>> kinds;
private const string ADDRESS_DEFAULT_DECK_CASE = "DeckCase0001_L"; private const int CODE_DEFAULT_DECK_CASE = 1080001;
private const string ADDRESS_DEFAULT_DECK_CASE_LEGACY = "DeckCase0001_L";
public const string STRING_NULL = "coming soon"; public const string STRING_NULL = "coming soon";
public const int CODE_NONE = 0; public const int CODE_NONE = 0;
...@@ -627,15 +628,35 @@ namespace MDPro3 ...@@ -627,15 +628,35 @@ namespace MDPro3
} }
public async UniTask<Sprite> LoadDeckCaseIconAsync(int code, string suffix) public async UniTask<Sprite> LoadDeckCaseIconAsync(int code, string suffix)
{
var sprite = await TryLoadAddressableSprite(GetDeckCaseAddress(code, suffix));
if (sprite != null)
return sprite;
sprite = await TryLoadAddressableSprite(GetDeckCaseAddress(CODE_DEFAULT_DECK_CASE, suffix));
if (sprite != null)
return sprite;
return await TryLoadAddressableSprite(ADDRESS_DEFAULT_DECK_CASE_LEGACY);
}
private static string GetDeckCaseAddress(int code, string suffix)
{
if (code < 1080000 || code > 1089999)
code = CODE_DEFAULT_DECK_CASE;
return $"DeckCase{code.ToString()[3..]}{suffix ?? string.Empty}";
}
private async UniTask<Sprite> TryLoadAddressableSprite(string address)
{ {
try try
{ {
return await LoadAddressableSprite($"DeckCase{code.ToString()[3..]}{suffix}"); return await LoadAddressableSprite(address);
} }
catch catch
{ {
Debug.LogError("Addressables Not Found: " + $"DeckCase {code}_{suffix}"); return null;
return await LoadAddressableSprite(ADDRESS_DEFAULT_DECK_CASE);
} }
} }
......
using UnityEngine; using UnityEngine;
using System;
namespace MDPro3.UI namespace MDPro3.UI
{ {
public class EventSEPlayer : MonoBehaviour public class EventSEPlayer : MonoBehaviour
{ {
public static float LastEventTime { get; private set; } = float.NegativeInfinity;
public static string LastEventLabel { get; private set; } = string.Empty;
void PlayAnimationEventSe(string se) void PlayAnimationEventSe(string se)
{ {
RegisterEvent(se);
AudioManager.PlaySE(se, 0.4f); AudioManager.PlaySE(se, 0.4f);
} }
void NewEvent(string se) void NewEvent(string se)
{ {
RegisterEvent(se);
AudioManager.PlaySE(se, 0.4f); AudioManager.PlaySE(se, 0.4f);
} }
public static bool HasRecentEvent(string expectedPrefix, float sinceTime)
{
if (LastEventTime < sinceTime)
return false;
if (string.IsNullOrEmpty(expectedPrefix))
return true;
return !string.IsNullOrEmpty(LastEventLabel)
&& LastEventLabel.StartsWith(expectedPrefix, StringComparison.OrdinalIgnoreCase);
}
private static void RegisterEvent(string se)
{
LastEventTime = Time.unscaledTime;
LastEventLabel = se ?? string.Empty;
}
} }
} }
...@@ -10,6 +10,7 @@ using MDPro3.Servant; ...@@ -10,6 +10,7 @@ using MDPro3.Servant;
using MDPro3.UI.ServantUI; using MDPro3.UI.ServantUI;
using MDPro3.Utility; using MDPro3.Utility;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
using MDPro3.Duel;
namespace MDPro3.UI namespace MDPro3.UI
{ {
...@@ -28,6 +29,7 @@ namespace MDPro3.UI ...@@ -28,6 +29,7 @@ namespace MDPro3.UI
m_Protector = m_Protector != null ? m_Protector m_Protector = m_Protector != null ? m_Protector
: Manager.GetElement<RawImage>(LABEL_RIMG_PROTECTOR); : Manager.GetElement<RawImage>(LABEL_RIMG_PROTECTOR);
private const string LABEL_IMG_WALLPAPER_BG = "WallpaperBG"; private const string LABEL_IMG_WALLPAPER_BG = "WallpaperBG";
private Image m_WallpaperBG; private Image m_WallpaperBG;
private Image WallpaperBG => private Image WallpaperBG =>
...@@ -52,6 +54,11 @@ namespace MDPro3.UI ...@@ -52,6 +54,11 @@ namespace MDPro3.UI
private Coroutine refreshCoroutine; private Coroutine refreshCoroutine;
private Coroutine hideCoroutine; private Coroutine hideCoroutine;
private Image premiumOverlayIcon;
private Coroutine premiumCrossfadeCoroutine;
private const float CrossfadeHoldSeconds = 2.0f;
private const float CrossfadeFadeSeconds = 0.6f;
protected override void Awake() protected override void Awake()
{ {
base.Awake(); base.Awake();
...@@ -131,6 +138,7 @@ namespace MDPro3.UI ...@@ -131,6 +138,7 @@ namespace MDPro3.UI
Icon.material = Appearance.matForFace; Icon.material = Appearance.matForFace;
loaded = true; loaded = true;
StartPremiumCrossfade();
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
...@@ -208,9 +216,10 @@ namespace MDPro3.UI ...@@ -208,9 +216,10 @@ namespace MDPro3.UI
} }
else else
{ {
if (DeckEditor.Deck.Mate != itemID) var normalizedMateId = PremiumMateRules.GetBaseMateId(itemID);
if (DeckEditor.Deck.Mate != normalizedMateId)
{ {
DeckEditor.Deck.Mate = itemID; DeckEditor.Deck.Mate = normalizedMateId;
Program.instance.deckEditor.GetUI<DeckEditorUI>().DeckView.SetDirty(true); Program.instance.deckEditor.GetUI<DeckEditorUI>().DeckView.SetDirty(true);
Program.instance.deckEditor.GetUI<DeckEditorUI>().IconMate.sprite = Icon.sprite; Program.instance.deckEditor.GetUI<DeckEditorUI>().IconMate.sprite = Icon.sprite;
} }
...@@ -220,6 +229,9 @@ namespace MDPro3.UI ...@@ -220,6 +229,9 @@ namespace MDPro3.UI
{ {
if (AppearanceUI.currentContent == "Wallpaper") if (AppearanceUI.currentContent == "Wallpaper")
Config.Set("Wallpaper", itemID.ToString()); Config.Set("Wallpaper", itemID.ToString());
else if (AppearanceUI.currentContent == "Mate")
Config.Set(Appearance.condition.ToString() + AppearanceUI.currentContent + Appearance.player,
PremiumMateRules.GetBaseMateId(itemID).ToString());
else else
Config.Set(Appearance.condition.ToString() + AppearanceUI.currentContent + Appearance.player, itemID.ToString()); Config.Set(Appearance.condition.ToString() + AppearanceUI.currentContent + Appearance.player, itemID.ToString());
...@@ -384,6 +396,7 @@ namespace MDPro3.UI ...@@ -384,6 +396,7 @@ namespace MDPro3.UI
if (hideCoroutine != null || !gameObject.activeSelf) if (hideCoroutine != null || !gameObject.activeSelf)
return; return;
hideCoroutine = StartCoroutine(HideAsync()); hideCoroutine = StartCoroutine(HideAsync());
StopPremiumCrossfade();
GetComponent<LayoutElement>().ignoreLayout = true; GetComponent<LayoutElement>().ignoreLayout = true;
GetComponent<RectTransform>().anchoredPosition = Vector2.zero; GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
...@@ -412,10 +425,13 @@ namespace MDPro3.UI ...@@ -412,10 +425,13 @@ namespace MDPro3.UI
GetComponent<LayoutElement>().ignoreLayout = false; GetComponent<LayoutElement>().ignoreLayout = false;
transform.SetSiblingIndex(index); transform.SetSiblingIndex(index);
StartPremiumCrossfade();
} }
public void Dispose() public void Dispose()
{ {
StopPremiumCrossfade();
if(refreshCoroutine != null) if(refreshCoroutine != null)
StopCoroutine(refreshCoroutine); StopCoroutine(refreshCoroutine);
...@@ -424,5 +440,150 @@ namespace MDPro3.UI ...@@ -424,5 +440,150 @@ namespace MDPro3.UI
Destroy(gameObject); Destroy(gameObject);
} }
#region Premium Mate Crossfade
private void StartPremiumCrossfade()
{
StopPremiumCrossfade();
if (!loaded)
return;
if (AppearanceUI.currentContent != "Mate")
return;
if (!PremiumMateRules.IsPremiumBaseId(itemID))
return;
if (Icon == null || !Icon.gameObject.activeSelf)
return;
premiumCrossfadeCoroutine = StartCoroutine(PremiumCrossfadeAsync());
}
private void StopPremiumCrossfade()
{
if (premiumCrossfadeCoroutine != null)
{
StopCoroutine(premiumCrossfadeCoroutine);
premiumCrossfadeCoroutine = null;
}
if (premiumOverlayIcon != null)
{
Destroy(premiumOverlayIcon.gameObject);
premiumOverlayIcon = null;
}
if (Icon != null)
{
var c = Icon.color;
c.a = 1f;
Icon.color = c;
}
}
private Image CreateOverlayIcon()
{
var overlayGo = new GameObject("PremiumOverlay");
overlayGo.transform.SetParent(Icon.transform.parent, false);
overlayGo.transform.SetSiblingIndex(Icon.transform.GetSiblingIndex() + 1);
var overlayImg = overlayGo.AddComponent<Image>();
overlayImg.raycastTarget = false;
overlayImg.preserveAspect = Icon.preserveAspect;
overlayImg.type = Icon.type;
overlayImg.maskable = Icon.maskable;
var overlayRt = overlayImg.rectTransform;
var iconRt = Icon.rectTransform;
overlayRt.anchorMin = iconRt.anchorMin;
overlayRt.anchorMax = iconRt.anchorMax;
overlayRt.pivot = iconRt.pivot;
overlayRt.anchoredPosition = iconRt.anchoredPosition;
overlayRt.sizeDelta = iconRt.sizeDelta;
overlayRt.localScale = iconRt.localScale;
overlayRt.localRotation = iconRt.localRotation;
var c = Color.white;
c.a = 0f;
overlayImg.color = c;
return overlayImg;
}
private IEnumerator PremiumCrossfadeAsync()
{
if (!PremiumMateRules.TryGetRuleByBaseId(itemID, out var rule))
yield break;
Sprite subSprite = null;
foreach (var variantId in rule.VariantIds)
{
var task = Program.items.LoadItemIconAsync(variantId.ToString(), Items.ItemType.Mate);
while (task.Status == UniTaskStatus.Pending)
yield return null;
try
{
subSprite = task.GetAwaiter().GetResult();
if (subSprite != null)
break;
}
catch
{
// Icon not available for this variant, try next
}
}
if (subSprite == null || this == null || Icon == null)
yield break;
premiumOverlayIcon = CreateOverlayIcon();
premiumOverlayIcon.sprite = subSprite;
// Icon shows base (alpha=1), overlay shows sub (alpha=0) initially.
// Crossfade loop: hold → fade overlay in → hold → fade overlay out → repeat.
while (true)
{
// Hold on base icon
yield return new WaitForSecondsRealtime(CrossfadeHoldSeconds);
// Fade in overlay (base → sub)
yield return FadeOverlay(0f, 1f, CrossfadeFadeSeconds);
// Hold on sub icon
yield return new WaitForSecondsRealtime(CrossfadeHoldSeconds);
// Fade out overlay (sub → base)
yield return FadeOverlay(1f, 0f, CrossfadeFadeSeconds);
}
}
private IEnumerator FadeOverlay(float fromAlpha, float toAlpha, float duration)
{
if (premiumOverlayIcon == null)
yield break;
var elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.unscaledDeltaTime;
var t = Mathf.Clamp01(elapsed / duration);
t = t * t * (3f - 2f * t); // smoothstep
var alpha = Mathf.Lerp(fromAlpha, toAlpha, t);
if (premiumOverlayIcon != null)
{
var c = premiumOverlayIcon.color;
c.a = alpha;
premiumOverlayIcon.color = c;
}
yield return null;
}
if (premiumOverlayIcon != null)
{
var c = premiumOverlayIcon.color;
c.a = toAlpha;
premiumOverlayIcon.color = c;
}
}
#endregion
} }
} }
...@@ -8,6 +8,7 @@ using UnityEngine.EventSystems; ...@@ -8,6 +8,7 @@ using UnityEngine.EventSystems;
using UnityEngine.UI; using UnityEngine.UI;
using static MDPro3.Servant.Appearance; using static MDPro3.Servant.Appearance;
using static YgomGame.Duel.BattleAimingEffect; using static YgomGame.Duel.BattleAimingEffect;
using MDPro3.Duel;
namespace MDPro3.UI.ServantUI namespace MDPro3.UI.ServantUI
{ {
...@@ -390,6 +391,8 @@ namespace MDPro3.UI.ServantUI ...@@ -390,6 +391,8 @@ namespace MDPro3.UI.ServantUI
int itemCount = 0; int itemCount = 0;
foreach (var itemInfo in targetItems) foreach (var itemInfo in targetItems)
{ {
if (currentContent == "Mate" && PremiumMateRules.IsPremiumVariantId(itemInfo.id))
continue;
if (itemInfo.notReady) continue; if (itemInfo.notReady) continue;
GameObject item = Instantiate(Template); GameObject item = Instantiate(Template);
...@@ -520,44 +523,68 @@ namespace MDPro3.UI.ServantUI ...@@ -520,44 +523,68 @@ namespace MDPro3.UI.ServantUI
foreach (var item in currentList) foreach (var item in currentList)
{ {
var itemMono = item.GetComponent<SelectionToggle_AppearanceItem>();
if (currentContent == "Mate" && PremiumMateRules.IsPremiumVariantId(itemMono.itemID))
{
itemMono.Hide();
continue;
}
if (player.Contains("0") && onlyOpSideShowItems.Contains(item)) if (player.Contains("0") && onlyOpSideShowItems.Contains(item))
item.GetComponent<SelectionToggle_AppearanceItem>().Hide(); itemMono.Hide();
else else
item.GetComponent<SelectionToggle_AppearanceItem>().Show(); itemMono.Show();
} }
foreach (var item in currentList) foreach (var item in currentList)
{ {
var itemMono = item.GetComponent<SelectionToggle_AppearanceItem>();
if (currentContent == "Wallpaper") if (currentContent == "Wallpaper")
{ {
if (item.GetComponent<SelectionToggle_AppearanceItem>().itemID.ToString() == Config.Get("Wallpaper", targetItems[0].id.ToString())) if (itemMono.itemID.ToString() == Config.Get("Wallpaper", targetItems[0].id.ToString()))
{ {
item.GetComponent<SelectionToggle_AppearanceItem>().SetToggleOn(); itemMono.SetToggleOn();
break; break;
} }
} }
else else
{ {
var itemID = item.GetComponent<SelectionToggle_AppearanceItem>().itemID; var itemID = itemMono.itemID;
if (currentContent == "Mate" && PremiumMateRules.IsPremiumVariantId(itemID))
continue;
if (condition == Condition.DeckEditor) if (condition == Condition.DeckEditor)
{ {
if (itemID == DeckEditor.Deck.Case if (currentContent == "Mate")
{
var selectedMate = PremiumMateRules.GetBaseMateId(DeckEditor.Deck.Mate);
if (itemID == selectedMate)
{
itemMono.SetToggleOn();
break;
}
}
else if (itemID == DeckEditor.Deck.Case
|| itemID == DeckEditor.Deck.Protector || itemID == DeckEditor.Deck.Protector
|| itemID == DeckEditor.Deck.Field || itemID == DeckEditor.Deck.Field
|| itemID == DeckEditor.Deck.Grave || itemID == DeckEditor.Deck.Grave
|| itemID == DeckEditor.Deck.Stand || itemID == DeckEditor.Deck.Stand
|| itemID == DeckEditor.Deck.Mate) || itemID == DeckEditor.Deck.Mate)
{ {
item.GetComponent<SelectionToggle_AppearanceItem>().SetToggleOn(); itemMono.SetToggleOn();
break; break;
} }
} }
else else
{ {
if (itemID.ToString() == Config.Get(condition.ToString() + currentContent + player, targetItems[0].id.ToString())) var selectedCode = Config.Get(condition.ToString() + currentContent + player, targetItems[0].id.ToString());
if (currentContent == "Mate" && int.TryParse(selectedCode, out var selectedMateCode))
selectedCode = PremiumMateRules.GetBaseMateId(selectedMateCode).ToString();
if (itemID.ToString() == selectedCode)
{ {
item.GetComponent<SelectionToggle_AppearanceItem>().SetToggleOn(); itemMono.SetToggleOn();
break; break;
} }
} }
...@@ -618,4 +645,4 @@ namespace MDPro3.UI.ServantUI ...@@ -618,4 +645,4 @@ namespace MDPro3.UI.ServantUI
} }
} }
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment