CTT/Server/Hotfix/Game/System/Bag/BagSystem.cs

753 lines
28 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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<Bag>
{
public override void Awake(Bag self)
{
self.InitBag();
self.getAttributeFunc = self.GetAttribute;
}
}
public class BagDeserializeSystem : DeserializeSystem<Bag>
{
public override void Deserialize(Bag self)
{
self.getAttributeFunc = self.GetAttribute;
}
}
public class BagDestroySystem : DestroySystem<Bag>
{
public override void Destroy(Bag self)
{
self.ItemCount = 0;
self.ItemDic.Clear();
self.WornEquipDic.Clear();
self.getAttributeFunc = null;
}
}
public static class BagSystem
{
/// <summary>
/// 初始化背包,创建人物时使用一次
/// // by 左倾月 on 2020/6/29 at 10:28
/// </summary>
/// <param name="self"></param>
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<EquipItem>();
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;
}
/// <summary>
/// 添加物品
/// // by 左倾月 on 2020/6/29 at 10:26
/// </summary>
/// <param name="self"></param>
/// <param name="item"></param>
/// <returns></returns>
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<Item> 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<GoodsBase>(itemId).MaxAmount,
ItemType.MaterialsItem => DataTableHelper.Get<MaterialBase>(itemId).MaxAmount,
_ => throw new InvalidCastException($"物品类型错误type= {item.ItemType}"),
};
if (self.ItemDic.TryGetValueByKey2(itemId, out List<Item> 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<Item> 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;
}
}
}
}
}
/// <summary>
/// 判断能否增加道具和材料
/// </summary>
/// <param name="self"></param>
/// <param name="itemId"></param>
/// <param name="count"></param>
/// <returns></returns>
public static bool CanAddItem(this Bag self, int itemId, int count)
{
if (!self.ItemDic.TryGetValueByKey2(itemId, out List<Item> 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<Item> nullItemList))
{
return false;
}
count -= maxCount*nullItemList.Count;
return count <= 0;
}
public static int AddItemNeedSlot(this Bag self, int itemId, int count, int maxCount)
{
if (!self.ItemDic.TryGetValueByKey2(itemId, out List<Item> 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;
}
}
/// <summary>
/// 删除物品
/// // by 左倾月 on 2020/6/29 at 10:27
/// </summary>
/// <param name="self"></param>
/// <param name="index"></param>
/// <param name="count"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 删除多个物品
/// // by 左倾月 on 2020/8/11 at 11:43
/// </summary>
/// <param name="self"></param>
/// <param name="index"></param>
/// <param name="count"></param>
/// <returns></returns>
public static Item DeleteMultiItem(this Bag self, int itemId, int count, bool needUnload = false)
{
if (!self.ItemDic.TryGetValueByKey2(itemId, out List<Item> 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;
}
/// <summary>
/// 交换位置或者堆叠物品
/// // by 左倾月 on 2020/6/29 at 10:28
/// </summary>
/// <param name="self"></param>
/// <param name="index1"></param>
/// <param name="index2"></param>
/// <returns></returns>
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<GoodsBase>(item1.ItemId);
maxCount = goodsBase.MaxAmount;
break;
case ItemType.MaterialsItem:
MaterialBase materialBase = DataTableHelper.Get<MaterialBase>(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;
}
}
/// <summary>
/// 拆分物品
/// // by 左倾月 on 2020/6/29 at 10:28
/// </summary>
/// <param name="self"></param>
/// <param name="index"></param>
/// <param name="count"></param>
/// <returns></returns>
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<Item> 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系统错误未找到相应背包位置的物品";
}
/// <summary>
/// 整理背包
/// // by 左倾月 on 2020/6/29 at 10:28
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
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<Item>[] allList = self.ItemDic.GetAllByKey2().ToArray();
self.ItemDic.Clear();
int index = -1;
foreach (List<Item> 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;
}
/// <summary>
/// 穿戴装备
/// // by 左倾月 on 2020/6/29 at 10:30
/// </summary>
/// <param name="self"></param>
/// <param name="index"></param>
/// <returns></returns>
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<Unit>();
if (equip.ItemType != ItemType.EquipItem)
{
Log.Error($"【{ UserComponent.Instance.Get(unit.Id)?.NickName} ({ unit.Id})】想要穿戴非装备类物品!");
return "您只能穿戴装备或者形象!";
}
//!+用装备类型做索引,也是字典的键
EquipBase equipBase = DataTableHelper.Get<EquipBase>(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<SkinBase>(itemId);
if (skinBase == null)
{
Log.Warning($"skinBase == null where ItemId = {itemId}");
return;
}
NumericComponent num = unit.GetComponent<NumericComponent>();
num.Set(NumericType.SkinId, skinBase.Id);
}
else
if (equipType == EquipType.)
{
NumericComponent num = unit.GetComponent<NumericComponent>();
num.Set(NumericType.Title, itemId);
}
}
/// <summary>
/// 卸下装备
/// // by 左倾月 on 2020/6/29 at 16:30
/// </summary>
/// <param name="self"></param>
/// <param name="index"></param>
/// <returns></returns>
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<Unit>();
wornItem.IsLock = true;
self.AddItem(wornItem);
EquipBase equipBase = DataTableHelper.Get<EquipBase>(wornItem.ItemId);
EquipType equipType = (EquipType)equipBase.Type;
if (equipType == EquipType.)
{
NumericComponent num = unit.GetComponent<NumericComponent>();
User user = UserComponent.Instance.Get(unit.Id);
num.Set(NumericType.SkinId, user.JobId);
}
else
if (equipType == EquipType.)
{
NumericComponent num = unit.GetComponent<NumericComponent>();
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<int, Item>.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<EquipItem>();
// if (data.starSoulItemServerId != 0)
// {
// oldId = data.starSoulItemServerId;
// }
// data.starSoulItemServerId = id;
return null;
}
}
}