Модуль:Таблица разрушаемости

Материал из Playzone Minecraft Wiki
Версия от 23:14, 19 ноября 2016; Atributz (обсуждение)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Для документации этого модуля может быть создана страница Модуль:Таблица разрушаемости/doc

local p = {}
p.row = function( f )
	local args = require( [[Модуль:ProcessArgs]] ).norm()
	
	if (args[1] == '') or (args[1] == nil) then
		args[1] = mw.title.getCurrentTitle().text
		args["встолбик"] = 1
	end

	if (args[2] == '') or (args[2] == nil) then
		local firstblock = mw.ustring.gsub(mw.ustring.lower(mw.text.trim( mw.text.split(args[1],'[,;]')[1] or '' )), "[_%(%)%-%s]+", '')

		local deftool = f:callParserFunction( '#dplvar', 'blocktool' )
		if (deftool ~= nil) and (deftool ~= '') then
			local p = mw.text.split(mw.ustring.lower(deftool),'%s* %s*')
			if p[2] == nil then
				if p[1] == 'ножницы' then
					args["ножницы"] = 1
				elseif p[1] == 'меч' then
					args["меч"] = 1
				else
					args[2] = mw.ustring.upper(mw.ustring.sub( p[1], 1,1 ))..mw.ustring.sub( p[1], 2 )
					args[3] = 'Любое'
				end
			else
				args[2] = mw.ustring.upper(mw.ustring.sub( p[2], 1,1 ))..mw.ustring.sub( p[2], 2 )
				args[3] = mw.ustring.upper(mw.ustring.sub( p[1], 1,1 ))..mw.ustring.sub( p[1], 2 )
			end
		end
	end

	local getDplVar = function( var )
		local val = f:callParserFunction( '#dplvar', 'breaking ' .. var )
		if val == '' then
			val = false
		end
		return val
	end
	local dplVars = {}
	local setDplVar = function( var, val )
		table.insert( dplVars, 'breaking ' .. var )
		table.insert( dplVars, val or '1' )
	end
	
	local breakingTimeHeader = 'Время [[Добыча|разрушения]]' .. f:preprocess( '<ref group="note">Время для незачарованных инструментов в секундах.</ref>' )
	
	local rows = {}
	local tableParts = {}
	local categories = {}
	
	local horizontal
	if args["встолбик"] or args[1]:match( ';' ) then
		horizontal = true
	end
	local showTool = true
	local showShears = true
	local showSword = true
	local header, sortable, simple
	if horizontal or not getDplVar( 'header' ) then
		if args["скрытьинструмент"] or horizontal and ( not args[2] or mw.ustring.lower(args[2]) == 'любое' or mw.ustring.lower(args[2]) == 'нет' ) then
			showTool = false
			setDplVar( 'hidetool' )
		end
		if args["скрытьножницы"] or horizontal and not args["ножницы"] then
			showShears = false
			setDplVar( 'hideshears' )
		end
		if args["скрытьмеч"] or horizontal and not args["меч"] then
			showSword = false
			setDplVar( 'hidesword' )
		end
		
		sortable = not horizontal and args["сортировка"]
		if sortable then
			setDplVar( 'sortable' )
		end
		simple = args["простой"]
		if simple and not horizontal then
			setDplVar( 'simple' )
		end
		
		local tableClasses = { 'wikitable' }
		if sortable then
			table.insert( tableClasses, 'sortable' )
		end
		table.insert( rows, ' {| class="' .. table.concat( tableClasses, ' ' ) .. '" style="text-align:center"' )
		
		local sortType = ''
		if sortable then
			sortType = 'data-sort-type="number"'
		end
		local rowspan = ''
		if not horizontal then
			rowspan = 'rowspan="2" '
		end
		header = {
			'! ' .. rowspan .. ' | Блок'
		}
		
		if not simple then
			table.insert( header, '! ' .. rowspan .. sortType .. ' | Прочность' )
			if showTool then
				table.insert( header, '! ' .. rowspan .. ' | Инструмент' )
			end
		end
		
		local toolColumns = {}
		if showTool then
			local firsttool = mw.text.trim( simple and 'Инструмент' or args[2] or 'Любое' ):gsub( '^%l', string.upper )
			firsttool = mw.text.split( firsttool, ';' )[1]
			if firsttool == 'Кирка' or firsttool == 'Лопата' then
				toolColumns = { 'Деревянная', 'Каменная', 'Железная', 'Алмазная', 'Золотая' }
			else
				toolColumns = { 'Деревянный', 'Каменный', 'Железный', 'Алмазный', 'Золотой' }
			end
		end
		table.insert(
			toolColumns, 1,
			'<abbr title="Сюда также относятся варианты, когда игрок использует неподходящие инструменты или предметы, не являющиеся инструментами.">Рука</abbr>'
		)
		if not simple then
			if showShears then
				table.insert( toolColumns, 'Ножницы' )
			end
			if showSword then
				table.insert( toolColumns, 'Меч' )
			end
		end
		
		if not horizontal then
			table.insert( header, '! colspan="' .. #toolColumns .. '" |' .. breakingTimeHeader )
			table.insert( header, '|-' )
		end
		
		for _, tool in ipairs( toolColumns ) do
			table.insert( header, '! ' .. sortType .. ' | ' .. tool )
		end
		
		if not horizontal then
			header = table.concat( header, '\n' )
			setDplVar( 'header', header )
		end
		table.insert( tableParts, header )
	else
		showTool = not getDplVar( 'hidetool' )
		showShears = not getDplVar( 'hideshears' )
		showSword = not getDplVar( 'hidesword' )
		sortable = getDplVar( 'sortable' )
		simple = getDplVar( 'simple' )
	end
	
	local sprite = require( [[Модуль:Спрайт]] )
	local hardness = require( [[Модуль:Значения блоков]] ).value
	
	local fillCells = function( cellsTable, text, num )
		for i = 1, num do
			table.insert( cellsTable, text )
		end
	end
	local materialGrade = {
		["Любая"] = 0, ["Любой"] = 0, ["Любое"] = 0,
		["Деревянная"] = 1, ["Деревянный"] = 1,
		["Золотая"] = 1, ["Золотой"] = 1,
		["Каменная"] = 2, ["Каменный"] = 2,
		["Железная"] = 3, ["Железный"] = 3,
		["Алмазная"] = 4, ["Алмазный"] = 4,
		["Нет"] = 5
	}
	local materialSpeed = {
		["Нет"] = 1,
		["Любая"] = 1, ["Любой"] = 1, ["Любое"] = 1,
		["Деревянная"] = 2, ["Деревянный"] = 2,
		["Каменная"] = 4, ["Каменный"] = 4,
		["Железная"] = 6, ["Железный"] = 6,
		["Алмазная"] = 8, ["Алмазный"] = 8,
		["Золотая"] = 12, ["Золотой"] = 12
	}
	local insertBlock = function( blockArgs )
		local cells = {}
		local blocks = mw.text.split( blockArgs[1], '%s*,%s*' )
		local hardnessVal = tonumber( hardness{ blocks[1], ["тип"] = 'прочности' } )
		if not hardnessVal then
			hardnessVal = '?'
		end
		local unbreakable
		if hardnessVal == -1 or blockArgs.liquid then
			unbreakable = true
		end
		

		local blockSprites = {}
		local links = mw.text.split( blockArgs["ссылка"] or '', '%s*,%s*' )
		local ids = mw.text.split( blockArgs["спрайт"] or '', '%s*,%s*' )
		local items = mw.text.split( blockArgs["предмет"] or '', '%s*,%s*' )
		for i, block in ipairs( blocks ) do
			local link
			if not links[i] and links[1] ~= '' then
				link = links[1]
			elseif links[i] ~= '' then
				link = links[i]
			end
			local id
			if not ids[i] and ids[1] ~= '' then
				id = ids[1]
			elseif ids[i] ~= '' then
				id = ids[i]
			end
			local blockText
			if args["сократить"] then
				blockText = block:gsub( args["сократить"] .. '$', '' )
			else
				blockText = block
			end
			local blockSpriteArgs = {
				["настройки"] = 'БлокСпрайт',
				block,
				["текст"] = blockText,
				["ссылка"] = link,
				["ID"] = id
			}
			if items[i] == '1' or not items[i] and items[1] == '1' then
				blockSpriteArgs.settings = 'ПредметСпрайт'
			end
			
			local image, spriteCat = sprite.link( blockSpriteArgs )
			table.insert( blockSprites, image )
			table.insert( categories, spriteCat )
		end
		table.insert( cells,
			'! style="text-align:left" | ' .. table.concat( blockSprites, '<br>' ) .. ( blockArgs["прим"] or '' )
		)

		local tool = mw.text.trim( simple and 'Инструмент' or blockArgs[2] or 'Любое' ):gsub( '^%l', string.upper )
		local material = mw.text.trim( simple and blockArgs[2] or blockArgs[3] or 'Любое' ):gsub( '^%l', string.upper )
		if tool == 'Нет' then
			material = tool
		end
		if not simple then
			local hardnessText = hardnessVal
			if hardnessVal == -1 then
				hardnessText = ( sortable and 'data-sort-value="999" | ' or '' ) .. '∞'
			end
			table.insert( cells, '|' .. hardnessText )
			
			if showTool then
				local toolCell = '—'
				if tool ~= 'Любое' and tool ~= 'Нет' then
					local toolName = ( material ~= 'Любое' and material .. ' ' or '' ) .. tool
					local ftoolName = toolName
					if material == 'Любое' then
						if tool == 'Кирка' then
							ftoolName = 'Деревянная кирка'
						end
						if tool == 'Топор' then
							ftoolName = 'Деревянный топор'
						end
						if tool == 'Лопата' then
							ftoolName = 'Деревянная лопата'
						end
					end
					local image, spriteCat = sprite.sprite{
						["настройки"] = 'ПредметСпрайт',
						ftoolName,
						["назв"] = toolName,
						["ссылка"] = tool
					}
					toolCell = ( sortable and 'data-sort-value="' .. toolName .. '" |' or '' ) .. image
					table.insert( categories, spriteCat )
				end
				table.insert( cells, '|' .. toolCell )
			end
		end
		
		local choices = {}
		local getChoice = function( choice, text )
			if not choices[choice] then
				choices[choice] = f:expandTemplate{ title = 'Таблица выбора', args = { choice, '' } }
			end
			return choices[choice] .. text
		end
		
		if hardnessVal == '?' then
			fillCells( cells, '|?', 6 )
		else
			local processTime = function( num )
				if num < 0.05 then		-- Blocks have a minimum breaking time of 1 game tick (0.05 seconds)
					num = 0.05
				else					-- And they must be broken in multiples of 1 game tick (0.05 seconds)
					num = math.ceil( num * 20 ) / 20
				end
				return num
			end
			
			if unbreakable then
				table.insert( cells, '| ' .. ( sortable and 'data-sort-value="999" ' or '' ) .. getChoice( 'нет', '∞' ) )
				if showTool then
					fillCells( cells, '|—', 5 )
				end
			else
				local drop = 'да'
				if blockArgs["дроп"] == '0' then
					drop = 'частично'
				end
				local requiredLevel = unbreakable and 999 or materialGrade[material]
				local insertMaterialCell = function( material )
					local willDrop = drop
					if materialGrade[material] < requiredLevel then
						willDrop = 'нет'
					end
					local breakTime = processTime( hardnessVal / materialSpeed[material] * ( willDrop == 'нет' and 5 or 1.5 ) )
					table.insert( cells, '|' .. getChoice( willDrop, breakTime ) )
				end
				
				if not showTool or tool == 'Любое' or tool == 'Нет' then
					insertMaterialCell( 'Любое' )
					if showTool then
						fillCells( cells, '|—', 5 )
					end
				else
					for _, material in ipairs{ 'Любое', 'Деревянный', 'Каменный', 'Железный', 'Алмазный', 'Золотой' } do
						insertMaterialCell( material )
					end
				end
			end
			
			if not simple and ( showShears or showSword ) then
				local tools = {}
				if showShears then
					table.insert( tools, 'Ножницы' )
				end
				if showSword then
					table.insert( tools, 'Меч' )
				end
				if hardnessVal == '?' then
					fillCells( cells, '|?', #tools )
				else
					local toolSpeed = {
						["Ножницы"] = 1,
						["Меч"] = 1.5
					}
					if blocks[1] == 'Шерсть' then
						toolSpeed["Ножницы"] = 5
					elseif blocks[1] == 'Листва' then
						toolSpeed["Ножницы"] = 15
					elseif blocks[1] == 'Паутина' then
						toolSpeed["Меч"] = 15
						toolSpeed["Ножницы"] = 15
					end
					
					for _, tool in ipairs( tools ) do
						local toolDrop = blockArgs[mw.ustring.lower( tool )]
						if not toolDrop then
							table.insert( cells, '|—' )
						else
							local willDrop = 'да'
							if toolDrop == '0' then
								willDrop = 'частично'
							end
							
							local breakTime = processTime( hardnessVal / toolSpeed[tool] * 1.5 )
							table.insert( cells, '|' .. getChoice( willDrop, breakTime ) )
						end
					end
				end
			end
		end
		
		if not horizontal then
			cells = table.concat( cells, '\n' )
		end
		table.insert( tableParts, cells )
	end
	
	if horizontal then
		local blocksArgs = {}
		for _, arg in ipairs{ 1, 'прим', 'спрайт', 'ссылка', 'предмет', 'дроп', 2, 3, 'ножницы', 'меч' } do
			if args[arg] then
				local col = 0
				for colVal in mw.text.gsplit( args[arg], '%s*;%s*' ) do
					col = col + 1
					if colVal ~= '' then
						if not blocksArgs[col] then
							blocksArgs[col] = {}
						end
						
						blocksArgs[col][arg] = colVal
					end
				end
			end
		end
		for _, block in ipairs( blocksArgs ) do
			insertBlock( block )
		end
		
		local columns = #tableParts
		for row = 1, #tableParts[1] do
			local cells = {}
			for col = 1, columns do
				table.insert( cells, tableParts[col][row] )
			end
			table.insert( rows, table.concat( cells, '\n' ) )
		end
		
		-- Insert breaking time header after block row when simple, or after tool or hardness row when not
		table.insert( rows, simple and 3 or showTool and 5 or 4, '! colspan="' .. columns + 1 .. '" |' .. breakingTimeHeader )
	else
		insertBlock( args )
		for _, row in ipairs( tableParts ) do
			table.insert( rows, row )
		end
	end
	table.insert( rows, '' )
	
	local note = ''
	if args["подвал"] or horizontal then
		note = f:preprocess( '<references group="note"/>' )
		
		if args["подвал"] == '2' then
			table.insert( rows, header or getDplVar( 'header' ) )
		end
		table.insert( rows, '|}' )
		
		if not horizontal then
			f:callParserFunction( '#dplvar:set',
				'breaking header', '',
				'breaking hidetool', '',
				'breaking hideshears', '',
				'breaking hidesword', '',
				'breaking simple', '',
				'breaking sortable', ''
			)
		end
	elseif #dplVars > 0 then
		f:callParserFunction( '#dplvar:set', dplVars )
	end
	
	return table.concat( rows, '\n|-\n' ) .. note .. table.concat( categories )
end
return p