🌟現在、鉄壁 鉄壁ヘッドショットには対応済みです。
鉄壁HSは通常HSと同じダメージになります。LMG及びDMR、チャージライフル、ハンマーポイント弾を除き、すべてのダメージ値が一致していることを確認しています。

「モジュール:WeaponInfobox/Spread」の版間の差分

提供:Apex Data
ナビゲーションに移動 検索に移動
(文字サイズ指定の廃止)
(差分フォーマットの取得関数の引数が間違っていた問題の修正)
 
(同じ利用者による、間の8版が非表示)
4行目: 4行目:
local cfg = mw.loadData('Module:WeaponInfobox/configuration')
local cfg = mw.loadData('Module:WeaponInfobox/configuration')


local aw = require('Module:Utility/Library')
local iu = require('Module:Utility/Image')
local iu = require('Module:Utility/Image')


13行目: 14行目:
and k.air_hip == 0
and k.air_hip == 0
and k.air_ads == 0
and k.air_ads == 0
end
local function isAllSpreadSame(k)
return k.stand_hip_run == k.stand_hip
and k.stand_hip_sprint == k.stand_hip
and k.stand_ads == k.stand_hip
and k.crouch_hip == k.stand_hip
and k.crouch_ads == k.stand_hip
and k.air_hip == k.stand_hip
and k.air_ads == k.stand_hip
end
end


43行目: 54行目:
end
end


local function getFormatStringFunction(stat)
local function getDiffFormatString3(num)
if hasSecondDecimalPlace(stat.stand_hip)
if num == 0 then
or hasSecondDecimalPlace(stat.stand_hip_run)
return '-'
or hasSecondDecimalPlace(stat.stand_hip_sprint)
else
return string.format('%+.3f°', num)
end
end
 
local function getFormatStringFunction(stat, qkdw, hasHipfire)
if (qkdw and hasSecondDecimalPlace(qkdw.stand_hip))
or (qkdw and hasSecondDecimalPlace(qkdw.stand_hip_run))
or (hasHipfire and hasSecondDecimalPlace(stat.stand_hip))
or (hasHipfire and hasSecondDecimalPlace(stat.stand_hip_run))
or (hasHipfire and hasSecondDecimalPlace(stat.stand_hip_sprint))
or hasSecondDecimalPlace(stat.stand_ads)
or hasSecondDecimalPlace(stat.stand_ads)
or hasSecondDecimalPlace(stat.crouch_hip)
or (hasHipfire and hasSecondDecimalPlace(stat.crouch_hip))
or hasSecondDecimalPlace(stat.crouch_ads)
or hasSecondDecimalPlace(stat.crouch_ads)
or hasSecondDecimalPlace(stat.air_hip)
or (hasHipfire and hasSecondDecimalPlace(stat.air_hip))
or hasSecondDecimalPlace(stat.air_ads)
or hasSecondDecimalPlace(stat.air_ads)
or hasSecondDecimalPlace(stat.max_kick.stand_hip)
or (hasHipfire and hasSecondDecimalPlace(stat.max_kick.stand_hip))
or hasSecondDecimalPlace(stat.max_kick.stand_ads)
or hasSecondDecimalPlace(stat.max_kick.stand_ads)
or hasSecondDecimalPlace(stat.max_kick.crouch_hip)
or (hasHipfire and hasSecondDecimalPlace(stat.max_kick.crouch_hip))
or hasSecondDecimalPlace(stat.max_kick.crouch_ads)
or hasSecondDecimalPlace(stat.max_kick.crouch_ads)
or hasSecondDecimalPlace(stat.max_kick.air_hip)
or (hasHipfire and hasSecondDecimalPlace(stat.max_kick.air_hip))
or hasSecondDecimalPlace(stat.max_kick.air_ads) then
or hasSecondDecimalPlace(stat.max_kick.air_ads) then
return getFormatString2
return getFormatString2
64行目: 85行目:
end
end


