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

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

提供:Apex Data
ナビゲーションに移動 検索に移動
(ページの作成:「local p = {} local cfg = mw.loadData('Module:WeaponInfobox/configuration') local function isAllKickOnFireZero(k) return k.stand_hip == 0 and k.stand_ads == 0 and k.…」)
 
(差分フォーマットの取得関数の引数が間違っていた問題の修正)
 
(同じ利用者による、間の11版が非表示)
1行目: 1行目:
require('Module:Utility/mw.html Extensions')
local p = {}
local p = {}
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 function isAllKickOnFireZero(k)
local function isAllKickOnFireZero(k)
9行目: 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


39行目: 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
60行目: 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
73行目: 104行目:
end
end


function p.renderSpread(stat, 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
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')
local tbl = mw.html.create('table')
:addClass('intable')
:addClass('intable')
:css('font-size', '92%')
local header = tbl:tag('tr')
local header = tbl:tag('tr')
:tag('th')
:tag('th')
:attr('colspan', 3)
:attr('colspan', layout.state_colspan)
:wikitext(spread.state.name)
:wikitext(spread.state.name)
:done()
:done()
90行目: 224行目:
:done()
:done()
local hideKickOnFire = isAllKickOnFireZero(stat.kick_on_fire)
if not hideKickOnFire then
if not hideKickOnFire then
header:tag('th')
header:tag('th')
100行目: 233行目:
-- Hipfire
-- Hipfire
tbl:tag('tr')
if hasHipfire then
:tag('th')
local hipfire = tbl:tag('tr')
:addClass(spread.state.hip_class)
:tag('th')
:attr('rowspan', 5)
:addClass(spread.state.hip_class)
:tag('span')
:attr('rowspan', layout.hip_rowspan)
:wikitext(spread.state.hip)
: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('  ')
: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('  ')
: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()
:done()
:done()
renderKickOnFireCell(crouch, stat, 'crouch_hip', env)
:tag('th')
:addClass(spread.state.stand_class)
if lazer_sight then
:attr('rowspan', 3)
renderLazerRows(tbl, stat, layout.hipads_colspan - 1, env, 'crouch_hip')
:tag('span')
end
:wikitext(spread.state.stand)
-- Hipfire in the air
local air = tbl:tag('tr')
:tag('th')
:attr('colspan', layout.hipads_colspan)
:wikitext(spread.state.air)
:done()
:done()
:done()
renderKickOnFireCell(air, stat, 'air_hip', env)
:tag('th')
:wikitext(spread.state.still)
if lazer_sight then
:done()
renderLazerRows(tbl, stat, layout.hipads_colspan - 1, env, 'air_hip')
:tag('td')
end
:addClass('cell-type-number')
end
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip))
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:attr('rowspan', 3)
: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))
tbl:tag('tr')
:tag('th')
:wikitext(spread.state.run)
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip_run))
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip_run + stat.max_kick.stand_hip))
tbl:tag('tr')
:tag('th')
:wikitext(spread.state.sprint)
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip_sprint))
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.stand_hip_sprint + stat.max_kick.stand_hip))
-- Hipfire while crouching
tbl:tag('tr')
:tag('th')
:attr('colspan', 2)
:wikitext(spread.state.crouch)
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.crouch_hip))
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getDiffFormatString(stat.kick_on_fire.crouch_hip))
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.crouch_hip + stat.max_kick.crouch_hip))
-- Hipfire in the air
tbl:tag('tr')
:tag('th')
:attr('colspan', 2)
:wikitext(spread.state.air)
:done()
:tag('td')
:addClass('cell-type-number')
:attr('align', 'right')
:wikitext(getFormatString(stat.air_hip))
:done()
: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))
-- ADS
-- ADS
206行目: 411行目:
and stat.kick_on_fire.stand_ads == stat.kick_on_fire.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
and stat.max_kick.stand_ads == stat.max_kick.crouch_ads then
tbl:tag('tr')
local ads = tbl:tag('tr')
:tag('th')
:tag('th')
:addClass(spread.state.ads_class)
:addClass(spread.state.ads_class)
215行目: 420行目:
:done()
:done()
:tag('th')
:tag('th')
:attr('colspan', 2)
:attr('colspan', layout.hipads_colspan)
: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()
: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))
else
else
tbl:tag('tr')
local hipads = tbl:tag('tr')
:tag('th')
:tag('th')
:addClass(spread.state.ads_class)
:addClass(spread.state.ads_class)
241行目: 434行目:
:done()
:done()
:tag('th')
:tag('th')
:attr('colspan', 2)
:attr('colspan', layout.hipads_colspan)
: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()
: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))
-- ADS while crouching
-- ADS while crouching
tbl:tag('tr')
local crouchads = tbl:tag('tr')
:tag('th')
:tag('th')
:attr('colspan', 2)
:attr('colspan', layout.hipads_colspan)
: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()
: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
-- ADS in the air
-- ADS in the air
tbl:tag('tr')
local airads = tbl:tag('tr')
:tag('th')
:tag('th')
:attr('colspan', 2)
:attr('colspan', layout.hipads_colspan)
: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()
: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))
return tbl
return tbl
305行目: 462行目:
lang = lang or 'ja'
lang = lang or 'ja'
local stat = mw.loadData('Module:Stat/Weapon')[name].spread
local stat = mw.loadData('Module:Stat/Weapon')[name]
local node = p.renderSpread(stat, lang)
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)
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