Module:User:HertzDevil/Keywords

local List = require 'Module:ListUtil' local strip_wikitext = require 'Module:StripWikitext'.main1

local strip_desc = function (str) local count = nil repeat str, count = mw.ustring.gsub(str, '(.-) ', '%1')	until count == 0;	repeat		str, count = mw.ustring.gsub(str, (.-), '%1')	until count == 0;	return strip_wikitext(mw.ustring.gsub(str, ' ', ' ')) end

local Template_Hover_nocargo = function (text, title) if title == nil or title == '' then return text end return ( %s ):format(		strip_wikitext(title):gsub('\n', '&#10;'), text) end

local make_keyword_func = function (name, arg_count, desc_func) return function (args) local keyword_args = List.sub(args, 1, arg_count) local desc = desc_func(unpack(List.map(keyword_args, strip_desc), 1, arg_count)) return ("%s(%s)"):format(			Template_Hover_nocargo(name, desc),			table.concat(List.map(keyword_args, function (x) return ("%s"):format(tostring(x)) end), '; ')) end end

local signed = function (x) local n = tonumber((mw.ustring.gsub(x, '^−', '-'))) local str = n and ("%+d"):format(n) or x	return (mw.ustring.gsub(str, '^%-', '−')) end

local cond_desc = function (x, eq, desc) local x_num = tonumber((mw.ustring.gsub(x, '^−', '-'))) if x_num == eq then return desc elseif not x_num then return ("• %s = %s: %s"):format(x, tostring(eq):gsub('^%-', '−'), desc) end end

local ones = make_keyword_func('ONES', 1, function (x) return ("%s mod 10"):format(x) end) local tens = make_keyword_func('TENS', 1, function (x) return ("floor(%s ÷ 10) mod 10"):format(x) end) local hundreds = make_keyword_func('HUNDREDS', 1, function (x) return ("floor(%s ÷ 100) mod 10"):format(x) end) local tens_ones = make_keyword_func('TENS_ONES', 1, function (x) return ("%s mod 100"):format(x) end)

local within_range = make_keyword_func('WITHIN_RANGE', 1, function (u)	return ("within skill_range spaces of %s"):format(u) end)

local within_column = make_keyword_func('WITHIN_COLUMN', 1, function (u)	return ("within (2 × skill_range + 1) columns centered on %s"):format(u) end)

local within_range_ex = make_keyword_func('WITHIN_RANGE_EX', 1, function (u)	return ( "• range_shape = 0: within skill_range spaces of %s\n" .. "• range_shape = 1 (used by Duo skills): within skill_range spaces of %s\n" .. "• range_shape = 2: within (2 × ONES(skill_range) + 1) rows and (2 × TENS(skill_range) + 1) columns centered on %s\n" .. "• range_shape = 3: in cardinal directions of %s\n" .. "• range_shape = 4: within (2 × skill_range + 1) columns centered on %s\n" .. "• range_shape = 5: within (2 × skill_range + 1) rows centered on %s" ):format(u, u, u, u, u, u) end)

local count_around_a = make_keyword_func('COUNT_AROUND', 2, function (u, v)	return ("the number of %s within skill_range spaces of %s (excluding %s)"):format(v, u, u) end)

local count_around_l = make_keyword_func('COUNT_AROUND', 2, function (u, v)	return ("the number of %s within param1 spaces of %s (excluding %s)"):format(v, u, u) end)

local unit_near = make_keyword_func('UNIT_NEAR', 1, function (u)	return ("if unit is within skill_range spaces of %s"):format(u) end)

local neighborhood = make_keyword_func('NEIGHBORHOOD', 1, function (u)	return ("%s and units on %s’s team within skill_range spaces of %s"):format(u, u, u) end)

local neighborhood_ex = make_keyword_func('NEIGHBORHOOD_EX', 1, function (u)	return ("%s and units on %s’s team WITHIN_RANGE_EX(%s)"):format(u, u, u) end)

local stat = make_keyword_func('STAT', 1, function (x)	return ( "• %s = 0: current HP\n" .. "• %s = 1: Atk\n" .. "• %s = 2: Spd\n" .. "• %s = 3: Def\n" .. "• %s = 4: Res\n" ):format(x, x, x, x, x) end)

local stat_difference = make_keyword_func('STAT_DIFFERENCE', 2, function (x, u)	if x == 'HP' or x == 'Atk' or x == 'Spd' or x == 'Def' or x == 'Res' then		return ("unit’s %s − %s’s %s (including Phantom skills)"):format(x, u, x)	else		return ("unit’s STAT(%s) − %s’s STAT(%s) (including Phantom skills)"):format(x, u, x)	end end)

local hp_between = make_keyword_func('HP_BETWEEN', 3, function (x, y, u)	return ("%s%% ≤ %s’s HP ≤ %s%%"):format(x, u, y) end)