local function getDiffFormatStringFunction(stat)
local function getDiffFormatStringFunction(stat, lsrs, hasHipfire)
if hasSecondDecimalPlace(stat.kick_on_fire.stand_hip)
if (hasHipfire and hasSecondDecimalPlace(stat.kick_on_fire.stand_hip))
or hasSecondDecimalPlace(stat.kick_on_fire.stand_ads)
or hasSecondDecimalPlace(stat.kick_on_fire.stand_ads)
or hasSecondDecimalPlace(stat.kick_on_fire.crouch_hip)
or (hasHipfire and hasSecondDecimalPlace(stat.kick_on_fire.crouch_hip))
or hasSecondDecimalPlace(stat.kick_on_fire.crouch_ads)
or hasSecondDecimalPlace(stat.kick_on_fire.crouch_ads)
or hasSecondDecimalPlace(stat.kick_on_fire.air_hip)
or (hasHipfire and hasSecondDecimalPlace(stat.kick_on_fire.air_hip))
or hasSecondDecimalPlace(stat.kick_on_fire.air_ads) then
or hasSecondDecimalPlace(stat.kick_on_fire.air_ads) then
if lsrs then
return getDiffFormatString3
else
return getDiffFormatString2
end
elseif lsrs then
return getDiffFormatString2
return getDiffFormatString2
else
else
77行目: 104行目:
end
end


function p.renderSpread(stat, quickdraw_holster, lang)
local function renderKickOnFireCell(row, stat, target, env)
local base = stat[target]
row:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(env.getFormatString(stat[target]))
if not env.hideKickOnFire then
local incr = stat.kick_on_fire[target]
if incr == 0 then
row:tag('td')
:addClass('disabled')
:attr('align', 'center')
:attr('colspan', 2)
:wikitext(env.cfg.na)
else
row
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(env.getDiffFormatString(incr))
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(env.getFormatString(base + stat.max_kick[target]))
end
end
end
 
local lazerSightRatio = { 0.8, 0.6, 0.4 }
local function renderLazerRow(tbl, stat, level, colspan, env, target, target2)
local mul = lazerSightRatio[level]
local lazerhip = tbl:tag('tr')
:tag('th')
:css('border-top', '0 none transparent')
:wikitext('  ')
:done()
:tag('th')
:attrIf(colspan > 1, { colspan = colspan })
:wikitext(iu.attachment('レーザーサイト', level))
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(env.getFormatString(mul * stat[target]))
:done()
if not env.hideKickOnFire then
lazerhip
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(env.getDiffFormatString(mul * stat.kick_on_fire[target2 or target]))
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(env.getFormatString(mul * (stat[target] + stat.max_kick[target2 or target])))
end
end
local function renderLazerRows(tbl, stat, colspan, env, target, target2)
renderLazerRow(tbl, stat, 1, colspan, env, target, target2)
renderLazerRow(tbl, stat, 2, colspan, env, target, target2)
renderLazerRow(tbl, stat, 3, colspan, env, target, target2)
end
 
