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

「モジュール:Utility/ApexLibrary」の版間の差分

提供:Apex Data
ナビゲーションに移動 検索に移動
(ダメージ計算の関数を細かく分割)
(ヘルメット - レベル3の計算が間違っていた問題の修正)
 
(同じ利用者による、間の23版が非表示)
18行目: 18行目:
return 0.2 + 0.8 * headmul
return 0.2 + 0.8 * headmul
elseif part == apex.HEAD_HLMLV2 then
elseif part == apex.HEAD_HLMLV2 then
return 0.4 + 0.6 * headmul
return 0.5 + 0.5 * headmul
elseif part == apex.HEAD_HLMLV3 then
elseif part == apex.HEAD_HLMLV3 then
return 0.5 + 0.5 * headmul
return 0.65 + 0.35 * headmul
else
else
return headmul
return headmul
29行目: 29行目:
function apex.calcHammerpointDamage(base, hammerpoint)
function apex.calcHammerpointDamage(base, hammerpoint)
return math.floor(hammerpoint * base)
return math.floor(hammerpoint * base)
end
-- [[ 貫通減衰倍率を考慮したダメージ計算 ]]
function apex.calcPassthroughDamage(base, passthrough)
return aw.round(passthrough * base)
end
end


63行目: 68行目:
function apex.calcDamageFromPartAndPassive(base, partmul, passive, opts)
function apex.calcDamageFromPartAndPassive(base, partmul, passive, opts)
-- 部位倍率
-- 部位倍率
base = calcPartDamage(base, partmul)
base = apex.calcPartDamage(base, partmul)
-- 小柄・鉄壁
-- 小柄・鉄壁
base = calcPassiveDamage(base, passive, opts)
if (opts and not opts.ignorePassiveForHeadshot) or partmul <= 1 then
base = apex.calcPassiveDamage(base, passive, opts)
end
return base
return base
75行目: 82行目:
opts = opts or {}
opts = opts or {}
opts.hammerpointRounds = opts.hammerpointRounds or 0
opts.hammerpointRounds = opts.hammerpointRounds or 0
opts.passthrough      = opts.passthrough or 1
opts.disruptorRounds  = opts.disruptorRounds or 0
opts.disruptorRounds  = opts.disruptorRounds or 0
80行目: 88行目:
if opts.ampedCover then
if opts.ampedCover then
base = aw.round(1.2 * base)
base = aw.round(1.2 * base)
else
base = aw.round(base)
end
-- チャージ倍率
if opts.charged > 1 then
base = aw.round(opts.charged * base)
end
end
-- ハンマーポイント弾
-- ハンマーポイント弾
if opts.hammerpointRounds > 1 then
if opts.hammerpointRounds > 1 then
base = calcHammerpointDamage(base, opts.hammerpointRounds)
base = apex.calcHammerpointDamage(base, opts.hammerpointRounds)
end
end
-- 部位倍率
-- 貫通減衰倍率
base = calcPartDamage(base, partmul)
if opts.passthrough < 1 then
base = apex.calcPassthroughDamage(base, opts.passthrough)
end
-- 部位倍率、小柄・鉄壁
base = apex.calcDamageFromPartAndPassive(base, partmul, passive, opts)
-- ディスラプター弾
-- ディスラプター弾
if opts.disruptorRounds > 1 then
if opts.disruptorRounds > 1 then
base = calcDisruptorDamage(base, opts.disruptorRounds)
base = apex.calcDisruptorDamage(base, opts.disruptorRounds)
end
end
-- 小柄・鉄壁
base = calcPassiveDamage(base, passive, opts)
-- ビームダメージ
-- ビームダメージ
if opts.beam and aw.isNumberAndGreaterThanOrEqualToZero(opts.beam.damage) then
if aw.isNumberAndGreaterThanZero(opts.beamdamage) and aw.isNumberAndGreaterThanZero(opts.beamticks)then
local beamdamage = apex.calcDamageFromPartAndPassive(opts.beam.damage, partmul, passive, opts)
local beamdamage = apex.calcDamageFromPartAndPassive(opts.beamdamage, partmul, passive, opts)
base = base + opts.beam.ticks * beamdamage
base = base + opts.beamticks * beamdamage
end
end
107行目: 124行目:
end
end


-- 射撃モード
-- [[ マガジン計算 ]]
apex.BURST              = 0
function apex.calcMagazineWithModdedLoader(magazine)
apex.DOUBLE_TAP_TRIGGER  = apex.BURST
return aw.round(1.15 * magazine)
apex.AUTO                = 100
end
apex.SINGLE              = 200
 