local skill_targets = make_keyword_func('SKILL_TARGETS', 1, function (u)	return ( "• target_either = true: %s is a target_mov unit or target_mov %s uses target_wep\n" .. "• target_either = false: target_mov %s uses target_wep" ):format(u, u, u) end)

local targeted = make_keyword_func('TARGETED', 1, function (u)	return ( "• target_either = true: target_mov %s and %s using target_wep\n" .. "• target_either = false: target_mov %s using target_wep" ):format(u, u, u) end)

local combat_boost = make_keyword_func('COMBAT_BOOST', 1, function (u)	return ("for each stat, grants/inflicts stat+skill_params.stat to/on %s during combat"):format(u) end)

local combat_boost2 = make_keyword_func('COMBAT_BOOST2', 1, function (u)	return ("for each stat, grants/inflicts stat+skill_params2.stat to/on %s during combat"):format(u) end)

local counter = make_keyword_func('COUNTER', 1, function (u)	return ("%s can counterattack regardless of opponent’s range"):format(u) end)

local no_counter = make_keyword_func('NO_COUNTER', 1, function (u)	return ("%s cannot counterattack"):format(u) end)

local follow_up = make_keyword_func('FOLLOW_UP', 2, function (x, u)	return table.concat(List.compact { cond_desc(x, 1, ("%s makes a guaranteed follow-up attack"):format(u)), cond_desc(x, -1, ("%s cannot make a follow-up attack"):format(u)), }, '\n') end)

local null_follow_up = make_keyword_func('NULL_FOLLOW_UP', 2, function (x, y)	return table.concat(List.compact { cond_desc(x, 1, "neutralizes effects that guarantee foe’s follow-up attacks during combat"), cond_desc(y, 1, "neutralizes effects that prevent unit’s follow-up attacks during combat"), }, '\n') end)

local vantage = make_keyword_func('VANTAGE', 1, function (u)	return ("%s can counterattack before opponent’s first attack"):format(u) end)

local desperation = make_keyword_func('DESPERATION', 1, function (u)	return ("%s can make a follow-up attack before opponent can counterattack"):format(u) end)

local brave = make_keyword_func('BRAVE', 1, function (u)	return ("%s attacks twice"):format(u) end)

local charge = make_keyword_func('CHARGE', 3, function (mode, x, u)	x = signed(x)

return table.concat(List.compact {		cond_desc(mode, 0, ("grants/inflicts Special cooldown charge %s to/on %s per attack during combat (Only highest value applied. Does not stack.)"):format(x, u)),		cond_desc(mode, 1, ("grants/inflicts Special cooldown charge %s to/on %s per %s’s attack during combat (Only highest value applied. Does not stack.)"):format(x, u, u)),		cond_desc(mode, 2, ("grants/inflicts Special cooldown charge %s to/on %s per opponent of %s’s attack during combat (Only highest value applied. Does not stack.)"):format(x, u, u)),	}, '\n') end)

local blade = make_keyword_func('BLADE', 1, function (u)	return ('CHARGE(skill_params.hp; −skill_params.atk; %s) and CHARGE(skill_params.hp; −skill_params.spd; %s’s opponent)'):format(u, u) end)

local raven = make_keyword_func('RAVEN', 1, function (u)	return ("grants weapon-triangle advantage to %s against colorless opponents, and inflicts weapon-triangle disadvantage on colorless opponents during combat"):format(u) end)

local cancel_affinity = make_keyword_func('CANCEL_AFFINITY', 2, function (x, u)	return table.concat(List.compact { cond_desc(x, 1, ("neutralizes weapon-triangle advantage granted by %s’s skills"):format(u)), cond_desc(x, 2, ("if %s has weapon-triangle advantage, neutralizes weapon-triangle advantage granted by %s’s skills"):format(u, u)), cond_desc(x, 3, ("if %s has weapon-triangle advantage, reverses weapon-triangle advantage granted by %s’s skills"):format(u, u)), }, '\n') end)

local adaptive = make_keyword_func('ADAPTIVE', 1, function (u)	return ("calculates %s’s damage during combat using the lower of opponent’s Def or Res"):format(u) end)

local adaptive_aoe = make_keyword_func('ADAPTIVE_AOE', 1, function (u)	return ("calculates damage from %s’s area-of-effect Specials using the lower of opponent’s Def or Res"):format(u) end)

local wrathful_staff = make_keyword_func('WRATHFUL_STAFF', 1, function (u)	return ("calculates damage from %s’s staff like other weapons"):format(u) end)

local damage = make_keyword_func('DAMAGE', 1, function (x)	return ("deals %s damage"):format(x) end)

local combat_add_hp = make_keyword_func('COMBAT_ADD_HP', 2, function (x, u)	return ("restores HP to %s during combat = %s"):format(u, x) end)