function p.renderSpread(stat, lazer_sight, quickdraw_holster, lang)
local spread = cfg[lang].spread
local spread = cfg[lang].spread
local getFormatString = getFormatStringFunction(stat)
local hasHipfire = aw.isNumberAndGreaterThanOrEqualToZero(stat.stand_hip)
local getDiffFormatString = getDiffFormatStringFunction(stat)
local getFormatString = getFormatStringFunction(stat, quickdraw_holster, hasHipfire)
local getDiffFormatString = getDiffFormatStringFunction(stat, lazer_sight, hasHipfire)
local layout
local layout
if quickdraw_holster then
if lazer_sight then
layout = {
state_colspan  = 4,
hip_rowspan    = 20,
stand_rowspan  = 12,
hipads_colspan = 3,
concat_incr    = false,
}
elseif quickdraw_holster then
layout = {
layout = {
state_colspan  = 4,
state_colspan  = 4,
88行目: 188行目:
stand_rowspan  = 5,
stand_rowspan  = 5,
hipads_colspan = 3,
hipads_colspan = 3,
concat_incr    = true,
}
}
else
else
95行目: 196行目:
stand_rowspan  = 3,
stand_rowspan  = 3,
hipads_colspan = 2,
hipads_colspan = 2,
concat_incr    = true,
}
}
end
local hideKickOnFire = isAllKickOnFireZero(stat.kick_on_fire)
local env = {
cfg                = spread,
hideKickOnFire      = hideKickOnFire,
getFormatString    = getFormatString,
getDiffFormatString = getDiffFormatString,
}
if hideKickOnFire and isAllSpreadSame(stat) then
return mw.html.create('span')
:wikitext(getFormatString(stat.stand_hip))
end
end
110行目: 224行目:
:done()
:done()
local hideKickOnFire = isAllKickOnFireZero(stat.kick_on_fire)
if not hideKickOnFire then
if not hideKickOnFire then
header:tag('th')
header:tag('th')
120行目: 233行目:
-- Hipfire
-- Hipfire
local hipfire = tbl:tag('tr')
if hasHipfire then
:tag('th')
local hipfire = tbl:tag('tr')
:addClass(spread.state.hip_class)
:tag('th')
:attr('rowspan', layout.hip_rowspan)
:addClass(spread.state.hip_class)
:tag('span')
:attr('rowspan', layout.hip_rowspan)
:wikitext(spread.state.hip)
:tag('span')
:wikitext(spread.state.hip)
:done()
:done()
:done()
:done()
:tag('th')
:tag('th')
:addClass(spread.state.stand_class)
:addClass(spread.state.stand_class)
:attr('rowspan', layout.stand_rowspan)
:attr('rowspan', layout.stand_rowspan)
:tag('span')
:tag('span')
:wikitext(spread.state.stand)
:wikitext(spread.state.stand)
:done()
:done()
:done()
:done()
:tag('th')
:tag('th')
:attrIf(lazer_sight or quickdraw_holster, { colspan = 2 })
:attrIf(quickdraw_holster, { colspan = 2 })
:wikitext(spread.state.still)
:cssIf(quickdraw_holster, { ['border-bottom'] = '0 none transparent' })
:wikitext(spread.state.still)
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip))
:done()
if not hideKickOnFire then
hipfire
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:attr('rowspan', layout.stand_rowspan)
:wikitext(getDiffFormatString(stat.kick_on_fire.stand_hip))
:done()
:done()
:tag('td')
:tag('td')
:addClass('cell-type-number')
:addClass('cell-type-number')
:attr('align', 'right')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip + stat.max_kick.stand_hip))
:wikitext(getFormatString(stat.stand_hip))
end
if quickdraw_holster then
local quickhip = tbl:tag('tr')
:tag('th')
:css('border-top', '0 none transparent')
:wikitext('  ')
:done()
:done()
if not hideKickOnFire then
hipfire
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:attrIf(layout.concat_incr, { rowspan = layout.stand_rowspan })
:wikitext(getDiffFormatString(stat.kick_on_fire.stand_hip))
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip + stat.max_kick.stand_hip))
end
if lazer_sight then
renderLazerRows(tbl, stat, 1, env, 'stand_hip')
elseif quickdraw_holster then
local quickhip = tbl:tag('tr')
:tag('th')
:css('border-top', '0 none transparent')
:wikitext('  ')
:done()
:tag('th')
:wikitext(iu.hopup('quickdraw_holster'))
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(quickdraw_holster.stand_hip))
:done()
if not hideKickOnFire then
if not layout.concat_incr then
quickhip:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getDiffFormatString(stat.kick_on_fire.stand_hip))
end
quickhip:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(quickdraw_holster.stand_hip + stat.max_kick.stand_hip))
end
end
local run = tbl:tag('tr')
:tag('th')
:tag('th')
:wikitext(iu.hopup('quickdraw_holster'))
:attrIf(lazer_sight or quickdraw_holster, { colspan = 2 })
:wikitext(spread.state.run)
:done()
:done()
:tag('td')
:tag('td')
:addClass('cell-type-number')
:addClass('cell-type-number')
:attr('align', 'right')
:attr('align', 'right')
:wikitext(getFormatString(quickdraw_holster.stand_hip))
:wikitext(getFormatString(stat.stand_hip_run))
:done()
:done()
if not hideKickOnFire then
if not hideKickOnFire then
quickhip:tag('td')
if not layout.concat_incr then
run:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getDiffFormatString(stat.kick_on_fire.stand_hip))
end
run:tag('td')
:addClass('cell-type-number')
:addClass('cell-type-number')
:attr('align', 'right')
:attr('align', 'right')
:wikitext(getFormatString(quickdraw_holster.stand_hip + stat.max_kick.stand_hip))
:wikitext(getFormatString(stat.stand_hip_run + stat.max_kick.stand_hip))
end
if lazer_sight then
renderLazerRows(tbl, stat, 1, env, 'stand_hip_run', 'stand_hip')
elseif quickdraw_holster then
local quickrun = tbl:tag('tr')
:tag('th')
:css('border-top', '0 none transparent')
:wikitext('  ')
:done()
:tag('th')
:wikitext(iu.hopup('quickdraw_holster'))
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(quickdraw_holster.stand_hip_run))
:done()
if not hideKickOnFire then
if not layout.concat_incr then
quickrun:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getDiffFormatString(stat.kick_on_fire.stand_hip))
end
quickrun:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(quickdraw_holster.stand_hip_run + stat.max_kick.stand_hip))
end
end
end
end
local sprint = tbl:tag('tr')
local run = tbl:tag('tr')
:tag('th')
:attrIf(quickdraw_holster, { colspan = 2 })
:cssIf(quickdraw_holster, { ['border-bottom'] = '0 none transparent' })
:wikitext(spread.state.run)
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip_run))
:done()
if not hideKickOnFire then
run:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip_run + stat.max_kick.stand_hip))
end
if quickdraw_holster then
local quickrun = tbl:tag('tr')
:tag('th')
:css('border-top', '0 none transparent')
:wikitext('  ')
:done()
:tag('th')
:tag('th')
:wikitext(iu.hopup('quickdraw_holster'))
:attrIf(lazer_sight or quickdraw_holster, { colspan = 2 })
:wikitext(spread.state.sprint)
:done()
:done()
:tag('td')
:tag('td')
:addClass('cell-type-number')
:addClass('cell-type-number')
:attr('align', 'right')
:attr('align', 'right')
:wikitext(getFormatString(quickdraw_holster.stand_hip_run))
:wikitext(getFormatString(stat.stand_hip_sprint))
:done()
:done()
if not hideKickOnFire then
if not hideKickOnFire then
quickrun:tag('td')
if not layout.concat_incr then
sprint:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getDiffFormatString(stat.kick_on_fire.stand_hip))
end
sprint:tag('td')
:addClass('cell-type-number')
:addClass('cell-type-number')
:attr('align', 'right')
:attr('align', 'right')
:wikitext(getFormatString(quickdraw_holster.stand_hip_run + stat.max_kick.stand_hip))
:wikitext(getFormatString(stat.stand_hip_sprint + stat.max_kick.stand_hip))
end
if lazer_sight then
renderLazerRows(tbl, stat, 1, env, 'stand_hip_sprint', 'stand_hip')
end
end
end
local sprint = tbl:tag('tr')
:tag('th')
:attrIf(quickdraw_holster, { colspan = 2 })
:wikitext(spread.state.sprint)
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip_sprint))
:done()
if not hideKickOnFire then
sprint:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip_sprint + stat.max_kick.stand_hip))
end
-- Hipfire while crouching
local crouch = tbl:tag('tr')
:tag('th')
:attr('colspan', layout.hipads_colspan)
:wikitext(spread.state.crouch)
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.crouch_hip))
:done()
if not hideKickOnFire then
-- Hipfire while crouching
crouch
local crouch = tbl:tag('tr')
:tag('td')
:tag('th')
:addClass('cell-type-number')
:attr('colspan', layout.hipads_colspan)
:attr('align', 'right')
:wikitext(spread.state.crouch)
:wikitext(getDiffFormatString(stat.kick_on_fire.crouch_hip))
:done()
:tag('td')
renderKickOnFireCell(crouch, stat, 'crouch_hip', env)
:addClass('cell-type-number')
:attr('align', 'right')
if lazer_sight then
:wikitext(getFormatString(stat.crouch_hip + stat.max_kick.crouch_hip))
renderLazerRows(tbl, stat, layout.hipads_colspan - 1, env, 'crouch_hip')
end
end
-- Hipfire in the air
-- Hipfire in the air
local air = tbl:tag('tr')
local air = tbl:tag('tr')
:tag('th')
:tag('th')
:attr('colspan', layout.hipads_colspan)
:attr('colspan', layout.hipads_colspan)
:wikitext(spread.state.air)
:wikitext(spread.state.air)
:done()
:done()
:tag('td')
renderKickOnFireCell(air, stat, 'air_hip', env)
:addClass('cell-type-number')
:attr('align', 'right')
if lazer_sight then
:wikitext(getFormatString(stat.air_hip))
renderLazerRows(tbl, stat, layout.hipads_colspan - 1, env, 'air_hip')
:done()
end
if not hideKickOnFire then
air:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getDiffFormatString(stat.kick_on_fire.air_hip))
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.air_hip + stat.max_kick.air_hip))
end
end
300行目: 423行目:
:wikitext(spread.state.standcrouch)
:wikitext(spread.state.standcrouch)
:done()
:done()
:tag('td')
renderKickOnFireCell(ads, stat, 'stand_ads', env)
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_ads))
:done()
if not hideKickOnFire then
ads
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getDiffFormatString(stat.kick_on_fire.stand_ads))
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_ads + stat.max_kick.stand_ads))
end
else
else
local hipads = tbl:tag('tr')
local hipads = tbl:tag('tr')
329行目: 437行目:
:wikitext(spread.state.stand)
:wikitext(spread.state.stand)
:done()
:done()
:tag('td')
renderKickOnFireCell(hipads, stat, 'stand_ads', env)
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_ads))
:done()
if not hideKickOnFire then
hipads
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getDiffFormatString(stat.kick_on_fire.stand_ads))
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_ads + stat.max_kick.stand_ads))
end
-- ADS while crouching
-- ADS while crouching
352行目: 445行目:
:wikitext(spread.state.crouch)
:wikitext(spread.state.crouch)
:done()
:done()
:tag('td')
renderKickOnFireCell(crouchads, stat, 'crouch_ads', env)
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.crouch_ads))
:done()
if not hideKickOnFire then
crouchads
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getDiffFormatString(stat.kick_on_fire.crouch_ads))
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.crouch_ads + stat.max_kick.crouch_ads))
end
end
end
376行目: 454行目:
:wikitext(spread.state.air)
:wikitext(spread.state.air)
:done()
:done()
:tag('td')
renderKickOnFireCell(airads, stat, 'air_ads', env)
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.air_ads))
:done()
if not hideKickOnFire then
airads
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getDiffFormatString(stat.kick_on_fire.air_ads))
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.air_ads + stat.max_kick.air_ads))
end
return tbl
return tbl
400行目: 463行目:
local stat = mw.loadData('Module:Stat/Weapon')[name]
local stat = mw.loadData('Module:Stat/Weapon')[name]
local lsrs = stat.attachments.laser_sight
local qkdw = stat.quickdraw_holster and stat.quickdraw_holster.spread
local qkdw = stat.quickdraw_holster and stat.quickdraw_holster.spread
local node = p.renderSpread(stat.spread, qkdw, lang)
local node = p.renderSpread(stat.spread, lsrs, qkdw, lang)
return tostring(node)
return tostring(node)
end
end