apex.ANVIL_RECEIVER      = 201
function apex.calcMagazinesWithModdedLoader(magazines)
apex.SELECTFIRE_RECEIVER = 300
return {
aw.round(1.15 * magazines[1]),
aw.round(1.15 * magazines[2]),
aw.round(1.15 * magazines[3]),
aw.round(1.15 * magazines[4]),
}
end


-- [[ 複数の射撃レートが定義されているかどうか ]]
function apex.getMagazineWithModdedLoader(magazines)
function apex.hasMultipleFirerate(stat, mode)
local magazinesType = type(magazines)
local firerate = stat.firarate
if magazinesType == 'table' then
if not firarate then
return apex.calcMagazinesWithModdedLoader(magazines)
return false
elseif magazinesType == 'number' then
end
return apex.calcMagazineWithModdedLoader(magazines)
if mode == apex.BURST then
return type(firerate.burst_delay) == 'table'
elseif mode == apex.AUTO then
return type(firerate.auto) == 'table'
elseif mode == apex.SINGLE then
return type(firerate.single) == 'table' or type(firerate.single_rechamber) == 'table'
else
else
return false
return nil
end
end
end
end


-- [[ 射撃レート計算 ]]
-- [[ 射撃レート計算 ]]
local function chooseData(data, level)
function apex.calcBurstAverageFirerate(count, delay, firerate)
local typename = type(data)
return count / ((count - 1) / firerate + delay)
if typename == 'table' then
end
return data[level]
 
elseif typename == 'number' then
local function calcBurstAverageFirerate(stat, delay)
return data
return apex.calcBurstAverageFirerate(stat.burst_count, delay, stat.firerate)
elseif typename == 'string' then
end
return tonumber(data)
 
else
function apex.calcRechamberFirerate(firerate, rechamber)
return 0
return 1 / (1 / firerate + rechamber)
end
end
end


