本模块用于输出所有物品相关信息


{{#invoke:Item|equip}}
{{#invoke:Item|other}}

输出包含所有物品的Navbox,详见模板:Navbox物品


{{#invoke:Item|link|空手}}

生成带图标的链接,详见模板:Link物品


{{#invoke:Item|main|id=|name=|damage=|distance=|text=|need=}}

利用由mod从游戏中获取的物品文本,二次加工后生成物品页面,并在smw中记录tooltip所需信息,详见物品/空手


local p = {}

local RichTab = require('Module:RichTab').meta
local NavBox = require('Module:Navbox').meta
local Name = mw.loadData("Module:Const/name")
local Make = mw.loadData("Module:Item/make")
local Data = mw.loadData("Module:Item/data")

local MakeSkills = mw.text.split('制木|锻造|制石|织锦|厨艺|医毒', '|', true)
local Immortals = mw.text.split('莫女衣|伏邪铁|大玄凝|凤凰茧|焚神练|解龙魄|溶尘隐|囚魔木|鬼神霞|伏虞剑', '|', true)

local All = Data.data
function getByName(name)
	return All[Data.name[name]]
end

function link(id)
    local item = All[id]
    if item==nil then error(id or 'nil') end
    local name = item.name
    local level = item.data8
    local color = Name.color[level]
    local result = '[[文件:ItemIcon '..item.data98..' 20.png|link=]][['..'物品/'..name..'|<span style="color:'..color..'">'..name..'</span>]]'
    --[=[local brief = mw.smw.ask({'[[Category:物品]]', '[[ID::80209]]','?brief','?ID'})[1]
    if brief then
    	result = '<span class="tooltip1">'..result..'<span class="tooltiptext" style="max-width:200px;text-align: left;">'..brief.Brief..'</span></span>'
    end]=]--
    result = '<div class="huiji-tt" data-type="Item" data-name="'..name..'" style="display:inline-block">'..result..'</div>'
    return result
end

function p.link(frame)
	local args = frame.args or frame
	local id = args[1]
	if id==nil or id=='' or id=='无' then return '无' end
	id = tonumber(id) or Data.name[id]
	if id==nil then
		local name = mw.ustring.gsub(args[1], '^.-·', '', 1)--大玄凝·化形·冰刃 → 化形·冰刃
		id = Data.name[name] 
		if id==nil then error(mw.dumpObject(args)) end
	end
	return link(id)
end

function p.tooltip(frame) --p.tooltip({'离离千世'})
	local args = frame.args or frame
	local name = args[1]
	if name==nil then error(mw.dumpObject(frame)) end
	local id = tonumber(name)
	if id then
		local item = id and All[id]
		name = item.name
	end
	local result = mw.smw.ask({'[[物品/'..name..']]', '?Brief'})[1].Brief
	--mw.logObject(result)
	return result
end

local material = {"织造", "木制", "玉石", "金铁"}
function cmpMakeName(a, b, cnt)
    cnt = cnt or 1
    if cnt >= 4 then --同为金铁,直接比较字符串
        return a < b
    end
    local flag1 = mw.ustring.find(a, material[cnt], 1, true)
    local flag2 = mw.ustring.find(b, material[cnt], 1, true)
    if flag1 and not flag2 then
        return true
    elseif not flag1 and flag2 then
        return false
    elseif flag1 and flag2 then --材质相同,直接比较字符串
        return a < b
    end
    return cmpMakeName(a, b, cnt + 1) --未找到材质,判断下一级
end

function makeLine(id,id2)
    local list = {}
    local cnt = 0
    id2 = id2 or 9
    id2 = id2>id and id2 or id+id2-1
    for j=id,id2 do
        local item = All[j]
        cnt = cnt + 1
        if item==nil then error('无此物品:'..j) end
        list[cnt] = link(j)
    end
    local result = table.concat(list,"·")
    return result
end
function makeLines(list,child)
    local oldLevel = 0
    local newLevel = 0
    local result = {}
    local head
    local tail
    for k,v in pairs(list) do
        local id = v[1]
        newLevel = v[2]
        head = head or id --获取第一个id
        if newLevel < oldLevel or (tail and id~=tail+1) then
            table.insert(result, makeLine(head,tail))
            head = id
        end
        oldLevel = newLevel
        tail = id --记录上一个id
    end
    table.insert(result, makeLine(head,tail))

    local nav = NavBox:new()
    if child then
        nav[1] = 'child'
    end
    for k,v in pairs(result) do
        nav:add(v)
    end
    return tostring(nav)
end

function p.equip(frame)
    local args = frame.args or frame
    local name = args[1]
    
    local make = Make.data
    local makeObjs = {}
    for k, makeTyp in pairs(make) do
        if makeTyp.data97 > 0 then
            local makeObj = {}
            local makeName = makeTyp.data0
            makeObj.name = makeName
            local hard = makeTyp.hard
            local soft = makeTyp.soft
            local first = tonumber(hard[1])
            local itemTyp = All[first].data5 -- 以首个产物的类型来设定该种生产的分类
            makeObj.nav = NavBox:new({above = makeName, [1] = 'child'})
            for i, id in ipairs(hard) do -- 九品~一品 为一行
                id = tonumber(id)
                makeObj.nav:add(makeLine(id), "硬")
            end
            for i, id in ipairs(soft) do
                id = tonumber(id)
                makeObj.nav:add(makeLine(id), "软")
            end
            makeObj.nav = tostring(makeObj.nav)
            if makeObjs[itemTyp] == nil then
                makeObjs[itemTyp] = {}
            end
            table.insert(makeObjs[itemTyp], makeObj)
        end
    end
    make = nil -- 清空物品制造数据
    
    local animal = {}
    animal.name = '动物代步'
    animal.nav = NavBox:new({above = animal.name, [1] = 'child'})
    animal.nav:add(makeLine(83601))
    animal.nav = tostring(animal.nav)
    table.insert(makeObjs[18], animal)
    animal = nil
    
    local uniform = {}
    uniform.name = '门派衣着'
    uniform.nav = NavBox:new({['above'] = uniform.name, [1] = 'child'})
    uniform.nav:add(makeLine(73801), '低阶')
    uniform.nav:add(makeLine(73901), '高阶')
    uniform.nav = tostring(uniform.nav)
    table.insert(makeObjs[17], uniform)
    uniform = nil
    
    local rich = RichTab:new()
    local tabCnt = 0
    for itemTyp, v in pairs(makeObjs) do -- 每种物品类型为一个navBox,并作为richTab的一页
        --按制造类型的名称排序
        table.sort(v , function(a , b)
            return cmpMakeName(a.name, b.name)
        end)
        local page = NavBox:new({
            ['listclass'] = 'hlist',
            ['liststyle'] = 'color:rgb(155,135,115)',
        })
        for i, makeObj in pairs(v) do
            page:add(makeObj.nav)
        end
        makeObjs[itemTyp] = nil --清理
        rich:add(Name.item[itemTyp], page)
    end
    
    local page = NavBox:new({
        ['listclass'] = 'hlist',
        ['liststyle'] = 'color:rgb(155,135,115)',
    })
    local child = NavBox:new({[1]='child', above='机关'})
    child:add(makeLine(40501), '锻造')
    child:add(makeLine(40601), '制木')
    page:add(child)
    child = NavBox:new({[1]='child', above='令符'})
    child:add(makeLine(40701), '制石')
    child:add(makeLine(40801), '织锦')
    page:add(child)
    child = NavBox:new({[1]='child', above='毒器'})
    child:add(makeLine(40301), '炼药')
    child:add(makeLine(40401), '炼毒')
    page:add(child)
    
    rich:add('副产物', page)
    
    return getResult(rich, name)
end

function medChild(above, id1, id2, name1, name2)
	local child = NavBox:new({[1] = 'child'})
    child.above = above
    child:add(makeLine(id1, 6)..'<br/>'..makeLine(id1+6, 6), name1)
    if id2 then
    	child:add(makeLine(id2, 6)..'<br/>'..makeLine(id2+6, 6), name2)
    end
    return child
end
function medicineNav()
    local nav = NavBox:new({
        ['listclass'] = 'hlist',
        ['liststyle'] = 'color:rgb(155,135,115)',
    })
    
    nav:add(medChild('疗伤药',100101,100113,'外伤','内伤'))

    nav:add(medChild('内息药',100125))

    nav:add(medChild('健康药', 100137))

    local child = NavBox:new({[1] = 'child'})
    child.above = '解毒药'
    for i=0,5 do
        child:add(makeLine(100173 + i*2*6,6)..'<br/>'..makeLine(100173+(i*2+1)*6,6), Name.poison[i])
    end
    nav:add(child)

    local child = NavBox:new({[1] = 'child'})
    child.above = '战斗药'
    local itemId = 100149
    child:add(makeLine(itemId,6)..'<br/>'..makeLine(itemId+6,6), '外伤上限')
    itemId = itemId + 12
    child:add(makeLine(itemId,6)..'<br/>'..makeLine(itemId+6,6), '内伤上限')
    itemId = 100245
    for k,v in ipairs({'护体','御气','卸力','拆招','闪避','内息','力道%','提气速度','精妙%','架势速度','迅疾%','造成内外伤',}) do
    	child:add(makeLine(itemId,6)..'<br/>'..makeLine(itemId+6,6), v)
    	itemId = itemId + 12
    end
    nav:add(child)

    return nav
end
function materialNav()
    local name1 = {'硬','软'}
    local name2 = {'木','铁','玉','布'}
    local nav = NavBox:new({
        ['listclass'] = 'hlist',
        ['liststyle'] = 'color:rgb(155,135,115)',
    })
    
    local child = NavBox:new({'child'})
    child.above = '引子'
    for i=1,4 do
        for j=1,2 do
            local itemId = 3001 + (i-1)*100 + (j-1)*7
            child:add(makeLine(itemId, 7), name1[j]..name2[i])
        end
    end
    nav:add(child)

    child = NavBox:new({'child'})
    child.above = '精制'
    for i=1,4 do
        for j=1,2 do
            local itemId = 3501 + (i-1)*100 + (j-1)*7
            child:add(makeLine(itemId, 7), name1[j]..name2[i])
        end
    end
    nav:add(child)
    
    return nav
end
function drinkNav()
    local nav = NavBox:new({
        ['listclass'] = 'hlist',
        ['liststyle'] = 'color:rgb(155,135,115)',
    })
    
    local child = NavBox:new({'child'})
    child.above = '茶'
    child:add(makeLine(100601), '外伤')
    child:add(makeLine(100610), '内伤')
    nav:add(child)
    
    child = NavBox:new({'child'})
    child.above = '酒'
    child:add(makeLine(100501), '破体')
    child:add(makeLine(100510), '破气')
    nav:add(child)
    
    return nav
end
function immortalNav()
    local nav = NavBox:new()
    for i=1,10 do
        local itemId = 110001 + (i-1)
        local sep = '&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;'
        local list = link(itemId)..sep..link(itemId+10)..sep..link(itemId+20)..sep..link(20101+(i-1))
        nav:add(list, Immortals[i])
    end
    return nav
end
function otherNav()
    local nav = NavBox:new()
    nav:add(makeLine(11,15), '资源包')
    nav:add(makeLine(21), '血露')
    nav:add(makeLine(81,99), '促织相关')
    return nav
end
function spNav()
	local nav = NavBox:new()
	nav:add(makeLine(0, 2), '随机应变')
	nav:add(makeLine(5001, 5005), '剧情物品')
	return nav
end

function classify()
    local result = {}
    for id,item in pairs(All) do
        local typ = item.data5
        if(result[typ]==nil) then
            result[typ] = {}
        end
        table.insert(result[typ],{id, item.data8})
    end
    for k,v in pairs(result) do
        table.sort(v , function(a , b)
            return a[1] < b[1]
        end)
    end
    return result
end

function p.others(frame)
    local classified = classify()
    local rich = RichTab:new()
    local args = frame.args or frame
    local name = args[1]
    
    local nav = NavBox:new()
    for i=1,6 do
    	nav:add(makeLine(10001 + (i-1)*100), MakeSkills[i])
    end
    rich:add('工具', nav)
    
    rich:add('材料', materialNav())
    
    local nav = NavBox:new()
    for i=0,5 do
    	nav:add(makeLine(4201+i*7,4207+i*7), Name.poison[i])
    end
    rich:add('毒物', nav)
    
    local nav = NavBox:new()
    for i=0,5 do
    	nav:add(makeLine(100001+i*9), Name.poison[i])
    end
    rich:add('毒药', nav)
    
    rich:add('药材', makeLines(classified[29]))
    rich:add('丹药', medicineNav())
    rich:add('杂物', otherNav())
    rich:add('蛰罐', makeLines(classified[33]))
    rich:add('食材', makeLines(classified[23]))
    rich:add('素食', makeLines(classified[34]))
    rich:add('荤食', makeLines(classified[35]))
    rich:add('神兵', immortalNav())
    rich:add('茶酒', drinkNav())
    rich:add('宝典', makeLines(classified[42]))
    rich:add('特殊', spNav())
    
    return getResult(rich, name)
end

function getResult(rich, name)
	if name then
	    local cnt = rich.cnt
	    local tabBar = rich.tabBar
	    for i=1,cnt do
	    	if tabBar[i].tabName==name then
	    		local result = rich.tabContent[i].tabText
	    		--mw.log(result)
	    		return result
	    	end
	    end
	    return '无此标签'
	end
    return rich
end

local NewLine = '<br/>\n'
local Space = '&nbsp;&nbsp;&nbsp;'
function noNewLine(s)
	if s==nil then return end
	return mw.ustring.gsub(s, NewLine, '', 1)
end
function P(s) return '<p>'..s..'</p>' end
function color(s,c) return '<span style="color:'..c..'">'..s..'</span>' end
function getTitle(s, one)
	local title = mw.ustring.match(s, '【(.-)】')
	if title==nil then return end
	s = mw.ustring.gsub(s, '<span style="color:#B97D4B">【.-】<br/>\n</span>', '', 1)
	--s = mw.ustring.gsub(s, '【.-】<br/>\n', '', 1)
	local newTitle = mw.getCurrentFrame():expandTemplate{ title = 'subtitle', args={title}}..'\n'
	if one then return newTitle..s end
	return title, s, newTitle
end


function moreInfo(itemId)
	local data = Data.data
	local item = data[itemId]
	local brief = {}
	local result = {}
	function add(k,v,tbl) 
		tbl = tbl or result
		if tbl[k]==nil then
			tbl[k] = {}
		end
		table.insert(tbl[k], v)
	end
	
	local level = item.data8
	local typ = item.data5
	
	if item.data50==1 then --可淬毒,可得精制材料
		local id = item.data52
		if id>0 then
			add('生产信息', '精制0~4次拆解可得:'..link(id))
			add('生产信息', '精制5~9次拆解可得:'..link(id+1))
			add('生产信息', '精制10次拆解可得:'..link(id+2))
		end
	end
	--精制效果
	local data51 = item.data51 or 0
	if data51>=101 and data51<=108 then
		local change = mw.loadData("Module:Item/change")
		for k,v in ipairs({'武器', '防具', '饰品'}) do
			local datum = change[data51 + (k-1)*100]
			local power = datum.data3
			power = math.abs(power) * level / datum.data5
			local content = '精制'..v..':'..color(datum.data1..power, Name.color[datum.data97])
			add('生产信息', content)
			table.insert(brief, content)
		end
	end
	--拆解产物
	local data55 = item.data55 or 0
	if data55>0 then
		local content = '拆解可得:'..color((data55*0.8)..'~'..(data55*1.2),'white')..Name.resource[item.data44-1]
		add('生产信息', content)
		if typ==32 then table.insert(brief, content) end
	end
	--制造产物
	local makeId = item.data48
	if typ==28 or typ==29 then --毒物药材
		local product
		local skillName
		local building
		if typ~=29 then
			product = 100001 + (makeId-1)*9 + (level - 2)
			skillName = '毒术'
			building = '血池'
		else
			local make = mw.loadData("Module:Item/medicine")
			local bonus = level/2 - 1
			product = {make[1][makeId] + bonus, make[2][makeId] + bonus}
			skillName = '医术'
			building = '水火青炉'
		end
		local need = {item.data43}
		need[2] = need[1] + level*20
		need[3] = need[2] + (level+1)*20
		for i=1,3 do
			local content = color(need[i], Name.color[3])..skillName
			if i==3 then content = content..'&'..building end
			content = content..':'
			if typ==29 then
				content = content..link(product[1]+i-1)..'|'..link(product[2]+i-1)
			else
				content = content..link(product+i-1)
			end
			add('生产信息', content)
		end
	elseif typ==23 then
		local make = mw.loadData("Module:Item/food")
		local makable = {}
		for i=0,7-level do --根据造诣提高产物品级
			local newId = itemId + i
			local newLevel = level + i
			local unlock = i==0 and 0 or newLevel*60 --解锁三个产物的需求
			local need = {data[newId].data43} --三个产物的字面需求
			need[2] = need[1] + newLevel*20
			need[3] = need[2] + (newLevel + 1)*20
			local content = ''
			local max = i==7-level and 3 or 2
			for j=1,max do --投入资源数量
				local get = make[(item.data54==1 and 'vegetable' or 'meat')][makeId] + i + (j - 1)
				get = link(get)
				local skill = math.max(need[j],unlock)
				add(skill, {j, get}, makable)
			end
		end
		-- 按造诣需求从低到高排序
		local tmp = {}
		for k,v in pairs(makable) do
			table.insert(tmp, {k,v})
		end
		table.sort(tmp, function(a,b) return a[1]<b[1] end)
		-- 输出
		for k,v in ipairs(tmp) do
			local skill = v[1]
			local list = v[2]
			local content = color(skill, Name.color[3])..'厨艺'
			if #list==1 and list[1][1]==3 then content = content..'&香料馆' end
			content = content..':'
			for j,pair in ipairs(list) do
				if j>1 then content = content..'|' end
				content = content..color(pair[1], Name.color[3])..'份资源-'..pair[2]
			end
			add('生产信息', content)
		end
	elseif typ==32 then --杂物
		--血露内力
		local tmp = item.data2012
		if tmp and tmp>0 then
			local content = '内力修为增加:'..color(tmp, Name.color[3])
			add('其他信息', content)
			table.insert(brief, content)
		end
	end
	
	local s = ''
	for k,v in pairs(result) do
		local str = mw.getCurrentFrame():expandTemplate{ title = 'subtitle', args={k}}..'\n'
		for i,line in ipairs(v) do
			str = str..'·'..line..NewLine
		end
		s = s..str
	end
	
	return {s, brief}
end

local briefTitle = {
	['使用效果'] = 1,
	['工具效果'] = 1,
	['战斗效果'] = 1,
	['装备效果'] = 1,
	['衣装造型'] = 1,
	['含有毒素'] = 1
}

function p.main(frame)
	local args = frame.args or frame
	local id = tonumber(args.id)
	local item = Data.data[id]
	local typ = item.data5
	if item==nil then error(args.id..'\n'..type(args.id)) end
	local name = args.name
	local arr = mw.text.split(name, NewLine)
	local level = arr[#arr]
	level = mw.ustring.gsub(level, '【(.-)】', '%1', 1)
	name = arr[1]
	if #arr==3 then name=name..'·'..arr[2] end
	name = '<div style=color:#F28234;font-size:28px;padding:10px>'..'[[文件:ItemIcon '..item.data98..' 40.png|link=]]&nbsp;&nbsp;'..name..'</div>'
	
	local text = args.text..'\n'
	text = mw.text.split(text, NewLine..NewLine)
	if not mw.ustring.find(text[2], '道具类型', 1, true) then --说明可能会有两个回车
		text[1] = text[1]..NewLine..text[2]
		for i=3,#text do
			text[i-1] = text[i]
		end
	end
	--说明
	text[1] = mw.ustring.gsub(text[1], '<span style=".*">(.-)</span>', '%1', 1)
	local des = text[1]
	des = mw.getCurrentFrame():expandTemplate{ title = 'Quote', args={des}}
	--基本信息
	local base = text[2]
	base = mw.ustring.gsub(base, '<span style="color:#B97D4B">【道具类型】<br/>\n</span>', '', 1)
	base = mw.ustring.gsub(base, '·', '')
	base = mw.text.split(base, NewLine) --1为类型,2为耐久,3为材质
	if mw.ustring.find(base[1], '耐久', 1, true) then --随机应变三件套没有类型
		base = {'', base[1], base[2]}
	end
	local brief = base[1]
	base[2] = mw.ustring.gsub(base[2], '(耐久:.-) / %d+', '%1')
	local baseInfo = (base[1]~='' and base[1]..Space or '')..level..Space..base[2]..(base[3] and NewLine..base[3] or '')
	baseInfo = baseInfo..NewLine..'价值:'..color(item.data904 or 0, 'white')..Space..'好感:'..color(item.data102 or 0, 'white')..Space
	local data104 = math.min(item.data104 or 0, 9)
	if data104>0 then
		baseInfo = baseInfo..'可赠'..Name.actorLevel[data104]
	else
		baseInfo = baseInfo..'无法赠送'
	end
	
	local info = ''
	for i=3,#text do
		local s= text[i]
		local title, content, newTitle = getTitle(s)
		--text[i] = {title, content}
		if title then
			s = content
			if title=='兵器属性' then
				local damage = noNewLine(args.damage)
				local distance = noNewLine(args.distance)
				s = '·攻击范围:'..mw.ustring.gsub(distance,'攻击范围:','',1)..NewLine..s
				s = '·伤害:'..mw.ustring.gsub(damage,'伤害:','',1)..NewLine..s
				s = s..NewLine..'·灵活度:'..color(item.data14 or 0,'orange')
				brief = brief..Space..base[2]..NewLine..base[3]..NewLine..s
			elseif briefTitle[title] then
				brief = brief..NewLine..title..':'..NewLine..s
			end
			s = newTitle..s
			info = info..s
		elseif #s>1 then
			info = info..NewLine..s
			brief = brief..NewLine..s
		end
	end
	
	local other = moreInfo(id)
	info = info..other[1]
	
	local need = args.need
	if need then
		need = mw.ustring.gsub(need, '<span style="color:#E4504D">(.)</span>', '%1')
		need = mw.text.split(need, NewLine..NewLine, true)
		for k,v in ipairs(need) do
			local s = getTitle(v, true)
		    info = info..(s or v)..NewLine
		end
	end
	
	local result = name..des..baseInfo..info
	result = '<div style="float:right">基于版本'..NewLine..'V0.2.3.1</div>'..result
	result = '<div style="max-width:400px">'..result..'</div>'
	result = result..'[[Category:物品]][[Category:物品/'..Name.item[item.data5]..']]'
	local tail = mw.getCurrentFrame():expandTemplate{ title = '太吾百晓册'}
	tail = mw.getCurrentFrame():expandTemplate{ title = 'H2', args = {'太吾百晓册', tail}}
	--result = result..NewLine..tail
	
	-- 用smw储存tooltip要显示的信息
	if item.data4==1 then
		if typ==28 or typ==29 or typ==23 then --毒 药 食材
			local tmp = mw.ustring.match(text[1], '((.-))')
			if tmp and #tmp>0 then
				brief = tmp
			end
		else
			local hard = item.data48
			if hard and hard>0 then
				local material = Name.material[typ][hard]
				if material then
					brief = material..'引子'
				end
			else
				local material = Name.material[typ]
				if material then
					material = material[0]
					brief = material..'精制材料'
				end
			end
		end
	end
	if id>=81 and id<=99 or id>=5001 and id<=5005 then brief = text[1] end --蛐蛐周边,剧情物品
	if #other[2]>0 then
		for k,v in ipairs(other[2]) do
			brief = brief..NewLine..v
		end
	end
	mw.smw.set({brief = brief, ID = id})
	mw.log(brief)
	--mw.log(result)
	return result
end

return p
avatar