return p
return p

2022年8月13日 (土) 12:07時点における最新版

このモジュールについての説明文ページを モジュール:WeaponInfobox/Spread/doc に作成できます

require('Module:Utility/mw.html Extensions')

local p = {}
local cfg = mw.loadData('Module:WeaponInfobox/configuration')

local aw = require('Module:Utility/Library')
local iu = require('Module:Utility/Image')

local function isAllKickOnFireZero(k)
	return k.stand_hip == 0
		and k.stand_ads == 0
		and k.crouch_hip == 0
		and k.crouch_ads == 0
		and k.air_hip == 0
		and k.air_ads == 0
end

local function isAllSpreadSame(k)
	return k.stand_hip_run == k.stand_hip
		and k.stand_hip_sprint == k.stand_hip
		and k.stand_ads == k.stand_hip
		and k.crouch_hip == k.stand_hip
		and k.crouch_ads == k.stand_hip
		and k.air_hip == k.stand_hip
		and k.air_ads == k.stand_hip
end

local function hasSecondDecimalPlace(num)
	return math.floor(10 * num) ~= 10 * num
end

local function getFormatString1(num)
	return string.format('%.1f°', num)
end

local function getFormatString2(num)
	return string.format('%.2f°', num)
end

local function getDiffFormatString1(num)
	if num <= 0 then
		return '-'
	else
		return string.format('%+.1f°', num)
	end