local map_add_hp = make_keyword_func('MAP_ADD_HP', 2, function (x, u)	return ( "• %s > 0: restores %s HP to %s\n" .. "• %s < 0: deals −%s damage to %s" ):format(x, x, u, x, x, u) end)

local cooldown = make_keyword_func('COOLDOWN', 2, function (x, u)	return ("inflicts/grants Special cooldown count%s on/to %s (Cannot exceed %s’s maximum Special cooldown. No effect if %s does not have a Special skill.)"):format(signed(x), u, u, u) end)

local buff = make_keyword_func('BUFF', 1, function (u)	return ( "for each stat,\n" .. "• skill_params.stat > 0: grants stat+skill_params.stat to %s for 1 turn\n" .. "• skill_params.stat < 0: inflicts stat+skill_params.stat on %s through their next actions" ):format(u, u) end)

local buff2 = make_keyword_func('BUFF2', 1, function (u)	return ( "for each stat,\n" .. "• skill_params2.stat > 0: grants stat+skill_params2.stat to %s for 1 turn\n" .. "• skill_params2.stat < 0: inflicts stat+skill_params2.stat on %s through their next actions" ):format(u, u) end)

local status = make_keyword_func('STATUS', 1, function (x)	return ( "• %s = 0: Gravity\n" .. "• %s = 1: Panic\n" .. "• %s = 2: No counterattacks\n" .. "• %s = 3: March\n" .. "• %s = 4: Triangle Adept\n" .. "• %s = 5: Guard\n" .. "• %s = 6: Air Orders\n" .. "• %s = 7: Isolation\n" .. "• %s = 8: Effective against dragons\n" .. "• %s = 9: Bonus Doubler\n" .. "• %s = 10: Dragon Shield\n" .. "• %s = 11: Svalinn Shield\n" .. "• %s = 12: Dominance\n" .. "• %s = 13: Resonance: Blades\n" .. "• %s = 14: Desperation\n" .. "• %s = −1: None" ):format(x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x) end)

local add_status = make_keyword_func('ADD_STATUS', 2, function (x, u)	return ("grants/inflicts %s to/on %s"):format(x, u) end)

local special_damage = make_keyword_func('SPECIAL_DAMAGE', 1, function (x)	return ("boosts damage by %s"):format(x) end)

local luna = make_keyword_func('LUNA', 1, function (x)	return ("treats foe’s Def/Res as if reduced by %s%%"):format(x) end)

local arena_assault_item = make_keyword_func('ARENA_ASSAULT_ITEM', 1, function (x)	return ( "• %s = 0: Elixir\n" .. "• %s = 1: Fortifying Horn\n" .. "• %s = 2: Special Blade\n" .. "• %s = 3: Infantry Boots\n" .. "• %s = 4: Naga's Tear\n" .. "• %s = 5: Dancer's Veil\n" .. "• %s = 6: Lightning Charm\n" .. "• %s = 7: Panic Charm\n" .. "• %s = 8: Fear Charm\n" .. "• %s = 9: Pressure Charm\n" ):format(x, x, x, x, x, x, x, x, x, x) end)

return { ONES = ones, TENS = tens, HUNDREDS = hundreds, TENS_ONES = tens_ones,

WITHIN_RANGE = within_range, WITHIN_COLUMN = within_column, WITHIN_RANGE_EX = within_range_ex, COUNT_AROUND_A = count_around_a, COUNT_AROUND_L = count_around_l, UNIT_NEAR = unit_near, NEIGHBORHOOD = neighborhood, NEIGHBORHOOD_EX = neighborhood_ex,

STAT = stat, STAT_DIFFERENCE = stat_difference, HP_BETWEEN = hp_between,

SKILL_TARGETS = skill_targets, TARGETED = targeted,

COMBAT_BOOST = combat_boost, COMBAT_BOOST2 = combat_boost2,

COUNTER = counter, NO_COUNTER = no_counter, FOLLOW_UP = follow_up, NULL_FOLLOW_UP = null_follow_up, VANTAGE = vantage, DESPERATION = desperation, BRAVE = brave,

CHARGE = charge, BLADE = blade,

RAVEN = raven, CANCEL_AFFINITY = cancel_affinity, ADAPTIVE = adaptive, ADAPTIVE_AOE = adaptive_aoe, WRATHFUL_STAFF = wrathful_staff, DAMAGE = damage, COMBAT_ADD_HP = combat_add_hp,

MAP_ADD_HP = map_add_hp, COOLDOWN = cooldown, BUFF = buff, BUFF2 = buff2, STATUS = status, ADD_STATUS = add_status,

SPECIAL_DAMAGE = special_damage, LUNA = luna,

ARENA_ASSAULT_ITEM = arena_assault_item, }