function apex.calcFirerate(stat, mode, level)
function apex.getFirerate(stat, opts)
level = (1 + level) or 1
stat = stat or mw.loadData('Module:Stat/Weapon')[opts.name]
-- Altfire mode
if opts.useAltfire and aw.isNumberAndGreaterThanZero(stat.altfire.firerate, stat.firerate) then
return stat.altfire.firerate
end
local rps = 0
-- Burst mode
if mode == apex.BURST then
if aw.isNumberAndGreaterThanOrEqualToX(stat.burst_count, 2) then
if aw.isNumberAndGreaterThanZero(stat.mode.burst) then
local delay = stat.burst_delay
local firerate = chooseData(stat.firerate.burst, level)
if type(delay) == 'table' then
if firerate > 0 then
return {
local delay = chooseData(stat.firerate.burst_delay, level)
calcBurstAverageFirerate(stat, delay[1]),
if delay > 0 then
calcBurstAverageFirerate(stat, delay[2]),
rps = stat.mode.burst / ((stat.mode.burst - 1) / firerate + delay)
calcBurstAverageFirerate(stat, delay[3]),
else
calcBurstAverageFirerate(stat, delay[4]),
rps = firerate
}
end
elseif aw.isNumberAndGreaterThanZero(delay) then
end
return calcBurstAverageFirerate(stat, delay)
end
end
elseif mode == apex.AUTO then
end
if stat.mode.auto then
rps = chooseData(stat.firerate.auto, level)
-- Revved Up
if opts.useRevvedUpMode and aw.isNumberAndGreaterThanOrEqualToX(stat.firerate_revvedup, stat.firerate) then
return stat.firerate_revvedup
end
-- w/Turbocharger
if opts.useTurbocharger and stat.turbocharger then
return {
stat.turbocharger.firerate        or stat.firerate,
stat.turbocharger.firerate_maximum or stat.firerate_maximum,
}
end
-- Variable firerate
if aw.isNumberAndGreaterThanOrEqualToX(stat.firerate_maximum, stat.firerate) then
return {
stat.firerate,
stat.firerate_maximum,
}
end
-- w/Anvil Receiver
if opts.useAnvilReceiver and stat.anvil_receiver then
return stat.anvil_receiver.firerate
end
-- w/Double Tap Trigger
if opts.useDoubleTapTrigger and stat.double_tap_trigger and aw.isNumberAndGreaterThanOrEqualToX(stat.double_tap_trigger.burst_count, 2) then
local delay = stat.double_tap_trigger.burst_delay
if type(delay) == 'table' then
return {
calcBurstAverageFirerate(stat.double_tap_trigger, delay[1]),
calcBurstAverageFirerate(stat.double_tap_trigger, delay[2]),
calcBurstAverageFirerate(stat.double_tap_trigger, delay[3]),
calcBurstAverageFirerate(stat.double_tap_trigger, delay[4]),
}
elseif aw.isNumberAndGreaterThanZero(delay) then
return calcBurstAverageFirerate(stat.double_tap_trigger, delay)
end
end
elseif mode == apex.SINGLE then
end
if stat.mode.single then
local firerate = chooseData(stat.firerate.single, level)
-- w/Deadeye's Tempo
if firerate > 0 then
if opts.useDeadeyesTempo and stat.deadeyes_tempo then
local rechamber = chooseData(stat.firerate.single_rechamber, level)
if aw.isNumberAndGreaterThanZero(stat.deadeyes_tempo.charge) then
if rechamber > 0 then
if aw.isNumberAndGreaterThanZero(stat.deadeyes_tempo.charge_minimum) then
rps = 1 / (1 / firerate + rechamber)
return {
else
apex.calcRechamberFirerate(stat.firerate, stat.deadeyes_tempo.charge_minimum),
rps = firerate
apex.calcRechamberFirerate(stat.firerate, stat.deadeyes_tempo.charge),
end
}
else
return apex.calcRechamberFirerate(stat.firerate, stat.deadeyes_tempo.charge)
end
end
elseif aw.isNumberAndGreaterThanZero(stat.deadeyes_tempo.rechamber) then
return apex.calcRechamberFirerate(stat.firerate, stat.deadeyes_tempo.rechamber)
end
end
elseif mode == apex.ANVIL_RECEIVER then
end
if stat.mode.single then
rps = chooseData(stat.firerate.anvil_receiver, level)
-- w/Charge
if aw.isNumberAndGreaterThanZero(stat.charge) then
if aw.isNumberAndGreaterThanZero(stat.charge_minimum) then
return {
apex.calcRechamberFirerate(stat.firerate, stat.charge_minimum),
apex.calcRechamberFirerate(stat.firerate, stat.charge),
}
elseif aw.isNumberAndGreaterThanZero(stat.rechamber) then
return {
apex.calcRechamberFirerate(stat.firerate, stat.rechamber),
apex.calcRechamberFirerate(stat.firerate, stat.rechamber + stat.charge),
}
else
return {
stat.firerate,
apex.calcRechamberFirerate(stat.firerate, stat.charge),
}
end
end
end
end
return rps
-- w/Rechamber
if type(stat.rechamber) == 'table' then
return {
apex.calcRechamberFirerate(stat.firerate, stat.rechamber[1]),
apex.calcRechamberFirerate(stat.firerate, stat.rechamber[2]),
apex.calcRechamberFirerate(stat.firerate, stat.rechamber[3]),
apex.calcRechamberFirerate(stat.firerate, stat.rechamber[4]),
}
elseif aw.isNumberAndGreaterThanZero(stat.rechamber) then
return apex.calcRechamberFirerate(stat.firerate, stat.rechamber)
end
return stat.firerate
end
end


return apex
return apex

2022年5月26日 (木) 00:01時点における最新版

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

local apex = {}

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

-- 部位ダメージ用定数
apex.HEAD        = 1
apex.HEAD_NOHLM  = 1
apex.HEAD_HLMLV1 = 2
apex.HEAD_HLMLV2 = 3
apex.HEAD_HLMLV3 = 4
apex.BODY        = 10
apex.LEGS        = 100
apex.SKY         = 1000

-- [[ ヘッドショット倍率の計算 ]]
function apex.calcHeadshotMultiplier(headmul, part)
	if part == apex.HEAD_HLMLV1 then
		return 0.2 + 0.8 * headmul
	elseif part == apex.HEAD_HLMLV2 then
		return 0.5 + 0.5 * headmul
	elseif part == apex.HEAD_HLMLV3 then
		return 0.65 + 0.35 * headmul
	else
		return headmul
	end
end

-- [[ ハンマーポイント弾倍率を考慮したダメージ計算 ]]
function apex.calcHammerpointDamage(base, hammerpoint)
	return math.floor(hammerpoint * base)
end

-- [[ 貫通減衰倍率を考慮したダメージ計算 ]]
function apex.calcPassthroughDamage(base, passthrough)
	return aw.round(passthrough * base)
