zxl
/
CTT
forked from Cal/CTT
1
0
Fork 0
CTT/Server/Hotfix/Game/System/Bag/BagSystem.cs

737 lines
27 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 += (type) =>
{
return self.GetAttribute(type);
};
}
}
public class BagDeserializeSystem : DeserializeSystem<Bag>
{
public override void Deserialize(Bag self)
{
self.getAttributeFunc += (type) =>
{
return self.GetAttribute(type);
};
}
}
public class BagDestroySystem : DestroySystem<Bag>
{
public override void Destroy(Bag self)
{
self.ItemCount = 0;
self.CurrEquipServerId = 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 var 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)
{
var bounds = 0f;
foreach (var 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);
}
foreach (var suitId in self.suitAttributes)
{
SuitConfig suitConfig = SuitConfigCategory.Instance.Get(suitId);
if (suitConfig == null)
{
Log.Error($"suitConfig is null where id = {suitId}");
continue;
}
foreach (var 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 var nullList))
{
var 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 var list))
{
CalucateCount();
}
int whileCount = 50;
while (count > 0)
{
if (self.ItemCount + 1 > self.MaxItemCount)
{
return item.Count - count;
}
if (self.ItemDic.TryGetValueByKey2(0, out var nullList))
{
var 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 (var 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 var list))
{
return self.CanAddNewItem();
}
int maxCount = BagHelper.GetItemBase(itemId) switch
{
GoodsBase goodsBase => goodsBase.MaxAmount,
MaterialBase materialBase => materialBase.MaxAmount,
_ => throw new InvalidCastException($"物品类型错误id= {itemId}"),
};
foreach (var item in list)
{
count = count + item.Count - maxCount;
if (count <= 0) return true;
}
if (count <= 0) return true;
if (!self.ItemDic.TryGetValueByKey2(0, out var nullItemList))
{
return false;
}
foreach (var 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 var list))
{
return GetNewStackItemNeedSlotCount(maxCount, count);
}
foreach (var 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 var 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 var itemList) || itemList.Count == 0)
{
return null;
}
Item retItem = null;
for (int i = itemList.Count - 1; i >= 0; i--)
{
var 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 var item1))
{
return "Bag系统错误未找到相应背包位置的物品";
}
if (!self.ItemDic.TryGetValueByKey1(index2, out var 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);
var 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 var item))
{
if (count <= 0)
{
return "拆分数量应该大于0";
}
if (item.Count <= 1)
{
return "物品数量为小于2无法拆分";
}
if (item.Count <= count)
{
return "拆分数量应该小于物品数量!";
}
if (self.ItemDic.TryGetValueByKey2(0, out var nullList))
{
var 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)
{
var now = TimeHelper.ClientNow();
if (now - self.lastSortTime <= self.SortTimeInterval)
{
return $"请等待{(self.lastSortTime + self.SortTimeInterval - now) / 1000f:f0}s之后再整理";
}
self.lastSortTime = now;
var allList = self.ItemDic.GetAllByKey2().ToArray();
self.ItemDic.Clear();
int index = -1;
foreach (var list in allList)
{
foreach (var 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)
{
var 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 var 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(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;
}
var num = unit.GetComponent<NumericComponent>();
num.Set(NumericType.SkinId, skinBase.Id);
}
else
if (equipType == EquipType.)
{
var 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 var 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);
var equipType = (EquipType)equipBase.Type;
if (equipType == EquipType.)
{
var num = unit.GetComponent<NumericComponent>();
var user = UserComponent.Instance.Get(unit.Id);
num.Set(NumericType.SkinId, user.JobId);
}
else
if (equipType == EquipType.)
{
var 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;
var 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 (var equip in suitConfig.EquipArr)
{
if (equip.Job == job)
{
foreach (var equipId in equip.EquipIdArr)
{
if (isPuton && equipId == itemId)
{
continue;
}
bool hasEquip = false;
foreach (var item in dic)
{
if (equipId == item.ItemId)
{
hasEquip = true;
break;
}
}
hasEquips = hasEquips && hasEquip;
}
break;
}
}
id = (int)suitConfig.Id;
return hasEquips;
}
}
}