using Cal; using Cal.DataTable; using MongoDB.Driver; using MongoDB.Driver.Core.Servers; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ET { public class BagAwakeSystem : AwakeSystem { public override void Awake(Bag self) { self.InitBag(); self.getAttributeFunc = self.GetAttribute; } } public class BagDeserializeSystem : DeserializeSystem { public override void Deserialize(Bag self) { self.getAttributeFunc = self.GetAttribute; } } public class BagDestroySystem : DestroySystem { public override void Destroy(Bag self) { self.ItemCount = 0; self.ItemDic.Clear(); self.WornEquipDic.Clear(); self.getAttributeFunc = null; } } public static class BagSystem { /// /// 初始化背包,创建人物时使用一次 /// // by 左倾月 on 2020/6/29 at 10:28 /// /// public static void InitBag(this Bag self) { self.ItemDic.Clear(); for (int i = 0; i < self.MaxItemCount; i++) { self.ItemDic.Add(i, 0, Item.Empty(i)); } self.WornEquipDic.Clear(); for (int i = 0; i < self.MaxWornEquipCount; i++) { self.WornEquipDic.Add(i, Item.Empty(i)); } self.ItemCount = 0; } public static bool CanAddNewItem(this Bag self) { return self.ItemCount < self.MaxItemCount; } public static void CheckSlot(this Bag self) { if (self.ItemDic.Count == self.MaxItemCount) { return; } self.ItemCount = 0; for (int i = 0; i < self.MaxItemCount; i++) { if (!self.ItemDic.TryGetValueByKey1(i, out Item item)) self.ItemDic.Add(i, 0, Item.Empty(i)); else { if (item.ItemId != 0) self.ItemCount++; } } } public static float GetAttribute(this Bag self, AttributeType attributeType) { float bounds = 0f; foreach (Item item in self.WornEquipDic.Values) { if (item.IsEmpty) continue; EquipItem equipItem = item.data.As(); bounds += equipItem.GetSpecialAttribute(attributeType); bounds += equipItem.GetMainAttribute(attributeType); bounds += equipItem.GetAdditionalAttribute(attributeType); bounds += equipItem.GetRandomAttribute(attributeType); bounds += equipItem.GetGemAttribute(attributeType); // bounds += equipItem.GetStarSoulAttribute(self,attributeType); } foreach (int suitId in self.suitAttributes) { SuitConfig suitConfig = SuitConfigCategory.Instance.Get(suitId); if (suitConfig == null) { Log.Error($"suitConfig is null where id = {suitId}"); continue; } foreach (SuitConfig.Suit suit in suitConfig.SuitArr) { if (suit.Key == (int)attributeType) { bounds += suit.Value; } } } return bounds; } /// /// 添加物品 /// // by 左倾月 on 2020/6/29 at 10:26 /// /// /// /// public static int AddItem(this Bag self, Item item) { if (item.ItemType != ItemType.EquipItem) { //!判断是否可以堆叠 return CalucateStacking(self, item); } if (self.CanAddNewItem()) { if (self.ItemDic.TryGetValueByKey2(0, out List nullList)) { Item nullItem = nullList[0]; int nullItemindex = nullItem.index; self.ItemDic.Remove(nullItemindex, 0, nullItem); item.index = nullItemindex; self.ItemDic.Add(nullItemindex, item.ItemId, item); self.ItemCount++; return 1; } } return 0; //!可堆叠物品逻辑 static int CalucateStacking(Bag self, Item item) { int itemId = item.ItemId; int count = item.Count; int maxCount = item.ItemType switch { ItemType.GoodsItem => DataTableHelper.Get(itemId).MaxAmount, ItemType.MaterialsItem => DataTableHelper.Get(itemId).MaxAmount, _ => throw new InvalidCastException($"物品类型错误,type= {item.ItemType}"), }; if (self.ItemDic.TryGetValueByKey2(itemId, out List list)) { CalucateCount(); } int whileCount = 50; while (count > 0) { if (self.ItemCount + 1 > self.MaxItemCount) { return item.Count - count; } if (self.ItemDic.TryGetValueByKey2(0, out List nullList)) { Item nullItem = nullList[0]; int nullItemIndex = nullItem.index; int nullItemId = 0; self.ItemDic.Remove(nullItemIndex, nullItemId, nullItem); self.ItemDic.Add(nullItemIndex, itemId, new Item(nullItemIndex, item.data, 0)); self.ItemCount++; } if (self.ItemDic.TryGetValueByKey2(itemId, out list)) { CalucateCount(); } if (whileCount-- <= 0) break; } return item.Count; //!计算堆叠后剩余数量 void CalucateCount() { foreach (Item bagItem in list) { if (bagItem.IsLock == item.IsLock && bagItem.Count < maxCount) { int oldCount = bagItem.Count; bagItem.Count += count; if (bagItem.Count > maxCount) { int dCount = bagItem.Count - maxCount; bagItem.Count -= dCount; count -= maxCount - oldCount; } else { count -= bagItem.Count - oldCount; break; } } else { continue; } } } } } /// /// 判断能否增加道具和材料 /// /// /// /// /// public static bool CanAddItem(this Bag self, int itemId, int count) { if (!self.ItemDic.TryGetValueByKey2(itemId, out List list)) { return self.CanAddNewItem(); } int maxCount = BagHelper.GetItemBase(itemId) switch { GoodsBase goodsBase => goodsBase.MaxAmount, MaterialBase materialBase => materialBase.MaxAmount, _ => throw new InvalidCastException($"物品类型错误,id= {itemId}"), }; foreach (Item item in list) { count = count + item.Count - maxCount; if (count <= 0) return true; } if (count <= 0) return true; if (!self.ItemDic.TryGetValueByKey2(0, out List nullItemList)) { return false; } foreach (Item item in nullItemList) { count -= maxCount; if (count <= 0) return true; } return false; } public static int AddItemNeedSlot(this Bag self, int itemId, int count, int maxCount) { if (!self.ItemDic.TryGetValueByKey2(itemId, out List list)) { return GetNewStackItemNeedSlotCount(maxCount, count); } foreach (Item item in list) { count = count + item.Count - maxCount; if (count > 0) return GetNewStackItemNeedSlotCount(maxCount, count); } if (count > 0) return GetNewStackItemNeedSlotCount(maxCount, count); return 0; static int GetNewStackItemNeedSlotCount(int maxStack, int count) { if (count % maxStack == 0) return count / maxStack; return count / maxStack + 1; } } /// /// 删除物品 /// // by 左倾月 on 2020/6/29 at 10:27 /// /// /// /// /// public static Item DeleteItem(this Bag self, int index, int count) { if (self.ItemDic.TryGetValueByKey1(index, out Item item)) { if (!item.IsEmpty) { if (item.Count > count) { item.Count -= count; } else if (item.Count == count) { self.ItemDic.Remove(index, item.ItemId, item); self.ItemDic.Add(index, 0, Item.Empty(index)); self.ItemCount--; } else { return null; } return item; } } return null; } public struct DeleteItemInfo { public int itemId; public int count; public ItemType itemType; } /// /// 删除多个物品 /// // by 左倾月 on 2020/8/11 at 11:43 /// /// /// /// /// public static Item DeleteMultiItem(this Bag self, int itemId, int count, bool needUnload = false) { if (!self.ItemDic.TryGetValueByKey2(itemId, out List itemList) || itemList.Count == 0) { return null; } Item retItem = null; for (int i = itemList.Count - 1; i >= 0; i--) { Item item = itemList[i]; if (needUnload && item.IsLock) continue; if (item.IsEmpty) { continue; } if (item.Count > count) { item.Count -= count; break; } else if (item.Count == count) { self.ItemDic.Remove(item.index, item.ItemId, item); self.ItemDic.Add(item.index, 0, Item.Empty(item.index)); self.ItemCount--; break; } else { count -= item.Count; self.ItemDic.Remove(item.index, item.ItemId, item); self.ItemDic.Add(item.index, 0, Item.Empty(item.index)); self.ItemCount--; } retItem = item; } return retItem; } /// /// 交换位置或者堆叠物品 /// // by 左倾月 on 2020/6/29 at 10:28 /// /// /// /// /// public static string ChangePos(this Bag self, int index1, int index2) { if (index1 == index2) return "未换位"; if (!self.ItemDic.TryGetValueByKey1(index1, out Item item1)) { return "Bag系统错误,未找到相应背包位置的物品"; } if (!self.ItemDic.TryGetValueByKey1(index2, out Item item2)) { return "Bag系统错误,未找到相应背包位置的物品"; } //!一定会走这。除非网络信息有误 if (item1.IsEmpty) { Log.Error($"玩家Id=【{self.Parent.Id}】 Name=【{UserComponent.Instance.Get(self.Parent.Id).NickName}】 不应该出现的错误,背包中拖到了空格子"); return "系统错误,拖到了空格子"; } //!+叠加 if (!item2.IsEmpty && item1.IsLock == item2.IsLock && item1.ItemId == item2.ItemId) { int maxCount = 0; switch (item1.ItemType) { case ItemType.GoodsItem: GoodsBase goodsBase = DataTableHelper.Get(item1.ItemId); maxCount = goodsBase.MaxAmount; break; case ItemType.MaterialsItem: MaterialBase materialBase = DataTableHelper.Get(item1.ItemId); maxCount = materialBase.MaxAmount; break; case ItemType.EquipItem: return "装备不能叠加!"; default: break; } int dCount = maxCount - item2.Count; if (dCount > item1.Count) { item2.Count += item1.Count; self.ItemDic.Remove(item1.index, item1.ItemId, item1); self.ItemDic.Add(item1.index, 0, Item.Empty(item1.index)); self.ItemCount--; } else if (dCount < item1.Count) { item2.Count += dCount; item1.Count -= dCount; } else { item2.Count += dCount; self.ItemDic.Remove(item1.index, item1.ItemId, item1); self.ItemDic.Add(item1.index, 0, Item.Empty(item1.index)); self.ItemCount--; } return string.Empty; } //!+交换 return RealChangePos(); //!交换位置方法 string RealChangePos() { int item2Id = 0; if (!item2.IsEmpty) { item2Id = item2.ItemId; } int item1Id = item1.ItemId; self.ItemDic.Remove(index1, item1Id, item1); self.ItemDic.Remove(index2, item2Id, item2); ItemData data2 = item2.data; item2.data = item1.data; item1.data = data2; self.ItemDic.Add(index1, item2Id, item1); self.ItemDic.Add(index2, item1Id, item2); return string.Empty; } } /// /// 拆分物品 /// // by 左倾月 on 2020/6/29 at 10:28 /// /// /// /// /// public static string SplitItem(this Bag self, int index, int count) { if (!self.CanAddNewItem()) { return "背包已满,无法拆分,请清理背包后操作"; } if (self.ItemDic.TryGetValueByKey1(index, out Item item)) { if (count <= 0) { return "拆分数量应该大于0!"; } if (item.Count <= 1) { return "物品数量为小于2,无法拆分!"; } if (item.Count <= count) { return "拆分数量应该小于物品数量!"; } if (self.ItemDic.TryGetValueByKey2(0, out List nullList)) { Item nullItem = nullList[0]; int nullItemindex = nullItem.index; item.Count -= count; self.ItemDic.Remove(nullItemindex, 0, nullItem); self.ItemDic.Add(nullItemindex, item.ItemId, new Item(nullItemindex, item.data, count)); self.ItemCount++; return string.Empty; } } return "Bag系统错误,未找到相应背包位置的物品"; } /// /// 整理背包 /// // by 左倾月 on 2020/6/29 at 10:28 /// /// /// public static string SortBag(this Bag self) { long now = TimeHelper.ClientNow(); if (now - self.lastSortTime <= self.SortTimeInterval) { return $"请等待{(self.lastSortTime + self.SortTimeInterval - now) / 1000f:f0}s之后再整理"; } self.lastSortTime = now; List[] allList = self.ItemDic.GetAllByKey2().ToArray(); self.ItemDic.Clear(); int index = -1; foreach (List list in allList) { foreach (Item item in list) { //if (item.ItemId == 0) continue; if (item.IsEmpty) continue; ++index; item.index = index; self.ItemDic.Add(index, item.ItemId, item); } } while (++index < self.MaxItemCount) { self.ItemDic.Add(index, 0, Item.Empty(index)); } return string.Empty; } public static string CheckCanUse(this Bag self) { long now = TimeHelper.ClientNow(); if (now - self.lastUseTime <= Bag.UseTimeInterval) { return $"请等待{(self.lastUseTime + Bag.UseTimeInterval - now) / 1000f:f0}s之后再使用"; } self.lastUseTime = now; return null; } /// /// 穿戴装备 /// // by 左倾月 on 2020/6/29 at 10:30 /// /// /// /// public static string Puton(this Bag self, int index) { try { if (!self.ItemDic.TryGetValueByKey1(index, out Item equip)) { return "Bag系统错误,未找到相应背包位置的物品"; } if (equip.IsEmpty) return "空格子不能穿戴"; Unit unit = self.GetParent(); if (equip.ItemType != ItemType.EquipItem) { Log.Error($"【{ UserComponent.Instance.Get(unit.Id)?.NickName} ({ unit.Id})】想要穿戴非装备类物品!"); return "您只能穿戴装备或者形象!"; } //!+用装备类型做索引,也是字典的键 EquipBase equipBase = DataTableHelper.Get(equip.ItemId); User user = UserComponent.Instance.Get(unit.Id); if (equipBase.UseLevel > user.Level) { return "等级不足,无法穿戴"; } if (equipBase.JobId != 0 && equipBase.JobId != JobHelper.GetJobById(user.JobId)) { return "职业不符合,无法穿戴"; } int wornIndex = equipBase.Type; if (!self.WornEquipDic.TryGetValue(wornIndex, out Item wornItem)) { Log.Error($"【{ UserComponent.Instance.Get(unit.Id)?.NickName} ({ unit.Id})】 系统错误,{equipBase.Type}在字典中没有索引"); return "系统错误"; } //!+装备栏 空 if (wornItem.IsEmpty) { self.ItemDic.Remove(index, equip.ItemId, equip); self.ItemDic.Add(index, 0, Item.Empty(index)); self.ItemCount--; wornItem.index = wornIndex; wornItem.data = equip.data; wornItem.IsLock = true; } else { //!交换 self.ItemDic.Remove(index, equip.ItemId, equip); wornItem.IsLock = true; wornItem.index = index; equip.IsLock = true; equip.index = wornIndex; self.ItemDic.Add(index, wornItem.ItemId, wornItem); self.WornEquipDic[wornIndex] = equip; } //套装 if (self.IsSuit(wornItem.ItemId, true, out int oldSuitId)) { self.suitAttributes.Remove(oldSuitId); } if (self.IsSuit(equip.ItemId, true, out int suitId)) { self.suitAttributes.Add(suitId); } PutonSkin(unit, (EquipType)equipBase.Type, equip.ItemId); CharacterHelper.SyncNumeric(unit); } catch (Exception e) { Log.Error(e); } return string.Empty; } private static void PutonSkin(Unit unit, EquipType equipType, int itemId) { if (equipType == EquipType.形象) { SkinBase skinBase = DataTableHelper.Get(itemId); if (skinBase == null) { Log.Warning($"skinBase == null where ItemId = {itemId}"); return; } NumericComponent num = unit.GetComponent(); num.Set(NumericType.SkinId, skinBase.Id); } else if (equipType == EquipType.勋章) { NumericComponent num = unit.GetComponent(); num.Set(NumericType.Title, itemId); } } /// /// 卸下装备 /// // by 左倾月 on 2020/6/29 at 16:30 /// /// /// /// public static string Takeoff(this Bag self, int index) { try { if (!self.WornEquipDic.TryGetValue(index, out Item wornItem)) { return "Bag系统错误,未找到相应背包位置的物品"; } if (wornItem.IsEmpty) return "空物品不能卸下"; if (!self.CanAddNewItem()) { return "您的背包已满,无法卸下当前装备!"; } if (self.IsSuit(wornItem.ItemId, false, out int suitId)) { self.suitAttributes.Remove(suitId); } //!将卸下的装备置空 self.WornEquipDic[index] = Item.Empty(index); //!减属性 Unit unit = self.GetParent(); wornItem.IsLock = true; self.AddItem(wornItem); EquipBase equipBase = DataTableHelper.Get(wornItem.ItemId); EquipType equipType = (EquipType)equipBase.Type; if (equipType == EquipType.形象) { NumericComponent num = unit.GetComponent(); User user = UserComponent.Instance.Get(unit.Id); num.Set(NumericType.SkinId, user.JobId); } else if (equipType == EquipType.勋章) { NumericComponent num = unit.GetComponent(); num.Set(NumericType.Title, 0); } CharacterHelper.SyncNumeric(unit); } catch (Exception e) { Log.Error(e); } return string.Empty; } private static bool IsSuit(this Bag self, int itemId, bool isPuton, out int id) { id = 0; SortedDictionary.ValueCollection dic = self.WornEquipDic.Values; SuitConfig suitConfig = SuitConfigCategory.Instance.GetSuitConfigByEquipId(itemId); if (suitConfig == null) return false; User user = UserComponent.Instance.Get(self.Id); if (user == null) return false; int job = JobHelper.GetJobById(user.JobId); bool hasEquips = true; foreach (SuitConfig.Equip equip in suitConfig.EquipArr) { if (equip.Job == job) { foreach (int equipId in equip.EquipIdArr) { if (isPuton && equipId == itemId) { continue; } bool hasEquip = false; foreach (Item item in dic) { if (equipId == item.ItemId) { hasEquip = true; break; } } hasEquips = hasEquips && hasEquip; } break; } } id = (int)suitConfig.Id; return hasEquips; } public static string PutonStarSoulItem(this Bag self,EquipType equipType, long id,out long oldId) { oldId = 0; // if (!self.WornEquipDic.TryGetValue((int) equipType, out Item wornItem)) // { // Log.Error($"【{self.Id.GetPlayerFormatName()} ({ self.Id})】 系统错误,{equipType}在字典中没有索引"); // return "系统错误"; // } // // if (wornItem.IsEmpty) // { // return "先穿戴装备"; // } // // EquipItem data= wornItem.data.As(); // if (data.starSoulItemServerId != 0) // { // oldId = data.starSoulItemServerId; // } // data.starSoulItemServerId = id; return null; } } }