end

-- [[ 部位倍率を考慮したダメージ計算 ]]
function apex.calcPartDamage(base, partmul)
	if partmul ~= 1 then
		return aw.round(partmul * base)
	else
		return base
	end
end

-- [[ ディスラプター弾倍率を考慮したダメージ計算 ]]
function apex.calcDisruptorDamage(base, disruptor)
	return math.floor(disruptor * base)
end

-- [[ パッシブ倍率を考慮したダメージ計算 ]]
function apex.calcPassiveDamage(base, passive, opts)
	if passive == 1.05 then
		if not opts.round then
			return aw.roundover(passive * base)
		else
			return aw.round(passive * base)
		end
	elseif passive ~= 1 then
		return aw.round(passive * base)
	else
		return base
	end
end

-- [[ 部位倍率とパッシブ倍率を考慮したダメージ計算 ]]
function apex.calcDamageFromPartAndPassive(base, partmul, passive, opts)
	-- 部位倍率
	base = apex.calcPartDamage(base, partmul)
	
	-- 小柄・鉄壁
	if (opts and not opts.ignorePassiveForHeadshot) or partmul <= 1 then
		base = apex.calcPassiveDamage(base, passive, opts)
	end
	
	return base
end

-- [[ ダメージ計算 ]]
function apex.calcDamage(base, partmul, passive, opts)
	opts = opts or {}
	opts.hammerpointRounds = opts.hammerpointRounds or 0
	opts.passthrough       = opts.passthrough or 1
	opts.disruptorRounds   = opts.disruptorRounds or 0
	
	-- 増幅バリケード
	if opts.ampedCover then
		base = aw.round(1.2 * base)
	else
		base = aw.round(base)
	end
	
	-- チャージ倍率
	if opts.charged > 1 then
		base = aw.round(opts.charged * base)
	end
	
	-- ハンマーポイント弾
	if opts.hammerpointRounds > 1 then
		base = apex.calcHammerpointDamage(base, opts.hammerpointRounds)
	end
	
	-- 貫通減衰倍率
	if opts.passthrough < 1 then
		base = apex.calcPassthroughDamage(base, opts.passthrough)
	end
	
	-- 部位倍率、小柄・鉄壁
	base = apex.calcDamageFromPartAndPassive(base, partmul, passive, opts)
	
	-- ディスラプター弾
	if opts.disruptorRounds > 1 then
		base = apex.calcDisruptorDamage(base, opts.disruptorRounds)
	end
	
	-- ビームダメージ
	if aw.isNumberAndGreaterThanZero(opts.beamdamage) and aw.isNumberAndGreaterThanZero(opts.beamticks)then
		local beamdamage = apex.calcDamageFromPartAndPassive(opts.beamdamage, partmul, passive, opts)
		base = base + opts.beamticks * beamdamage
	end
	
	return base
end

-- [[ マガジン計算 ]]
function apex.calcMagazineWithModdedLoader(magazine)
	return aw.round(1.15 * magazine)
end

function apex.calcMagazinesWithModdedLoader(magazines)
	return {
		aw.round(1.15 * magazines[1]),
		aw.round(1.15 * magazines[2]),
		aw.round(1.15 * magazines[3]),
		aw.round(1.15 * magazines[4]),
	}
end

function apex.getMagazineWithModdedLoader(magazines)
	local magazinesType = type(magazines)
	if magazinesType == 'table' then
		return apex.calcMagazinesWithModdedLoader(magazines)
	elseif magazinesType == 'number' then
		return apex.calcMagazineWithModdedLoader(magazines)
	else
		return nil
	end
end

-- [[ 射撃レート計算 ]]
function apex.calcBurstAverageFirerate(count, delay, firerate)
	return count / ((count - 1) / firerate + delay)
end

local function calcBurstAverageFirerate(stat, delay)
	return apex.calcBurstAverageFirerate(stat.burst_count, delay, stat.firerate)
end

function apex.calcRechamberFirerate(firerate, rechamber)
	return 1 / (1 / firerate + rechamber)
end