end

local function getDiffFormatString2(num)
	if num == 0 then
		return '-'
	else
		return string.format('%+.2f°', num)
	end
end

local function getDiffFormatString3(num)
	if num == 0 then
		return '-'
	else
		return string.format('%+.3f°', num)
	end
end

local function getFormatStringFunction(stat, qkdw, hasHipfire)
	if (qkdw and hasSecondDecimalPlace(qkdw.stand_hip))
	or (qkdw and hasSecondDecimalPlace(qkdw.stand_hip_run))
	or (hasHipfire and hasSecondDecimalPlace(stat.stand_hip))
	or (hasHipfire and hasSecondDecimalPlace(stat.stand_hip_run))
	or (hasHipfire and hasSecondDecimalPlace(stat.stand_hip_sprint))
	or hasSecondDecimalPlace(stat.stand_ads)
	or (hasHipfire and hasSecondDecimalPlace(stat.crouch_hip))
	or hasSecondDecimalPlace(stat.crouch_ads)
	or (hasHipfire and hasSecondDecimalPlace(stat.air_hip))
	or hasSecondDecimalPlace(stat.air_ads)
	or (hasHipfire and hasSecondDecimalPlace(stat.max_kick.stand_hip))
	or hasSecondDecimalPlace(stat.max_kick.stand_ads)
	or (hasHipfire and hasSecondDecimalPlace(stat.max_kick.crouch_hip))
	or hasSecondDecimalPlace(stat.max_kick.crouch_ads)
	or (hasHipfire and hasSecondDecimalPlace(stat.max_kick.air_hip))
	or hasSecondDecimalPlace(stat.max_kick.air_ads) then
		return getFormatString2
	else
		return getFormatString1
	end
