----- 魂印弹窗 ----- require("Base/BasePanel") GodPrintPopUp = Inherit(BasePanel) local itemConfig = ConfigManager.GetConfig(ConfigName.ItemConfig) local equipConfig = ConfigManager.GetConfig(ConfigName.EquipConfig) local passiveSkillConfig = ConfigManager.GetConfig(ConfigName.PassiveSkillConfig) local heroConfig = ConfigManager.GetConfig(ConfigName.HeroConfig) local propertyconfig = ConfigManager.GetConfig(ConfigName.PropertyConfig) -- 面板类型 local Type = { Up = 1, -- 穿戴 Down = 2, -- 卸下 Access = 3, -- 有获取途径 传nil就不显示了 UpStar = 4 -- 升星 } -- 打开面板类型 local curType = 0 local heroId -- 当前英雄id local soulId -- 魂印id local pos -- 位置 local callback -- 回调 local localData -- 本地存储的魂印数据 包含soulId 该数据只在魂印装备时(Type.Up)才有用 -- 适用范围英雄容器 local proList = {} local _superProList = {} -- 白金属性对象 function GodPrintPopUp:InitComponent() self.spLoader = SpriteLoader.New() self.panel = Util.GetGameObject(self.gameObject, "Panel") self.maskBtn = Util.GetGameObject(self.gameObject, "mask") -- 基础信息 -- 装备详情--topBar self.topBar = Util.GetGameObject(self.transform, "Panel/topBar") self.topBarBg = Util.GetGameObject(self.transform, "Panel/topBar/bg2") self.topBarBgColor = Util.GetGameObject(self.transform, "Panel/topBar/bg1"):GetComponent("Image") self.soulName = Util.GetGameObject(self.topBar, "name"):GetComponent("Text") self.icon = Util.GetGameObject(self.topBar, "icon"):GetComponent("Image") self.frame = Util.GetGameObject(self.topBar, "frame"):GetComponent("Image") self.circleFrameBg = Util.GetGameObject(self.topBar, "circleFrameBg"):GetComponent("Image") self.circleFrame = Util.GetGameObject(self.topBar, "circleFrame"):GetComponent("Image") self.equipType = Util.GetGameObject(self.topBar, "equipType"):GetComponent("Text") self.lvTxt = Util.GetGameObject(self.topBar, "lv"):GetComponent("Text") self.equipQuaText = Util.GetGameObject(self.topBar, "equipQuaText"):GetComponent("Text") self.equipInfoText = Util.GetGameObject(self.topBar, "equipInfoText"):GetComponent("Text") self.powerNum = Util.GetGameObject(self.topBar, "powerNum"):GetComponent("Text") self.star = Util.GetGameObject(self.topBar, "star") self.effectbaijin = Util.GetGameObject(self.topBar, "fx_zhuangbeijiemian") -- 魂印效果 self.midBar = Util.GetGameObject(self.transform, "Panel/midBar") self.effectText = Util.GetGameObject(self.midBar, "basePro/Info/Text"):GetComponent("Text") self.desText = Util.GetGameObject(self.midBar, "basePro/PropertyName"):GetComponent("Text") self.desText.text = Language[11167] -- 突破效果 self.breakText = Util.GetGameObject(self.midBar, "breakPro/Info/Text"):GetComponent("Text") self.desText2 = Util.GetGameObject(self.midBar, "breakPro/PropertyName"):GetComponent("Text") self.desText2.text = Language[11168] self.breakObj = Util.GetGameObject(self.midBar, "breakPro") -- 技能效果 self.skillObj = Util.GetGameObject(self.midBar, "superPro") self.skillGrid = Util.GetGameObject(self.midBar, "superPro/proGrid") self.skillPre = Util.GetGameObject(self.midBar, "superPro/proGrid/Desc") -- 适用范围(还没做具体内容) self.trialScope = Util.GetGameObject(self.midBar, "TrialScope") self.trialScopeText = Util.GetGameObject(self.trialScope, "Text"):GetComponent("Text") -- 数据小于4自动布局 self.scroll_1 = Util.GetGameObject(self.trialScope, "Scroll_1") -- 静态布局根节点 self.trialScopePre = Util.GetGameObject(self.trialScope, "Scroll_1/TrialScopePre") -- 适用范围预设 -- 数据大于4优化布局 self.scroll_2 = Util.GetGameObject(self.trialScope, "Scroll_2") -- 优化滚动条 self.scrollView = SubUIManager.Open(SubUIConfig.ScrollFitterView, self.scroll_2.transform, self.trialScopePre, Vector2.New(899.5, 490), 1, 15) self.scrollView.gameObject:GetComponent("RectTransform").anchoredPosition = Vector2.New(-70, 0) self.scrollView.gameObject:GetComponent("RectTransform").anchorMin = Vector2.New(0.5, 0.5) self.scrollView.gameObject:GetComponent("RectTransform").anchorMax = Vector2.New(0.5, 0.5) self.scrollView.gameObject:GetComponent("RectTransform").pivot = Vector2.New(0.5, 0.5) self.scrollView.moveTween.MomentumAmount = 1 self.scrollView.moveTween.Strength = 2 self.btmBar = Util.GetGameObject(self.transform, "Panel/btmBar") -- 获取途径 self.howGet = Util.GetGameObject(self.btmBar, "howGet") self.canGetPre = Util.GetGameObject(self.howGet, "scroll/canGetPre") self.canGetGrid = Util.GetGameObject(self.howGet, "scroll") self.canGetScrollView = SubUIManager.Open(SubUIConfig.ScrollCycleView, self.canGetGrid.transform, self.canGetPre, nil, Vector2.New(self.canGetGrid.transform.rect.width, self.canGetGrid.transform.rect.height), 1, 1, Vector2.New(0, 0)) self.canGetScrollView.moveTween.MomentumAmount = 1 self.canGetScrollView.moveTween.Strength = 2 self.canGetScrollView.elastic = false self.jumpViewList = {} -- 操作按钮 self.btns = Util.GetGameObject(self.btmBar, "btnGrid") self.upBtn = Util.GetGameObject(self.btns, "UpBtn") self.downBtn = Util.GetGameObject(self.btns, "DownBtn") self.upStarBtn = Util.GetGameObject(self.btns, "UpStarBtn") end function GodPrintPopUp:BindEvent() -- 关闭面板 Util.AddClick(self.maskBtn, function() self:ClosePanel() end) -- 提升品阶 Util.AddClick(self.upStarBtn, function() if curType ~= 2 then heroId = nil end UIManager.OpenPanel(UIName.GeneralBigPopup, GENERAL_POPUP_TYPE.GodPrintUp, soulId, pos, heroId, callback) self:ClosePanel() end) -- 穿戴 Util.AddClick(self.upBtn, function() -- 检测是否已穿过该类型魂印 local curHeroData = HeroManager.GetSingleHeroData(heroId) if curHeroData and curHeroData.godPrintList and #curHeroData.godPrintList > 0 then for i = 1, #curHeroData.godPrintList do if curHeroData.godPrintList[i].equipId == soulId then PopupTipPanel.ShowTip(Language[11169]) return end end end -- 如果装备位置满了 显示替换界面 if pos == 0 then PopupTipPanel.ShowTip("剩余位置不足!") --[[ UIManager.OpenPanel(UIName.GodPrintPopUpV2, 2, curHeroData, localData, function() self:ClosePanel() self:RefreshShow() if callback then callback() end end) ]] return end -- 如果是别人装备的 -- if localData.upHero~="" then -- --当前点击魂印被装到的英雄数据 -- local curClickHeroData=HeroManager.GetSingleHeroData(localData.upHero) -- local str=string.format("是否要将%s的%s装备到%s上?",itemConfig[curClickHeroData.id].Name,equipConfig[localData.id].Name,itemConfig[curHeroData.id].Name) -- MsgPanel.ShowTwo(str, nil, function() -- local _pos = 0 -- for i = 1, #curClickHeroData.soulPrintList do -- if curClickHeroData.soulPrintList[i].equipId == localData.id then -- _pos = curClickHeroData.soulPrintList[i].position -- end -- end -- NetManager.SoulEquipUnLoadWearRequest(tostring(curClickHeroData.dynamicId),localData.id,_pos,function() -- HeroManager.DelSoulPrintUpHeroDynamicId(curClickHeroData.dynamicId,localData.id) -- local wearInfo = {heroId = tostring(curHeroData.dynamicId),equipId = localData.id,position = pos} -- NetManager.SoulEquipWearRequest(wearInfo,nil,function() -- HeroManager.AddSoulPrintUpHeroDynamicId(curHeroData.dynamicId,localData.id,pos) -- PopupTipPanel.ShowTip("装备成功!") -- self:RefreshShow() -- -- -- if callback then -- callback() -- end -- self:ClosePanel() -- end) -- end) -- end) -- return -- end -- else--选择的魂印没有被其他猎妖师装备 可直接装备 -- 穿戴 local wearInfo = { heroId = tostring(heroId), equipId = soulId, position = pos } NetManager.WearGodSealRequest(1, wearInfo, function() HeroManager.AddGodPrintUpHeroDynamicId(heroId, soulId, pos) PopupTipPanel.ShowTip(Language[11170]) HeroPropManager.SetDirtyByType(wearInfo.heroId, Hero_Prop_Type.GodPrint) if callback then callback() end end) self:ClosePanel() -- end end) -- 卸下 Util.AddClick(self.downBtn, function() local wearInfo = { heroId = tostring(heroId), equipId = soulId, position = pos } NetManager.WearGodSealRequest(0, wearInfo, function() PopupTipPanel.ShowTip(Language[11171]) HeroManager.DelGodPrintUpHeroDynamicId(heroId, soulId) HeroPropManager.SetDirtyByType(wearInfo.heroId, Hero_Prop_Type.GodPrint) if callback then callback() end end) self:ClosePanel() end) end function GodPrintPopUp:AddListener() end function GodPrintPopUp:RemoveListener() end -- curtype 面板类型(看最上面解释) heroId 英雄ID soulId魂印ID pos位置 callback回调 localData本地存储魂印数据(只在穿戴时用) function GodPrintPopUp:OnOpen(...) local args = { ... } curType = args[1] heroId = args[2] soulId = args[3] pos = args[4] callback = args[5] localData = args[6] end function GodPrintPopUp:OnShow() self:RefreshShow(curType) LayoutRebuilder.ForceRebuildLayoutImmediate(self.panel.transform) end function GodPrintPopUp:OnClose() for i = 1, #self.jumpViewList do destroy(self.jumpViewList[i].gameObject) end end function GodPrintPopUp:OnDestroy() self.spLoader:Destroy() self.scrollView = nil proList = {} _superProList = {} self.jumpViewList = {} end -- 读取魂印适用英雄效果 local x = function(index) local args = {} local tempArgs = string.split(GetLanguageStrById(equipConfig[soulId].Parameter), '|') local t = string.split(tempArgs[index], '#') for i, v in ipairs(t) do args[i] = v end return string.format(GetLanguageStrById(equipConfig[soulId].Describe), unpack(args)) end -- 刷新面板 function GodPrintPopUp:RefreshShow(_type) -- self.btns:SetActive(type==Type.Up or type==Type.Down) self.btns:SetActive(true) self.upBtn:SetActive(_type == Type.Up) self.downBtn:SetActive(_type == Type.Down) self.upStarBtn:SetActive(_type ~= 0 and equipConfig[soulId].Formula ~= nil and type(equipConfig[soulId].Formula[1][1]) ~= "userdata") -- 基础信息 self.soulName.text = GetLanguageStrById(equipConfig[soulId].Name) self.frame.sprite = self.spLoader:LoadSprite(GetQuantityImageByquality(equipConfig[soulId].Quality)) self.icon.sprite = self.spLoader:LoadSprite(GetResourcePath(itemConfig[soulId].ResourceID)) self.circleFrameBg.sprite = self.spLoader:LoadSprite(SoulPrintSpriteByQuantity[itemConfig[soulId].Quantity] .circleBg2) self.circleFrame.sprite = self.spLoader:LoadSprite(SoulPrintSpriteByQuantity[itemConfig[soulId].Quantity].circle) self.powerNum.text = equipConfig[soulId].Score -- 战力 self.lvTxt.gameObject:SetActive(equipConfig[soulId].Star > 0) self.lvTxt.text = "+" .. equipConfig[soulId].Star self.equipInfoText.text = GetLanguageStrById(itemConfig[soulId].ItemDescribe) self.equipQuaText.text = GetStringByEquipQua(equipConfig[soulId].Quality, GetQuaStringByEquipQua(equipConfig[soulId].Quality)) self.equipType.text = Language[11172] .. GetEquipPosStrByEquipPosNum(equipConfig[soulId].Position) -- self.topBar:GetComponent("Image").sprite = self.spLoader:LoadSprite("t_tongyong_di_"..equipConfig[soulId].Quality) --self.topBar:GetComponent("Image").sprite = self.spLoader:LoadSprite("t_tongyong_di_4") local aaa = tostring(equipConfig[soulId].Quality) self.topBarBg:GetComponent("Image").sprite = self.spLoader:LoadSprite("t_tongyong_di_" .. equipConfig[soulId].Quality) if aaa == "1" then self.topBarBgColor.color = Color.New(0.81, 0.81, 0.81, 1) elseif aaa == "2" then self.topBarBgColor.color = Color.New(0.24, 0.34, 0.21, 1) elseif aaa == "3" then self.topBarBgColor.color = Color.New(0.22, 0.42, 0.63, 1) elseif aaa == "4" then self.topBarBgColor.color = Color.New(0.29, 0.14, 0.26, 1) elseif aaa == "5" then self.topBarBgColor.color = Color.New(0.26, 0.14, 0.06, 1) elseif aaa == "6" then self.topBarBgColor.color = Color.New(0.25, 0.02, 0.02, 1) elseif aaa == "7" then self.topBarBgColor.color = Color.New(0.32, 0.32, 0.32, 1) elseif aaa == "8" then self.topBarBgColor.color = Color.New(0.32, 0.32, 0.32, 1) end self.effectbaijin:SetActive(equipConfig[soulId].Quality == 7) Util.SetParticleSortLayer(self.effectbaijin, self.sortingOrder + 1) if equipConfig[soulId] then -- 魂印效果 local txt = "" local pass = equipConfig[soulId].PassiveSkill if pass ~= nil and tonumber(pass[1]) ~= nil and tonumber(pass[1]) ~= 0 then self.effectText.text = GetLanguageStrById(passiveSkillConfig[pass[1]].Desc) else if equipConfig[soulId].Property then for index, value in ipairs(equipConfig[soulId].Property) do -- propertyconfig if index > 1 then txt = txt .. "," end if propertyconfig[value[1]].Style == 1 then txt = txt .. GetLanguageStrById(propertyconfig[value[1]].Info) .. "+" .. value[2] elseif propertyconfig[value[1]].Style == 2 then txt = txt .. GetLanguageStrById(propertyconfig[value[1]].Info) .. "+" .. math.floor((value[2] / 100)) .. "%" end end end self.effectText.text = txt end if equipConfig[soulId].Quality >= 7 then self.breakObj:SetActive(true) local allConfig = ConfigManager.TryGetConfigDataByThreeKey(ConfigName.EquipConfig, "SuiteID", equipConfig[soulId].SuiteID, "SuiteID1", equipConfig[soulId].SuiteID1, "Star", 10) local _allConfig = ConfigManager.TryGetConfigDataByThreeKey(ConfigName.EquipConfig, "SuiteID", equipConfig[soulId].SuiteID, "SuiteID1", equipConfig[soulId].SuiteID1, "Star", 1) local stringInfo = "" if allConfig then local firstStr = "" for index, value in ipairs(allConfig.Property) do -- propertyconfig local curStr = "" if propertyconfig[value[1]].Style == 1 then curStr = GetLanguageStrById(propertyconfig[value[1]].Info) .. "+" .. value[2] elseif propertyconfig[value[1]].Style == 2 then curStr = GetLanguageStrById(propertyconfig[value[1]].Info) .. "+" .. math.floor((value[2] / 100)) .. "%" end if index == 1 then -- 第一条属性不显示 -- firstStr=curStr elseif index == 2 then local _curStr = "" local _value = _allConfig.Property[2] if propertyconfig[_value[1]].Style == 1 then _curStr = GetLanguageStrById(propertyconfig[_value[1]].Info) .. "+" .. _value[2] elseif propertyconfig[_value[1]].Style == 2 then _curStr = GetLanguageStrById(propertyconfig[_value[1]].Info) .. "+" .. math.floor((_value[2] / 100)) .. "%" end if equipConfig[soulId].Star >= index - 1 then stringInfo = stringInfo .. "" .. string.format(Language[11173], index - 1) .. " " .. _curStr .. "\n" else stringInfo = stringInfo .. "" .. string.format(Language[11173], index - 1) .. " " .. _curStr .. "\n" end elseif index >= 12 then if equipConfig[soulId].Star >= 10 then stringInfo = stringInfo .. "" .. curStr .. " " .. "" else stringInfo = stringInfo .. "" .. curStr .. " " .. "" end elseif index == 11 then local _curStr = "" local _value = allConfig.Property[2] local _value2 = _allConfig.Property[2] if propertyconfig[_value[1]].Style == 1 then _curStr = GetLanguageStrById(propertyconfig[_value[1]].Info) .. "+" .. _value[2] elseif propertyconfig[_value[1]].Style == 2 then _curStr = GetLanguageStrById(propertyconfig[_value[1]].Info) .. "+" .. math.floor(((_value[2] - _value2[2]) / 100)) .. "%" end if equipConfig[soulId].Star >= 10 then stringInfo = stringInfo .. "" .. string.format(Language[11173], 10) .. " " .. curStr .. " " .. _curStr .. " " else stringInfo = stringInfo .. "" .. string.format(Language[11173], 10) .. " " .. curStr .. " " .. _curStr .. " " end else if equipConfig[soulId].Star >= index - 1 then stringInfo = stringInfo .. "" .. string.format(Language[11173], index - 1) .. " " .. curStr .. "\n" else stringInfo = stringInfo .. "" .. string.format(Language[11173], index - 1) .. " " .. curStr .. "\n" end end end end self.breakText.text = stringInfo else self.breakObj:SetActive(false) end local curID = 0 local isEnough = false local suiteId = equipConfig[soulId].SuiteID1 local heroData = HeroManager.GetSingleHeroData(heroId) if heroData then local tian = {} local di = {} local printList = {} for i = 1, #heroData.godPrintList do local id = heroData.godPrintList[i].equipId -- if equipConfig[id].SuiteID<=8 and equipConfig[soulId].SuiteID<=8 then -- --LogError("equipConfig[id].SuiteID1=="..equipConfig[id].SuiteID1) -- table.insert(tian,equipConfig[id].SuiteID1) -- elseif equipConfig[id].SuiteID>8 and equipConfig[soulId].SuiteID>8 then -- --LogError("equipConfig[id].SuiteID1=="..equipConfig[id].SuiteID1) -- table.insert(di,equipConfig[id].SuiteID1) -- end if equipConfig[id].ShenYinType == equipConfig[soulId].ShenYinType then if printList[equipConfig[id].ShenYinType] then printList[equipConfig[id].ShenYinType][1] = printList[equipConfig[id].ShenYinType][1] + 1 if equipConfig[id].SuiteID1 < printList[equipConfig[id].ShenYinType][2] then printList[equipConfig[id].ShenYinType][2] = equipConfig[id].SuiteID1 end else printList[equipConfig[id].ShenYinType] = {} printList[equipConfig[id].ShenYinType][1] = 1 printList[equipConfig[id].ShenYinType][2] = equipConfig[id].SuiteID1 end end end for key, value in pairs(printList) do LogError("key=====" .. key .. " value==" .. value[1] .. " id==" .. value[2]) if value[1] == 4 then isEnough = true suiteId = value[2] LogError("1111111111111111") end end -- LogError("tian len=="..#tian) -- LogError("di len=="..#di) -- if equipConfig[soulId].SuiteID<=8 then -- if #tian==4 then -- isEnough=true -- table.sort(tian,function(a,b) -- return a(%s)",GetEquipSuitStr(curGoldSuitConFig.Id,goldSuiteSkill[i][1])) -- LogError("goldSuiteSkill[i][2]=="..goldSuiteSkill[i][2]) if goldSuiteSkill[i][2] then if isEnough then -- go:GetComponent("Text").text = string.format("%s",GetLanguageStrById(passiveSkillConfig[goldSuiteSkill[i][2]].Desc)) go:GetComponent("Text").text = GetLanguageStrById( passiveSkillConfig[goldSuiteSkill[i][2]].Desc) else -- go:GetComponent("Text").text = string.format("%s",GetLanguageStrById(passiveSkillConfig[goldSuiteSkill[i][2]].Desc)) go:GetComponent("Text").text = GetLanguageStrById( passiveSkillConfig[goldSuiteSkill[i][2]].Desc) end end go:GetComponent("Text").enabled = true end end LayoutRebuilder.ForceRebuildLayoutImmediate(self.skillObj.transform) else self.skillObj:SetActive(false) end end -- 适用范围 -- local isOpenTrialScope=equipConfig[soulId].Range and equipConfig[soulId].Range[1]~=0 and equipConfig[soulId].Range[1]--是否开启适用 -- if isOpenTrialScope then -- self.trialScopeText.text = "以下神将可装备:" -- self.scroll_1:SetActive(#equipConfig[soulId].Range<=3) -- self.scroll_2:SetActive(#equipConfig[soulId].Range>3) -- --适用英雄<=3时 固定长度生成(预设) 反之使用优化滚动条 -- if #equipConfig[soulId].Range<=3 then -- for j = 0, self.scroll_1.transform.childCount-1 do -- self.scroll_1.transform:GetChild(j).gameObject:SetActive(false) -- end -- for i = 1, #equipConfig[soulId].Range do--遍历每个适用英雄 -- local item= proList[i] -- if not item then -- item= newObjToParent(self.trialScopePre,self.scroll_1) -- item.name="ProPre"..i -- proList[i]=item -- end -- proList[i].gameObject:SetActive(true) -- local _heroId=equipConfig[soulId].Range[i] -- local frame=Util.GetGameObject(item,"Head/Frame"):GetComponent("Image") -- local icon=Util.GetGameObject(item,"Head/Icon"):GetComponent("Image") -- local name=Util.GetGameObject(item,"Name"):GetComponent("Text") -- local info=Util.GetGameObject(item,"Info"):GetComponent("Text") -- frame.sprite=self.spLoader:LoadSprite(GetQuantityImageByquality(itemConfig[_heroId].Quantity)) -- icon.sprite=self.spLoader:LoadSprite(GetResourcePath(itemConfig[_heroId].ResourceID)) -- name.text=GetLanguageStrById(itemConfig[_heroId].Name) -- info.text=x(i) -- end -- else -- self.scrollView:SetData(equipConfig[soulId].Range,function(index,root) -- self:SetScrollPre(root,equipConfig[soulId].Range[index],index) -- end) -- self.scrollView:SetIndex(1) -- end -- else -- self.scroll_1:SetActive(false) -- self.scroll_2:SetActive(false) -- self.trialScopeText.text = "以下神将可装备:所有神将" -- end self.scroll_1:SetActive(false) self.scroll_2:SetActive(false) if equipConfig[soulId].Describe then self.trialScopeText.text = Language[11175] .. GetLanguageStrById(equipConfig[soulId].Describe) end -- 获取途径 if self.jumpViewList and #self.jumpViewList > 0 then for i = 1, #self.jumpViewList do SubUIManager.Close(self.jumpViewList[i]) end end local curitemData = itemConfig[soulId] self.howGet:SetActive(false) if curitemData and curitemData.Jump then if curitemData.Jump and #curitemData.Jump > 0 then self.howGet:SetActive(true) self.canGetScrollView:SetData(curitemData.Jump, function(index, item) local tempView = SubUIManager.Open(SubUIConfig.JumpView, item.transform, curitemData.Jump[index], true) table.insert(self.jumpViewList, tempView) end, true, true) end end LayoutRebuilder.ForceRebuildLayoutImmediate(self.midBar.transform) LayoutRebuilder.ForceRebuildLayoutImmediate(self.btmBar.transform) LayoutRebuilder.ForceRebuildLayoutImmediate(self.panel.transform) end -- 优化滚动条数据赋值 function GodPrintPopUp:SetScrollPre(root, data, index) local frame = Util.GetGameObject(root, "Head/Frame"):GetComponent("Image") local icon = Util.GetGameObject(root, "Head/Icon"):GetComponent("Image") local name = Util.GetGameObject(root, "Name"):GetComponent("Text") local info = Util.GetGameObject(root, "Info"):GetComponent("Text") frame.sprite = self.spLoader:LoadSprite(GetQuantityImageByquality(itemConfig[data].Quantity)) icon.sprite = self.spLoader:LoadSprite(GetResourcePath(itemConfig[data].ResourceID)) name.text = GetLanguageStrById(itemConfig[data].Name) info.text = x(index) end return GodPrintPopUp