function apex.getFirerate(stat, opts)
	stat = stat or mw.loadData('Module:Stat/Weapon')[opts.name]
	
	-- Altfire mode
	if opts.useAltfire and aw.isNumberAndGreaterThanZero(stat.altfire.firerate, stat.firerate) then
		return stat.altfire.firerate
	end
	
	-- Burst mode
	if aw.isNumberAndGreaterThanOrEqualToX(stat.burst_count, 2) then
		local delay = stat.burst_delay
		if type(delay) == 'table' then
			return {
				calcBurstAverageFirerate(stat, delay[1]),
				calcBurstAverageFirerate(stat, delay[2]),
				calcBurstAverageFirerate(stat, delay[3]),
				calcBurstAverageFirerate(stat, delay[4]),
			}
		elseif aw.isNumberAndGreaterThanZero(delay) then
			return calcBurstAverageFirerate(stat, delay)
		end
	end
	
	-- Revved Up
	if opts.useRevvedUpMode and aw.isNumberAndGreaterThanOrEqualToX(stat.firerate_revvedup, stat.firerate) then
		return stat.firerate_revvedup
	end
	
	-- w/Turbocharger
	if opts.useTurbocharger and stat.turbocharger then
		return {
			 stat.turbocharger.firerate         or stat.firerate,
			 stat.turbocharger.firerate_maximum or stat.firerate_maximum,
		}
	end
	
	-- Variable firerate
	if aw.isNumberAndGreaterThanOrEqualToX(stat.firerate_maximum, stat.firerate) then
		return {
			 stat.firerate,
			 stat.firerate_maximum,
		}
	end
	
	-- w/Anvil Receiver
	if opts.useAnvilReceiver and stat.anvil_receiver then
		return stat.anvil_receiver.firerate
	end
	
	-- w/Double Tap Trigger
	if opts.useDoubleTapTrigger and stat.double_tap_trigger and aw.isNumberAndGreaterThanOrEqualToX(stat.double_tap_trigger.burst_count, 2) then
		local delay = stat.double_tap_trigger.burst_delay
		if type(delay) == 'table' then
			return {
				calcBurstAverageFirerate(stat.double_tap_trigger, delay[1]),
				calcBurstAverageFirerate(stat.double_tap_trigger, delay[2]),
				calcBurstAverageFirerate(stat.double_tap_trigger, delay[3]),
				calcBurstAverageFirerate(stat.double_tap_trigger, delay[4]),
			}
		elseif aw.isNumberAndGreaterThanZero(delay) then
			return calcBurstAverageFirerate(stat.double_tap_trigger, delay)
		end
	end
	
	-- w/Deadeye's Tempo
	if opts.useDeadeyesTempo and stat.deadeyes_tempo then
		if aw.isNumberAndGreaterThanZero(stat.deadeyes_tempo.charge) then
			if aw.isNumberAndGreaterThanZero(stat.deadeyes_tempo.charge_minimum) then
				return {
					apex.calcRechamberFirerate(stat.firerate, stat.deadeyes_tempo.charge_minimum),
					apex.calcRechamberFirerate(stat.firerate, stat.deadeyes_tempo.charge),
				}
			else
				return apex.calcRechamberFirerate(stat.firerate, stat.deadeyes_tempo.charge)
			end
		elseif aw.isNumberAndGreaterThanZero(stat.deadeyes_tempo.rechamber) then
			return apex.calcRechamberFirerate(stat.firerate, stat.deadeyes_tempo.rechamber)
		end
	end
	
	-- w/Charge
	if aw.isNumberAndGreaterThanZero(stat.charge) then
		if aw.isNumberAndGreaterThanZero(stat.charge_minimum) then
			return {
				apex.calcRechamberFirerate(stat.firerate, stat.charge_minimum),
				apex.calcRechamberFirerate(stat.firerate, stat.charge),
			}
		elseif aw.isNumberAndGreaterThanZero(stat.rechamber) then
			return {
				apex.calcRechamberFirerate(stat.firerate, stat.rechamber),
				apex.calcRechamberFirerate(stat.firerate, stat.rechamber + stat.charge),
			}
		else
			return {
				stat.firerate,
				apex.calcRechamberFirerate(stat.firerate, stat.charge),
			}
		end
	end
	
	-- w/Rechamber
	if type(stat.rechamber) == 'table' then
		return {
			apex.calcRechamberFirerate(stat.firerate, stat.rechamber[1]),
			apex.calcRechamberFirerate(stat.firerate, stat.rechamber[2]),
			apex.calcRechamberFirerate(stat.firerate, stat.rechamber[3]),
			apex.calcRechamberFirerate(stat.firerate, stat.rechamber[4]),
		}
	elseif aw.isNumberAndGreaterThanZero(stat.rechamber) then
		return apex.calcRechamberFirerate(stat.firerate, stat.rechamber)
	end
	
	return stat.firerate
end

return apex