end

local function getDiffFormatStringFunction(stat, lsrs, hasHipfire)
	if (hasHipfire and hasSecondDecimalPlace(stat.kick_on_fire.stand_hip))
	or hasSecondDecimalPlace(stat.kick_on_fire.stand_ads)
	or (hasHipfire and hasSecondDecimalPlace(stat.kick_on_fire.crouch_hip))
	or hasSecondDecimalPlace(stat.kick_on_fire.crouch_ads)
	or (hasHipfire and hasSecondDecimalPlace(stat.kick_on_fire.air_hip))
	or hasSecondDecimalPlace(stat.kick_on_fire.air_ads) then
		if lsrs then
			return getDiffFormatString3
		else
			return getDiffFormatString2
		end
	elseif lsrs then
		return getDiffFormatString2
	else
		return getDiffFormatString1
	end
end

local function renderKickOnFireCell(row, stat, target, env)
	local base = stat[target]
	row:tag('td')
		:addClass('cell-type-number')
		:attr('align', 'right')
		:wikitext(env.getFormatString(stat[target]))
	
	if not env.hideKickOnFire then
		local incr = stat.kick_on_fire[target]
		if incr == 0 then
			row:tag('td')
				:addClass('disabled')
				:attr('align', 'center')
				:attr('colspan', 2)
				:wikitext(env.cfg.na)
		else
			row
				:tag('td')
					:addClass('cell-type-number')
					:attr('align', 'right')
					:wikitext(env.getDiffFormatString(incr))
				:tag('td')
					:addClass('cell-type-number')
					:attr('align', 'right')
					:wikitext(env.getFormatString(base + stat.max_kick[target]))
		end
	end
end

local lazerSightRatio = { 0.8, 0.6, 0.4 }
local function renderLazerRow(tbl, stat, level, colspan, env, target, target2)
	local mul = lazerSightRatio[level]
	local lazerhip = tbl:tag('tr')
		:tag('th')
			:css('border-top', '0 none transparent')
			:wikitext('&nbsp;&nbsp;')
			:done()
		:tag('th')
			:attrIf(colspan > 1, { colspan = colspan })
			:wikitext(iu.attachment('レーザーサイト', level))
			:done()
		:tag('td')
			:addClass('cell-type-number')
			:attr('align', 'right')
			:wikitext(env.getFormatString(mul * stat[target]))
			:done()
	if not env.hideKickOnFire then
		lazerhip
			:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
				:wikitext(env.getDiffFormatString(mul * stat.kick_on_fire[target2 or target]))
			:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
				:wikitext(env.getFormatString(mul * (stat[target] + stat.max_kick[target2 or target])))
	end
end
local function renderLazerRows(tbl, stat, colspan, env, target, target2)
	renderLazerRow(tbl, stat, 1, colspan, env, target, target2)
	renderLazerRow(tbl, stat, 2, colspan, env, target, target2)
	renderLazerRow(tbl, stat, 3, colspan, env, target, target2)
end

