// Filename : CECShopBase.cs // Creator : Xu Wenbin // Date : 2013/12/11 // Converted to C#: 2024 using System; using System.Linq; using BrewMonster; namespace PerfectWorld.Scripts.Shop { // 封装 gshop 和 backshop 等的数据访问 / Encapsulates data access for gshop and backshop etc. public static class CECShopConstants { public const int CECSHOP_INVALID_PRICE = -1; public const int BUY_COUNT = 4; } public abstract class CECShopBase : CECObservable { private CECShopItemOwnerNPC m_ownerNPC = new CECShopItemOwnerNPC(0); // CECShopBase public void OnItemChange() { CECShopBaseChange change = new CECShopBaseChange((uint)CECShopBaseChange.ChangeMask.ITEM_CHANGED); NotifyObservers(change); } public bool ValidateTimeStamp() { return GetLocalTimeStamp() == GetServerTimeStamp(); } public void SetOwnerNPCID(uint ownerNPCID) { if (ownerNPCID == m_ownerNPC.GetOwnerNPCID()) { return; } m_ownerNPC.SetOwnerNPCID(ownerNPCID); OnItemChange(); } public uint GetOwnerNPCID() { return m_ownerNPC.GetOwnerNPCID(); } public bool HasOwnerNPC() { return !m_ownerNPC.IsEmpty(); } public CECShopItemOwnerNPC GetOwnerNPC() { return m_ownerNPC; } public bool MatchOwnerNPC(GShopItem rhs) { return m_ownerNPC.MatchItem(rhs); } public bool IsValid(int itemIndex, int buyIndex) { bool bValid = false; GShopItem? pItem = GetItem(itemIndex); if (pItem.HasValue) { if (buyIndex >= 0 && buyIndex < CECShopConstants.BUY_COUNT) { bValid = true; } } return bValid; } public bool ReadyToBuy(int itemIndex, int buyIndex) { bool result = false; int[] buyType = new int[CECShopConstants.BUY_COUNT]; if (IsValid(itemIndex, buyIndex) && CalcBuyType(itemIndex, buyType)) { for (int i = 0; i < CECShopConstants.BUY_COUNT; ++i) { if (buyType[i] == buyIndex) { result = true; break; } } } return result; } public bool CalcBuyType(int itemIndex, int[] buyTypes) { bool bOK = false; GShopItem? pItem = GetItem(itemIndex); if (pItem.HasValue) { GShopItem item = pItem.Value; int[] typeDefault = new int[CECShopConstants.BUY_COUNT]; int[] typeNew = new int[CECShopConstants.BUY_COUNT]; int index1 = 0; int index2 = 0; for (int i = 0; i < CECShopConstants.BUY_COUNT; i++) { typeDefault[i] = -1; typeNew[i] = -1; if (item.buy != null && i < item.buy.Length) { if (item.buy[i].type == 3 && item.buy[i].price > 0) { typeNew[index1] = i; index1++; } else if (item.buy[i].type == -1 && item.buy[i].price > 0) { typeDefault[index2] = i; index2++; } } } if (index1 > 0) { Array.Copy(typeNew, buyTypes, CECShopConstants.BUY_COUNT); bOK = true; } else if (index2 > 0) { Array.Copy(typeDefault, buyTypes, CECShopConstants.BUY_COUNT); bOK = true; } } return bOK; } public bool HasSameBuyType(int itemIndexA, int itemIndexB) { int[] typeA = new int[CECShopConstants.BUY_COUNT]; int[] typeB = new int[CECShopConstants.BUY_COUNT]; if (CalcBuyType(itemIndexA, typeA) && CalcBuyType(itemIndexB, typeB) && typeA.SequenceEqual(typeB)) { GShopItem? pItemA = GetItem(itemIndexA); GShopItem? pItemB = GetItem(itemIndexB); if (pItemA.HasValue && pItemB.HasValue) { GShopItem itemA = pItemA.Value; GShopItem itemB = pItemB.Value; for (int i = 0; i < CECShopConstants.BUY_COUNT; ++i) { int buyIndex = typeA[i]; if (buyIndex != -1) { bool priceAValid = (itemA.buy != null && buyIndex < itemA.buy.Length && itemA.buy[buyIndex].price != 0); bool priceBValid = (itemB.buy != null && buyIndex < itemB.buy.Length && itemB.buy[buyIndex].price != 0); if (priceAValid != priceBValid) { return false; } if (!priceAValid) { continue; } if (itemA.buy[buyIndex].time != itemB.buy[buyIndex].time) { return false; } } } return true; } } return false; } public bool CalcBuyIndex(int itemIndex, out int buyIndex, int cash = -1) { buyIndex = -1; bool bOK = false; GShopItem? pItem = GetItem(itemIndex); if (pItem.HasValue) { GShopItem item = pItem.Value; // 参考实现 CDlgQShopItem::SetItem / Reference implementation CDlgQShopItem::SetItem // 判断要显示的购买方式 / Determine which purchase method to display int[] m_TypeDefault = new int[CECShopConstants.BUY_COUNT]; int[] m_TypeNew = new int[CECShopConstants.BUY_COUNT]; int index1 = 0; int index2 = 0; for (int i = 0; i < CECShopConstants.BUY_COUNT; i++) { m_TypeDefault[i] = -1; m_TypeNew[i] = -1; if (item.buy != null && i < item.buy.Length) { if (item.buy[i].type == 3 && item.buy[i].price > 0) { m_TypeNew[index1] = i; index1++; } else if (item.buy[i].type == -1 && item.buy[i].price > 0) { m_TypeDefault[index2] = i; index2++; } } } int m_BuyType = -1; if (index1 > 0) { m_BuyType = 0; } else { m_BuyType = 1; } if (cash == -1) { cash = GetCash(); } for (int i = 0; i < CECShopConstants.BUY_COUNT; i++) { int BuyIndex = 0; if (m_BuyType == 0) { BuyIndex = m_TypeNew[i]; } else { BuyIndex = m_TypeDefault[i]; } if (BuyIndex != -1 && item.buy != null && BuyIndex < item.buy.Length) { uint price = item.buy[BuyIndex].price; if (price != 0 && price <= cash) { bOK = true; buyIndex = BuyIndex; break; } } } } return bOK; } public int GetPrice(int itemIndex, int buyIndex) { int price = CECShopConstants.CECSHOP_INVALID_PRICE; if (IsValid(itemIndex, buyIndex)) { GShopItem? pItem = GetItem(itemIndex); if (pItem.HasValue && pItem.Value.buy != null && buyIndex < pItem.Value.buy.Length) { price = (int)pItem.Value.buy[buyIndex].price; } } else { UnityEngine.Debug.Assert(false); } return price; } public uint GetStatus(int itemIndex, int buyIndex) { uint status = 0xFFFFFFFF; // -1 as uint if (IsValid(itemIndex, buyIndex)) { GShopItem? pItem = GetItem(itemIndex); if (pItem.HasValue && pItem.Value.buy != null && buyIndex < pItem.Value.buy.Length) { status = pItem.Value.buy[buyIndex].status; } } else { UnityEngine.Debug.Assert(false); } return status; } public static bool IsSame(GShopItem lhs, GShopItem rhs) { bool result = false; if (lhs.mainType != rhs.mainType || lhs.subType != rhs.subType || lhs.id != rhs.id || lhs.num != rhs.num || lhs.idGift != rhs.idGift || lhs.giftNum != rhs.giftNum) { return false; } result = true; if (lhs.buy != null && rhs.buy != null) { int buyCount = Math.Min(lhs.buy.Length, rhs.buy.Length); for (int i = 0; i < buyCount && i < CECShopConstants.BUY_COUNT; ++i) { if (lhs.buy[i].type != rhs.buy[i].type || lhs.buy[i].price != rhs.buy[i].price || lhs.buy[i].time != rhs.buy[i].time || lhs.buy[i].status != rhs.buy[i].status) { result = false; break; } } } return result; } public static int GetOriginalPrice(int finalPrice, uint discountStatus) { int result = finalPrice; if (discountStatus >= 4 && discountStatus <= 12) { float originalPrice = finalPrice * (10.0f / (discountStatus - 3)); if (CECUIConfig.Instance().GetGameUI().bEnableCeilPriceBeforeDiscountToGold) { result = (int)Math.Ceiling(originalPrice) + 99; result /= 100; result *= 100; } else { result = (int)Math.Ceiling(originalPrice); } } return result; } // Abstract methods public abstract bool GetFromServer(int beginIndex, int endIndex); public abstract uint GetLocalTimeStamp(); public abstract uint GetServerTimeStamp(); public abstract int GetCount(); public abstract GShopItem? GetItem(int index); public abstract int GetCash(); public abstract bool Buy(int itemIndex, int buyIndex); public abstract bool IsFashionShopEnabled(); public abstract CECShopItemCategory GetFashionShopCategory(); public abstract bool IsFashionShopFlashSaleEnabled(); public abstract string GetFashionShopFlashSaleTitle(); } }