Module:User:Pival13/UnitStat

local mw = mw local html = mw.html local query = mw.ext.cargo.query local bit32 = require 'bit32' local Util = require 'Module:Util' local escq = require 'Module:EscQ'.main1

local parseArgs = function(args) local STATS = {"HP", "Atk", "Spd", "Def", "Res"} local SUPPORT = {"C", "B", "A", "S"}

local rarity = tonumber(args.rarity) if not rarity then return nil end local level = tonumber(args.level) if not level or level 50 then return nil end local merge if args.merge then merge = tonumber(args.merge) if not merge or merge 10 or level - merge > 40 or level - merge < 1 then return nil end else merge = level > 40 and level - 40 or 0 end level = level - merge local dragonflower = args.dragonflower and tonumber(args.dragonflower) or 0 if not dragonflower or dragonflower 15 then return nil end local ssupport = 0 for i = 1, 4 do		if args.ssupport and args.ssupport == SUPPORT[i] then ssupport = i		end end local iv = {2, 2, 2, 2, 2} for i = 1, 5 do		if args.asset and args.asset == STATS[i] then iv[i] = 3 elseif merge == 0 and args.flaw and args.flaw == STATS[i] then iv[i] = 1 end end return rarity, level, merge, dragonflower, ssupport, iv end

local downgradeHeroStats = function (stats, rarity) local atko = (stats[2] >= stats[3] and 1 or 0) + (stats[2] >= stats[4] and 1 or 0) + (stats[2] >= stats[5] and 1 or 0) local spdo = (stats[3] > stats[2] and 1 or 0) + (stats[3] >= stats[4] and 1 or 0) + (stats[3] >= stats[5] and 1 or 0) local defo = (stats[4] > stats[2] and 1 or 0) + (stats[4] >  stats[3] and 1 or 0) + (stats[4] >= stats[5] and 1 or 0) local reso = (stats[5] > stats[2] and 1 or 0) + (stats[5] >  stats[3] and 1 or 0) + (stats[5] >  stats[4] and 1 or 0)

local truestats = {stats[1], stats[2], stats[3], stats[4], stats[5]}

if rarity == 1 then for i = 1, #truestats do			truestats[i] = truestats[i] - 2 end elseif rarity <= 3 then for i = 1, #truestats do			truestats[i] = truestats[i] - 1 end end

if rarity == 2 or rarity == 4 then truestats[1] = truestats[1] - 1 if atko < 2 then truestats[2] = truestats[2] - 1 end if spdo < 2 then truestats[3] = truestats[3] - 1 end if defo < 2 then truestats[4] = truestats[4] - 1 end if reso < 2 then truestats[5] = truestats[5] - 1 end end

return truestats end

local getGrowthVector; do	local VECTORS = mw.loadData 'Module:StatTable/data' getGrowthVector = function (basestat, rate, rarity, vbase) local gvgv = math.floor(rate * (0.79 + 0.07 * rarity)) local vid = (3 * basestat + vbase + gvgv) % 0x40 local growth = math.floor(0.39 * gvgv) if growth 39 then return {} end local lobytes = VECTORS[growth * 128 + vid * 2 - 127] local hibytes = VECTORS[growth * 128 + vid * 2 - 126]

local vec = {} for i = 2, 31 do		vec[i] = bit32.extract(lobytes, i)	end for i = 32, 40 do		vec[i] = bit32.extract(hibytes, i - 32) end return vec end; end

local calculateStats = function (base, base5, rate, rarity, level, vbase, iv) local truebase = base if iv > 0 then truebase = truebase + 1 rate = rate + 5 elseif iv < 0 then truebase = truebase - 1 rate = rate - 5 end local vec = getGrowthVector(base5, rate, rarity, vbase)

local t = {truebase} if level > 1 then for i = 2, level do			t[i] = t[i - 1] + vec[i] end end return t[level] end

local getStatIV = function (stats, rates, rarity, bvid, level) local truestats = downgradeHeroStats(stats, rarity) return { HP = { calculateStats(truestats[1], stats[1], rates[1], rarity, level, bvid - 35, -1), calculateStats(truestats[1], stats[1], rates[1], rarity, level, bvid - 35, 0), calculateStats(truestats[1], stats[1], rates[1], rarity, level, bvid - 35, 1), },		Atk = { calculateStats(truestats[2], stats[2], rates[2], rarity, level, bvid - 28, -1), calculateStats(truestats[2], stats[2], rates[2], rarity, level, bvid - 28, 0), calculateStats(truestats[2], stats[2], rates[2], rarity, level, bvid - 28, 1), },		Spd = { calculateStats(truestats[3], stats[3], rates[3], rarity, level, bvid - 21, -1), calculateStats(truestats[3], stats[3], rates[3], rarity, level, bvid - 21, 0), calculateStats(truestats[3], stats[3], rates[3], rarity, level, bvid - 21, 1), },		Def = { calculateStats(truestats[4], stats[4], rates[4], rarity, level, bvid - 14, -1), calculateStats(truestats[4], stats[4], rates[4], rarity, level, bvid - 14, 0), calculateStats(truestats[4], stats[4], rates[4], rarity, level, bvid - 14, 1), },		Res = { calculateStats(truestats[5], stats[5], rates[5], rarity, level, bvid - 7, -1), calculateStats(truestats[5], stats[5], rates[5], rarity, level, bvid - 7,  0), calculateStats(truestats[5], stats[5], rates[5], rarity, level, bvid - 7,  1), },	} end