function p.renderSpread(stat, lazer_sight, quickdraw_holster, lang)
	local spread = cfg[lang].spread
	local hasHipfire = aw.isNumberAndGreaterThanOrEqualToZero(stat.stand_hip)
	local getFormatString = getFormatStringFunction(stat, quickdraw_holster, hasHipfire)
	local getDiffFormatString = getDiffFormatStringFunction(stat, lazer_sight, hasHipfire)
	local layout
	if lazer_sight then
		layout = {
			state_colspan  = 4,
			hip_rowspan    = 20,
			stand_rowspan  = 12,
			hipads_colspan = 3,
			concat_incr    = false,
		}
	elseif quickdraw_holster then
		layout = {
			state_colspan  = 4,
			hip_rowspan    = 7,
			stand_rowspan  = 5,
			hipads_colspan = 3,
			concat_incr    = true,
		}
	else
		layout = {
			state_colspan  = 3,
			hip_rowspan    = 5,
			stand_rowspan  = 3,
			hipads_colspan = 2,
			concat_incr    = true,
		}
	end
	local hideKickOnFire = isAllKickOnFireZero(stat.kick_on_fire)
	local env = {
		cfg                 = spread,
		hideKickOnFire      = hideKickOnFire,
		getFormatString     = getFormatString,
		getDiffFormatString = getDiffFormatString,
	}
	
	if hideKickOnFire and isAllSpreadSame(stat) then
		return mw.html.create('span')
			:wikitext(getFormatString(stat.stand_hip))
	end
	
	local tbl = mw.html.create('table')
		:addClass('intable')
	
	local header = tbl:tag('tr')
		:tag('th')
			:attr('colspan', layout.state_colspan)
			:wikitext(spread.state.name)
			:done()
		:tag('th')
			:wikitext(spread.first_shot)
			:done()
	
	if not hideKickOnFire then
		header:tag('th')
				:wikitext(spread.increment)
				:done()
			:tag('th')
				:wikitext(spread.maximum)
	end
	
	-- Hipfire
	if hasHipfire then
		local hipfire = tbl:tag('tr')
			:tag('th')
				:addClass(spread.state.hip_class)
				:attr('rowspan', layout.hip_rowspan)
				:tag('span')
					:wikitext(spread.state.hip)
					:done()
				:done()
			:tag('th')
				:addClass(spread.state.stand_class)
				:attr('rowspan', layout.stand_rowspan)
				:tag('span')
					:wikitext(spread.state.stand)
					:done()
				:done()
			:tag('th')
				:attrIf(lazer_sight or quickdraw_holster, { colspan = 2 })
				:wikitext(spread.state.still)
				:done()
			:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
				:wikitext(getFormatString(stat.stand_hip))
				:done()
		if not hideKickOnFire then
			hipfire
				:tag('td')
					:addClass('cell-type-number')
					:attr('align', 'right')
					:attrIf(layout.concat_incr, { rowspan = layout.stand_rowspan })
					:wikitext(getDiffFormatString(stat.kick_on_fire.stand_hip))
					:done()
				:tag('td')
					:addClass('cell-type-number')
					:attr('align', 'right')
					:wikitext(getFormatString(stat.stand_hip + stat.max_kick.stand_hip))
		end
		
		if lazer_sight then
			renderLazerRows(tbl, stat, 1, env, 'stand_hip')
		elseif quickdraw_holster then
			local quickhip = tbl:tag('tr')
				:tag('th')
					:css('border-top', '0 none transparent')
					:wikitext('&nbsp;&nbsp;')
					:done()
				:tag('th')
					:wikitext(iu.hopup('quickdraw_holster'))
					:done()
				:tag('td')
					:addClass('cell-type-number')
					:attr('align', 'right')
					:wikitext(getFormatString(quickdraw_holster.stand_hip))
					:done()
			if not hideKickOnFire then
				if not layout.concat_incr then
					quickhip:tag('td')
						:addClass('cell-type-number')
						:attr('align', 'right')
						:wikitext(getDiffFormatString(stat.kick_on_fire.stand_hip))
				end
				quickhip:tag('td')
					:addClass('cell-type-number')
					:attr('align', 'right')
					:wikitext(getFormatString(quickdraw_holster.stand_hip + stat.max_kick.stand_hip))
			end
		end
		
		local run = tbl:tag('tr')
			:tag('th')
				:attrIf(lazer_sight or quickdraw_holster, { colspan = 2 })
				:wikitext(spread.state.run)
				:done()
			:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
				:wikitext(getFormatString(stat.stand_hip_run))
				:done()
		if not hideKickOnFire then
			if not layout.concat_incr then
				run:tag('td')
					:addClass('cell-type-number')
					:attr('align', 'right')
					:wikitext(getDiffFormatString(stat.kick_on_fire.stand_hip))
			end
			run:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
				:wikitext(getFormatString(stat.stand_hip_run + stat.max_kick.stand_hip))
		end
		
		if lazer_sight then
			renderLazerRows(tbl, stat, 1, env, 'stand_hip_run', 'stand_hip')
		elseif quickdraw_holster then
			local quickrun = tbl:tag('tr')
				:tag('th')
					:css('border-top', '0 none transparent')
					:wikitext('&nbsp;&nbsp;')
					:done()
				:tag('th')
					:wikitext(iu.hopup('quickdraw_holster'))
					:done()
				:tag('td')
					:addClass('cell-type-number')
					:attr('align', 'right')
					:wikitext(getFormatString(quickdraw_holster.stand_hip_run))
					:done()
			if not hideKickOnFire then
				if not layout.concat_incr then
					quickrun:tag('td')
						:addClass('cell-type-number')
						:attr('align', 'right')
						:wikitext(getDiffFormatString(stat.kick_on_fire.stand_hip))
				end
				quickrun:tag('td')
					:addClass('cell-type-number')
					:attr('align', 'right')
					:wikitext(getFormatString(quickdraw_holster.stand_hip_run + stat.max_kick.stand_hip))
			end
		end
		
		local sprint = tbl:tag('tr')
			:tag('th')
				:attrIf(lazer_sight or quickdraw_holster, { colspan = 2 })
				:wikitext(spread.state.sprint)
				:done()
			:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
				:wikitext(getFormatString(stat.stand_hip_sprint))
				:done()
		if not hideKickOnFire then
			if not layout.concat_incr then
				sprint:tag('td')
					:addClass('cell-type-number')
					:attr('align', 'right')
					:wikitext(getDiffFormatString(stat.kick_on_fire.stand_hip))
			end
			sprint:tag('td')
				:addClass('cell-type-number')
				:attr('align', 'right')
				:wikitext(getFormatString(stat.stand_hip_sprint + stat.max_kick.stand_hip))
		end
		
		if lazer_sight then
			renderLazerRows(tbl, stat, 1, env, 'stand_hip_sprint', 'stand_hip')
		end
		
		-- Hipfire while crouching
		local crouch = tbl:tag('tr')
			:tag('th')
				:attr('colspan', layout.hipads_colspan)
				:wikitext(spread.state.crouch)
				:done()
		renderKickOnFireCell(crouch, stat, 'crouch_hip', env)
		
		if lazer_sight then
			renderLazerRows(tbl, stat, layout.hipads_colspan - 1, env, 'crouch_hip')
		end
		
		-- Hipfire in the air
		local air = tbl:tag('tr')
			:tag('th')
				:attr('colspan', layout.hipads_colspan)
				:wikitext(spread.state.air)
				:done()
		renderKickOnFireCell(air, stat, 'air_hip', env)
		
		if lazer_sight then
			renderLazerRows(tbl, stat, layout.hipads_colspan - 1, env, 'air_hip')
		end
	end
	
	-- ADS
	if stat.stand_ads == stat.crouch_ads
		and stat.kick_on_fire.stand_ads == stat.kick_on_fire.crouch_ads
		and stat.max_kick.stand_ads == stat.max_kick.crouch_ads then
		local ads = tbl:tag('tr')
			:tag('th')
				:addClass(spread.state.ads_class)
				:attr('rowspan', 3)
				:tag('span')
					:wikitext(spread.state.ads)
					:done()
				:done()
			:tag('th')
				:attr('colspan', layout.hipads_colspan)
				:wikitext(spread.state.standcrouch)
				:done()
		renderKickOnFireCell(ads, stat, 'stand_ads', env)
	else
		local hipads = tbl:tag('tr')
			:tag('th')
				:addClass(spread.state.ads_class)
				:attr('rowspan', 3)
				:tag('span')
					:wikitext(spread.state.ads)
					:done()
				:done()
			:tag('th')
				:attr('colspan', layout.hipads_colspan)
				:wikitext(spread.state.stand)
				:done()
		renderKickOnFireCell(hipads, stat, 'stand_ads', env)
		
		-- ADS while crouching
		local crouchads = tbl:tag('tr')
			:tag('th')
				:attr('colspan', layout.hipads_colspan)
				:wikitext(spread.state.crouch)
				:done()
		renderKickOnFireCell(crouchads, stat, 'crouch_ads', env)
	end
	
	-- ADS in the air
	local airads = tbl:tag('tr')
		:tag('th')
			:attr('colspan', layout.hipads_colspan)
			:wikitext(spread.state.air)
			:done()
	renderKickOnFireCell(airads, stat, 'air_ads', env)
	
	return tbl
end

function p._main(name, lang)
	lang = lang or 'ja'
	
	local stat = mw.loadData('Module:Stat/Weapon')[name]
	local lsrs = stat.attachments.laser_sight
	local qkdw = stat.quickdraw_holster and stat.quickdraw_holster.spread
	local node = p.renderSpread(stat.spread, lsrs, qkdw, lang)
	return tostring(node)
end

return p