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=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