local getBases = function (hero) local q = query('Units,UnitStats', 'Lv1HP5,Lv1Atk5,Lv1Spd5,Lv1Def5,Lv1Res5,HPGR3,AtkGR3,SpdGR3,DefGR3,ResGR3', {		join = 'Units.WikiName=UnitStats.WikiName',		where = ("Units._pageName='%s' AND IFNULL(Properties__full,'') NOT LIKE '%%enemy%%'"):format(escq(hero)),		groupBy = 'Units.WikiName',	})[1] if not q then return nil end local base = {tonumber(q.Lv1HP5), tonumber(q.Lv1Atk5), tonumber(q.Lv1Spd5), tonumber(q.Lv1Def5), tonumber(q.Lv1Res5)} local rates = {tonumber(q.HPGR3), tonumber(q.AtkGR3), tonumber(q.SpdGR3), tonumber(q.DefGR3), tonumber(q.ResGR3)} return base, rates end

local increaseStats = function(statIV, base, iv, merge, dragonflower, ssupport) local stat = {statIV.HP[iv[1]], statIV.Atk[iv[2]], statIV.Spd[iv[3]], statIV.Def[iv[4]], statIV.Res[iv[5]]} for i = 1, 5 do		base[i] = base[i] + iv[i] - 2 end local statOrder = { 0,				1 + (base[2] < base[3] and 1 or 0) + (base[2] < base[4] and 1 or 0) + (base[2] < base[5] and 1 or 0), 1 + (base[3] <= base[2] and 1 or 0) + (base[3] < base[4] and 1 or 0) + (base[3] < base[5] and 1 or 0), 1 + (base[4] <= base[2] and 1 or 0) + (base[4] <=  base[3] and 1 or 0) + (base[4] < base[5] and 1 or 0), 1 + (base[5] <= base[2] and 1 or 0) + (base[5] <=  base[3] and 1 or 0) + (base[5] <=  base[4] and 1 or 0), }	for i = 1, dragonflower do		for j = 1, 5 do			if statOrder[j] == (i - 1) % 5 then stat[j] = stat[j] + 1 end end end if merge ~= 0 and iv[1] == iv[2] == iv[3] == iv[4] == iv[5] then for i = 1, 3 do			for j = 1, 5 do				if statOrder[j] == i - 1 then stat[j] = stat[j] + 1 end end end end for i = 1, merge do		for j = 1, 5 do			if statOrder[j] == ((i - 1) * 2) % 5 then stat[j] = stat[j] + 1 end if statOrder[j] == ((i - 1) * 2 + 1) % 5 then stat[j] = stat[j] + 1 end end end for i = 1, ssupport do		stat[6-i] = stat[6-i] + 2 end if ssupport == 1 then stat[1] = stat[1] + 3 elseif ssupport == 2 or ssupport == 3 then stat[1] = stat[1] + 4 elseif ssupport == 4 then stat[1] = stat[1] + 5 end return table.concat({stat[1], stat[2], stat[3], stat[4], stat[5]}, ',') end

local getStat = function (args) local hero = args.hero or '' local bvid = query('HeroBVIDs', 'BVID', {		where = ("Hero='%s'"):format(escq(hero)),	})[1] local base, rates = getBases(hero) if not (bvid and base and rates) then return "—,—,—,—,—" end local rarity, level, merge, dragonflower, ssupport, iv = parseArgs(args) if not rarity then return "??,??,??,??,??" end local statIV = getStatIV(base, rates, rarity, tonumber(bvid.BVID, 16), level) if not (statIV and statIV.HP[iv[1]]) then return "??,??,??,??,??" end return increaseStats(statIV, base, iv, merge, dragonflower, ssupport) end

local getStatWithSkills = function(args) local strStat = getStat(args) if strStat == "??,??,??,??,??" or strStat == "—,—,—,—,—" then return stat end local statsBonus = query('Skills', 'StatModifiers=stat', {		where = ("(Scategory='passivea' AND Name='%s')"):format(escq(args.a or )) ..				(" OR (Scategory='passiveb' AND Name='%s')"):format(escq(args.b or )) ..				(" OR (Scategory='passivec' AND Name='%s')"):format(escq(args.c or )) ..				(" OR (Scategory='weapon' AND _pageName='%s' AND IFNULL(RefinePath,'-')='%s')"):format(escq(args.weapon or ), args.refine or '-'),		groupBy = 'stat',	}) local statsSeal = query('Skills', 'StatModifiers=stat', {		where = ("(Scategory LIKE 'passive_' OR Scategory='passiveseal') AND Name='%s'"):format(escq(args.seal or '')),		groupBy = 'stat',	})[1] local stat = {} mw.ustring.gsub(strStat, "([%-%d]+)", function(v) table.insert(stat, tonumber(v) or 0) end) for i = 1, statsBonus and #statsBonus do		if statsBonus[i].stat ~= '' then local temp = statsBonus[i].stat statsBonus[i] = {} mw.ustring.gsub(temp, "([%-%d]+)", function(v) table.insert(statsBonus[i], tonumber(v) or 0) end) else statsBonus[i] = {0,0,0,0,0} end end if statsSeal and statsSeal.stat ~= '' then table.insert(statsBonus, {}) mw.ustring.gsub(statsSeal.stat, "([%-%d]+)", function(v) table.insert(statsBonus[#statsBonus], tonumber(v) or 0) end) end for i = 1, statsBonus and #statsBonus do		for j = 1, 5 do			stat[j] = stat[j] + statsBonus[i][j] end end return table.concat({stat[1], stat[2], stat[3], stat[4], stat[5]}, ',') end

return require 'Module:makeMWModule'.makeMWModule { getStat = getStat, getStatWithSkills = getStatWithSkills, }