2025-06-04 05:02:57 +08:00

843 lines
20 KiB
Plaintext

autoImport("EquipInfo")
autoImport("SuitInfo")
autoImport("EnchantInfo")
autoImport("LoveLetterData")
autoImport("PetEggInfo")
autoImport("CodeData")
autoImport("WeddingData")
ItemData = class("ItemData")
ItemTarget_Type = {
Player = 1,
Npc = 2,
Monster = 4,
}
Item_CardType = {
Get = 1, --卡片抽取
Born = 2, --卡片合成
Raffle = 4, --禁止抽卡
Decompose = 8, --不可分解
}
local _MyItemStatusCheck = ItemsWithRoleStatusChange:Instance();
function ItemData:ctor(id,staticId)
--動態唯一標識id
self.id =""
self.bagtype = nil;
--table_item
self.staticData = nil
self.equipInfo = nil
self.cardInfo = nil
--附魔屬性
self.enchantInfo = nil
--目前裝備的卡片
self.equipedCardInfo = nil
--卡槽數量
self.cardSlotNum = 0
self.index = 0
self.num = 0
self.bind = false
self.expireTime = 0
self.equiped = 0
self.cdTime = 0;
self.configCdTime = 0
self.battlepoint = 0
self.isNew = false
self.isFashion = false
--此次登錄標記是否需要右下角提示
self.tempHint = true
self.isactive = false
self.couldUseWithRoleStatus = nil
self.replaceCount = 0;
self:ResetData(id,staticId)
self.CodeData = nil
end
function ItemData:ResetData(id,staticId)
self.cdTime = 0;
self.id = id
self.staticData = Table_Item[staticId]
if(self.staticData~=nil) then
self.staticData.id = staticId
elseif(staticId~=nil and staticId~=0)then
LogUtility.InfoFormat("根本找不到id為{0}的道具", tostring(staticId))
end
local equipData = Table_Equip[staticId]
if(equipData~=nil) then
self.equipInfo = EquipInfo.new(equipData)
self.cardSlotNum = equipData.CardSlot;
-- update replace count
self.replaceCount = 0;
if(equipData.SubstituteID)then
local cData = Table_Compose[equipData.SubstituteID];
local nextEquipId = cData.Product.id;
if(nextEquipId)then
while (nextEquipId~=nil and self.replaceCount < 5) do
self.replaceCount = self.replaceCount + 1;
local eData = Table_Equip[nextEquipId];
if(eData and eData.SubstituteID)then
cData = Table_Compose[eData.SubstituteID];
if(cData)then
nextEquipId = cData.Product.id;
else
nextEquipId = nil;
end
else
nextEquipId = nil;
end
end
end
end
else
self.equipInfo = nil
self.cardSlotNum = 0;
end
local useItemData = Table_UseItem[staticId]
self.configCdTime = useItemData and useItemData.CDTime or 0
-- 配置表的數據
self.cardInfo = Table_Card[staticId]
-- init suit
if(self.equipInfo)then
local suitIds = BagProxy.GetSuitIds(staticId)
if(#suitIds > 0)then
self.suitInfo = SuitInfo.new(suitIds);
end
end
end
function ItemData:GetCdConfigTime()
local useItemData = Table_UseItem[ self.staticData.id ];
if(useItemData == nil)then
return;
end
if(useItemData.PVPCDtime and Game.MapManager:IsPVPMode())then
return useItemData.PVPCDtime;
end
return useItemData.CDTime or 0;
end
-- {{guid = number, id = number}}
function ItemData:SetEquipCards(cards)
self.equipedCardInfo = {}
if(cards)then
for i=1,#cards do
local single = cards[i]
local equipedCard = ItemData.new(single.guid, single.id);
if(single.pos)then
equipedCard.index = single.pos;
self.equipedCardInfo[single.pos] = equipedCard;
else
table.insert(self.equipedCardInfo, equipedCard)
end
end
end
end
function ItemData:HasEquipedCard()
if(self.equipedCardInfo == nil)then
return false;
end
return next(self.equipedCardInfo) ~= nil;
end
function ItemData:GetEquipedCardNum()
if(self.equipedCardInfo == nil)then
return 0;
end
local count = 0;
for k,v in pairs(self.equipedCardInfo)do
count = count + 1;
end
return count;
end
function ItemData:SetEnchantInfo(enchantData)
if(not self.staticData)then
return;
end
if(not self.equipInfo)then
return;
end
if(self.enchantInfo == nil)then
self.enchantInfo = EnchantInfo.new(self.staticData.id);
end
self.enchantInfo:SetServerData(enchantData);
end
function ItemData:SetPreEnchantInfo(enchantData)
if(self.enchantInfo)then
self.enchantInfo:SetCacheServerData(enchantData);
end
end
function ItemData:SetCdStamp(stamp)
-- print("cd",stamp)
local configCdTime = self:GetCdConfigTime();
if(configCdTime and configCdTime>0 and stamp>0) then
-- print(-ServerTime.ServerDeltaSecondTime(stamp))
local delta = math.max(0,-ServerTime.ServerDeltaSecondTime(stamp))
if(delta<configCdTime and delta >=0) then
self.cdTime = configCdTime - delta
-- print(self.cdTime)
end
end
end
function ItemData:RefreshCD(deltaTime)
self.cdTime = self.cdTime - deltaTime
-- print(string.format("物品guid:%s,name:%s,剩餘cd時間:%s",self.id,self.staticData.NameZh,self.cdTime))
if(self.cdTime<=0) then
self.cdTime = 0
return true
end
return false
end
function ItemData:GetName(hideRefinelv, hideDamageColor)
if(self.staticData) then
local name = self.staticData.NameZh;
if(self.petEggInfo and self.petEggInfo.name ~= "")then
return string.format(ZhString.ItemData_PetEggName, self.petEggInfo.name);
end
if(self.equipInfo)then
if(self.equipInfo.refinelv>0 and hideRefinelv ~= true)then
name = string.format("+%d%s", self.equipInfo.refinelv, tostring(name));
end
if(self.equipInfo.equiplv > 0)then
name = name .. StringUtil.IntToRoman(self.equipInfo.equiplv);
end
if(self.equipInfo.damage and hideDamageColor ~= true)then
name = string.format("[c][CF1C0F]%s[-][/c]", tostring(name));
end
end
return name;
end
return ""
end
function ItemData.CheckIsEquip(itemid)
return Table_Equip[itemid] ~= nil;
end
function ItemData:IsEquip()
return self.equipInfo~=nil
end
function ItemData:IsFashion()
local result = false;
if(self.staticData and self.staticData.Type)then
result = BagProxy.fashionType[self.staticData.Type] ~= nil;
end
if(result == false)then
if(self.equipInfo and self.equipInfo.equipData.Body)then
result = true;
end
end
return result;
end
function ItemData:IsMount()
return self.staticData.Type==90;
end
function ItemData:IsNew()
return self.isNew~=nil and self.isNew or false
end
function ItemData:IsHint()
return self.isHint~=nil and self.isHint or false
end
function ItemData:IsLoveLetter()
return self.loveLetter ~= nil and self.loveLetter:CheckValid()
end
function ItemData:CanEquip(isSkipSkillCheck)
local myself = Game.Myself;
-- 處理手推車
local sid = self.staticData.id;
local otherLimit = GameConfig.EquipedLimitBySkill;
if(otherLimit and not isSkipSkillCheck)then
local skillConfig = otherLimit[sid];
if(skillConfig and myself.data:GetLernedSkillLevel(skillConfig[1]) < skillConfig[2])then
return false;
end
end
if self.equipInfo then
local sites = self.equipInfo:GetEquipSite()
if _MyItemStatusCheck:CanEquipWithCurrentStatus(sites) == false then
return false
end
local myPro = myself.data.userdata:Get(UDEnum.PROFESSION)
if(self.equipInfo:CanUseByProfess(myPro))then
local sexEquip = self.equipInfo.equipData.SexEquip or 0;
local mySex = myself.data.userdata:Get(UDEnum.SEX)
return sexEquip==0 or sexEquip==mySex;
end
else
return false
end
end
function ItemData:CanIOffEquip()
if(self.staticData == nil)then
return false;
end
if(self.equipInfo == nil)then
return false;
end
return _MyItemStatusCheck:CanOffEquipWithCurrentStatus(self.staticData.Type, self.equipInfo:GetEquipSite());
end
function ItemData:EyeCanEquip()
local mySex = Game.Myself.data.userdata:Get(UDEnum.SEX)
local id = self.staticData.id;
local staticData = Table_Eye[id];
if(staticData) then
if(mySex==staticData.Sex or staticData.Sex==3)then
if(staticData.IsPro==1 and staticData.OnSale == 1)then
return true
end
end
end
return false
end
function ItemData:HairCanEquip()
if(self.staticData == nil)then
return false;
end
local id = self.staticData.id;
local hairid = ShopDressingProxy.Instance:GetHairStyleIDByItemID(id)
if(hairid == nil)then
return false;
end
local hairSData = Table_HairStyle[hairid];
if(hairSData.IsPro == 1 and hairSData.OnSale == 1)then
local mySex = Game.Myself.data.userdata:Get(UDEnum.SEX)
return hairSData.Sex == mySex;
end
return false;
end
function ItemData:IsCodeCanSell()
if(self.CodeData)then
return self.CodeData:IsCodeCanSell()
end
return true
end
function ItemData:Clone()
local item = ItemData.new(self.id,self.staticData and self.staticData.id or 0)
item.num = self.num
item.isNew = self.isNew
item.bagtype = self.bagtype
if item.equipInfo then
item.equipInfo:Clone(self.equipInfo)
end
if self.equipedCardInfo then
item.equipedCardInfo = {}
for i=1,#self.equipedCardInfo do
TableUtility.ArrayPushBack(item.equipedCardInfo, self.equipedCardInfo[i]:Clone())
end
end
return item
end
-- function ItemData:CompareFightPointTo(item)
-- if(item) then
-- -- print(string.format("%s戰鬥力%s,vs,%s戰鬥力%s",self.staticData.NameZh,self.battlepoint,item.staticData.NameZh,item.battlepoint))
-- return self.battlepoint - item.battlepoint
-- end
-- return self.battlepoint
-- end
--傳入對比對象,返回自己是否比傳入的要好
function ItemData:CompareTo(item)
if(item) then
if(item.equipInfo ~= nil and self.equipInfo ~=nil) then
if(self.staticData.Quality >= item.staticData.Quality) then
if(item.staticData.Quality==1 and self.staticData.Quality > item.staticData.Quality) then
return true
end
local attrName,attrValue = item.equipInfo:GetEffect()
local selfAttrName,selfAttrValue = self.equipInfo:GetEffect()
if(attrName ~= selfAttrName) then
--武器屬性不同的話對比失敗
return false
end
if(attrValue ~= nil and selfAttrValue~=nil) then
if(selfAttrValue>attrValue)then
return true
elseif(selfAttrValue==attrValue)then
if(item.equipInfo.equipData and self.equipInfo.equipData) then
local selfEquipCardSlot = self.equipInfo.equipData.CardSlot or 0
local equipCardSlot = item.equipInfo.equipData.CardSlot or 0
if(selfEquipCardSlot > equipCardSlot) then
return true
end
end
return self.equipInfo.refinelv > item.equipInfo.refinelv
end
return false
end
end
return false
end
-- return self.battlepoint - item.battlepoint
end
return true
end
function ItemData:CanUse()
if(self.equipInfo)then
local myPro = Game.Myself.data.userdata:Get(UDEnum.PROFESSION);
local isValid = self.equipInfo:CanUseByProfess(myPro);
if(isValid)then
return self.num>0 and cdTime<=0;
end
end
return self.num>0 and self.cdTime<=0;
end
function ItemData:IsJobLimit()
local joblimit = self.staticData.JobLimit;
if(joblimit and #joblimit > 0)then
local myPro = Game.Myself.data.userdata:Get(UDEnum.PROFESSION);
local canuse = false;
for i=1,#joblimit do
if(myPro == joblimit[i])then
canuse = true;
break;
end
end
if(not canuse)then
return true;
end
end
return false;
end
function ItemData:IsLimitUse()
local sid = self.staticData.id;
local sData = Table_UseItem[sid];
if(sData == nil)then
return false;
end
local uselimit = sData.UseLimit;
if(uselimit == nil)then
return false;
end
if((uselimit & 1) > 0)then
if(Game.MapManager:IsPVPMode_GVGDetailed())then
return true;
end
end
if((uselimit & 2) > 0)then
local currentRaidID = Game.MapManager:GetRaidID();
local raidData = currentRaidID and Table_MapRaid[currentRaidID];
if(raidData == nil or raidData.Type ~= 10)then
return true;
end
end
if((uselimit & 4) > 0)then
if(not Game.MapManager:IsPVPMode())then
return true;
end
end
return false;
end
function ItemData:CanUseForTarget(targetType)
if(self.staticData == nil)then
return false;
end
local st = self.staticData.ItemTarget.type;
if(st ~= nil)then
if(st == 1)then
return targetType == ItemTarget_Type.Player;
elseif(st == 2)then
return targetType == ItemTarget_Type.Monster;
elseif(st == 3)then
return targetType == ItemTarget_Type.Monster or targetType == ItemTarget_Type.Player;
end
-- return st & targetType > 0;
end
return false;
end
function ItemData:ToString()
return string.format("Guid:%s Sid:%d Equiped:%d Type:%d Quality:%d Index:%d Num:%d",self.id,self.staticData.id,self.equiped,self.staticData.Type,self.staticData.Quality,self.index,self.num)
end
function ItemData:ToTestString()
return string.format("Guid:%s Sid:%d Equiped:%d Type:%d Quality:%d Index:%d Num:%d",self.id,self.sid,self.equiped,self.type,self.qua,self.index,self.num)
end
function ItemData:ParseFromServerData(serverItem)
local sItemData = serverItem.base
local sEquipData = serverItem.equip
local sECardInfo = serverItem.card
if(serverItem.equiped)then
self.equiped = 1
else
self.equiped = 0
end
-- helplog("ItemData ParseFromServerData: guid:"..sItemData.guid.." id:"..sItemData.id)
self:ResetData(sItemData.guid,sItemData.id)
if(self.staticData==nil) then
errorLog("server send item ,which has no staticData "..sItemData.id)
return
end
self.num = sItemData.count
self.battlepoint = serverItem.battlepoint
self.isNew = serverItem.base.isnew
self.isHint = serverItem.base.ishint
-- item.cardSlotNum = sEquipData.cardslot or 0
self.index = sItemData.index
self.createtime = sItemData.createtime
self.deltime = sItemData.overtime
self.isFashion = BagProxy.fashionType[self.staticData.Type] or false
self.bind = sItemData.eBind == ProtoCommon_pb.EBINDTYPE_BIND
self:SetCdStamp(sItemData.cd)
if(self.equipInfo and sEquipData) then
self.equipInfo:Set(sEquipData)
end
self:SetEquipCards(sECardInfo);
if(serverItem.enchant)then
self:SetEnchantInfo(serverItem.enchant);
self:SetPreEnchantInfo(serverItem.previewenchant);
end
self:UpdateEnchantCombineEffect();
local sLoveLetter = serverItem.letter
if sLoveLetter then
if self.loveLetter == nil then
self.loveLetter = LoveLetterData.new()
end
self.loveLetter:SetDataByItemServerData(sItemData.id, sLoveLetter)
end
if(serverItem.egg and serverItem.egg.id~=nil and serverItem.egg.id~=0)then
self.petEggInfo = PetEggInfo.new(self.staticData);
self.petEggInfo:Server_SetData(serverItem.egg);
end
if(serverItem.code)then
self.CodeData=CodeData.new(sItemData.guid,self.staticData)
self.CodeData:Server_SetData(serverItem.code)
end
if(serverItem.wedding and serverItem.wedding.id ~= 0)then
if(not self.weddingData)then
self.weddingData = WeddingData.new(self.staticData);
end
self.weddingData:Server_Update(serverItem.wedding);
end
local s_sender = serverItem.sender;
if(s_sender)then
if(s_sender.charid ~= nil and s_sender.charid ~= 0)then
self.sender_charid = s_sender.charid;
self.sender_name = s_sender.name;
end
end
end
function ItemData:ExportServerItem()
if(not self.staticData)then
return;
end
local serverItem = SceneItem_pb.ItemData();
serverItem.base.id = self.staticData.id;
-- ...
if(self.equipInfo)then
-- serverItem.equip.strengthlv = self.equipInfo.strengthlv;
serverItem.equip.refinelv = self.equipInfo.refinelv;
serverItem.equip.damage = self.equipInfo.damage;
serverItem.equip.lv = self.equipInfo.equiplv;
-- ...
end
if(self.enchantInfo)then
local attrs = self.enchantInfo:GetEnchantAttrs();
if(#attrs > 0)then
serverItem.enchant.type = self.enchantInfo.enchantType;
local serverAttris = {};
for i=1,#attrs do
local serverAttri = SceneItem_pb.EnchantAttr()
serverAttri.type = attrs[i].type;
serverAttri.value = attrs[i].serverValue;
table.insert(serverItem.enchant.attrs, serverAttri)
end
local combineEffect = self.enchantInfo:GetCombineEffects();
for i=1,#combineEffect do
local serverExtra = SceneItem_pb.EnchantExtra()
serverExtra.configid = combineEffect[i].configid;
serverExtra.buffid = combineEffect[i].buffid;
table.insert(serverItem.enchant.extras, serverExtra)
end
end
end
return serverItem;
end
function ItemData:UpdateEnchantCombineEffect()
if(self.enchantInfo and self.equipInfo)then
self.enchantInfo:UpdateCombineEffectWork(self.equipInfo.refinelv);
end
end
function ItemData:SetDelWarningState(b)
self.delWarning = b;
end
function ItemData:GetDelWarningState()
return self.delWarning;
end
function ItemData:CheckItemCardType(item_CardType)
if(self.cardInfo and self.cardInfo.Type)then
return (self.cardInfo.Type & item_CardType) > 0;
end
return false;
end
function ItemData:GetFoodSData()
local sid = self.staticData.id;
return Table_Food[sid];
end
function ItemData:IsFood()
return self:GetFoodSData() ~= nil;
end
function ItemData:IsCard()
return self.cardInfo ~= nil;
end
function ItemData:IsPic()
if(self.staticData)then
return self.staticData.Type == 50;
end
return false;
end
function ItemData:IsPetEgg()
if(self.staticData)then
return self.staticData.Type == 101;
end
return false;
end
function ItemData:IsUseItem()
if(self.staticData == nil)then
return false
end
return Table_UseItem[ self.staticData.id ] ~= nil;
end
-- 結婚邀請函
function ItemData:IsMarryInviteLetter()
if(self.staticData and self.weddingData)then
return self.staticData.Type == 167;
end
return false;
end
function ItemData:IsMarriageCertificate()
if(self.staticData and self.weddingData)then
return self.staticData.Type == 166;
end
return false;
end
function ItemData:IsMarriageRing()
if(self.staticData and self.weddingData)then
return self.staticData.Type == 540;
end
return false;
end
function ItemData:GetFoodEffectDesc()
if(self.buffDesc == nil)then
self.buffDesc = "";
local sid = self.staticData.id;
if(sid == FoodProxy.FailFood_ItemID)then
self.buffDesc = "??????????";
else
local foodSData = self:GetFoodSData();
if(foodSData)then
local buffids = foodSData.BuffEffect;
local buff_SData;
for i=1,#buffids do
buff_SData = Table_Buffer[buffids[i]];
self.buffDesc = self.buffDesc .. buff_SData.Dsc;
if(i < #buffids)then
self.buffDesc = self.buffDesc .. "\n"
end
end
else
self.buffDesc = "";
end
end
end
return self.buffDesc;
end
function ItemData:CanTrade()
if(self.petEggInfo)then
return self.petEggInfo:CanExchange();
end
return ItemData.CheckItemCanTrade(self.staticData.id);
end
function ItemData.CheckItemCanTrade(itemid)
local data = Table_Exchange[itemid]
if data then
if data.Trade ~= 1 then
return false
end
local _FormatTime2TimeStamp = StringUtil.FormatTime2TimeStamp
local serverTime = ServerTime.CurServerTime()/1000
local canTrade = true
local isTFBranch = EnvChannel.IsTFBranch()
--這個時間后,可上架
local tradeTime
if isTFBranch then
tradeTime = data.TFTradeTime
else
tradeTime = data.TradeTime
end
if tradeTime ~= nil and tradeTime ~= "" then
local t = _FormatTime2TimeStamp(tradeTime)
canTrade = serverTime >= t
end
--這個時間后,不可上架
local unTradeTime
if isTFBranch then
unTradeTime = data.TFUnTradeTime
else
unTradeTime = data.UnTradeTime
end
if unTradeTime ~= nil and unTradeTime ~= "" then
local t = _FormatTime2TimeStamp(unTradeTime)
canTrade = (serverTime <= t) and canTrade
end
return canTrade
end
return false
end
function ItemData.Get_GetLimitCount(itemid)
local limitCfg = Table_Item[itemid].GetLimit;
local mylv = Game.Myself.data.userdata:Get(UDEnum.ROLELEVEL)
local limitCount = ItemData.Help_GetLimitCount(limitCfg.limit, mylv);
if(type(limitCount) == "table")then
local hasMonthVIP = ServiceUserEventProxy.Instance:AmIMonthlyVIP();
if(hasMonthVIP)then
limitCount = limitCount[1] + limitCount[2];
else
limitCount = limitCount[1];
end
end
return limitCount;
end
local tempTable = {};
function ItemData.Help_GetLimitCount( map, mylv )
local limitCount = nil;
TableUtility.TableClear(tempTable);
for lv, count in pairs(map) do
table.insert(tempTable, {lv, count})
end
table.sort(tempTable, function (a,b)
return a[1] < b[1];
end)
for i=1,#tempTable do
if(mylv <= tempTable[i][1])then
limitCount = tempTable[i][2]
break;
end
end
if(limitCount == nil)then
limitCount = tempTable[1][2];
end
return limitCount;
end
-- return Prop
function ItemData:CanStack()
if(self.staticData == nil)then
return;
end
return self.staticData.MaxNum > 1;
end
function ItemData:CanStorage(bagType)
if(self.staticData == nil)then
return false;
end
local noStorage = self.staticData.NoStorage;
if(noStorage == nil)then
return true;
end
local Item_Nostorge_Type = {
[BagProxy.BagType.Storage] = 1,
[BagProxy.BagType.PersonalStorage] = 2,
[BagProxy.BagType.Barrow] = 2,
}
local forbidValue = Item_Nostorge_Type[bagType];
if(forbidValue == nil)then
return true;
end
return noStorage & forbidValue <= 0;
end
function ItemData:SetItemNum( num )
self.num = num
end