Editing
Module
:
Buildup
Give feedback
Jump to navigation
Jump to search
Warning:
You are not logged in. Once you make an edit, a temporary account will be created for you.
Learn more
.
Log in
or
create an account
to continue receiving notifications after this account expires, and to access other features.
Anti-spam check. Do
not
fill this in!
local p = {} local heroes_data = mw.loadJsonData("Data:HeroData.json") local items_data = mw.loadJsonData("Data:ItemData.json") -- Helper to find Item Buildup value by name -- Handles both flat numbers and lookup in the ItemData file local function get_item_bb(target_name) if target_name == nil then return nil end -- Clean input local clean_name = mw.text.trim(target_name) -- If user input a number directly if tonumber(clean_name) then return tonumber(clean_name) end -- Iterate Item Data for key, item in pairs(items_data) do if item["Name"] == clean_name then -- Valve data structure (nested) if item["m_mapAbilityProperties"] and item["m_mapAbilityProperties"]["BuildUpPerShot"] then return tonumber(item["m_mapAbilityProperties"]["BuildUpPerShot"]["m_strValue"]) end -- Flat data structure (fallback) if item["BuildUpPerShot"] then return tonumber(item["BuildUpPerShot"]) end end end return nil end -- Helper to find Hero Data by name or key local function get_hero_data(hero_name) if hero_name == nil then return nil end local clean_name = mw.text.trim(hero_name) -- Try direct Key lookup if heroes_data[clean_name] then return heroes_data[clean_name] end -- Try adding "hero_" prefix local key_lower = "hero_" .. string.lower(clean_name) if heroes_data[key_lower] then return heroes_data[key_lower] end -- Search by Name field for k, v in pairs(heroes_data) do if v["Name"] == clean_name then return v end end return nil end -- Helper: number of bullets/pellets fired per trigger pull -- For shotguns (Abrams, etc.) this is the pellet count. -- For burst weapons this is the burst size. -- For normal weapons it is 1. local function get_bullets_per_shot(hero) if not hero or not hero.Weapon then return 1 end local bps = tonumber( hero.Weapon.BulletsPerShot or hero.Weapon.PelletsPerShot or hero.Weapon.BulletsPerBurst or 1 ) if bps == nil or bps < 1 then bps = 1 end return bps end -- Core calculation logic -- Returns: per_bullet_bps (float), bullets_per_shot (int) local function calculate_bps(hero, bb) if not hero or not hero.Weapon then return 0, 1 end local rps = tonumber(hero.Weapon.RoundsPerSecond or 0) local spin_rps = tonumber(hero.Weapon.RoundsPerSecondAtMaxSpin or 0) -- 1. Handle Spin-up (McGinnis/Bebop) if spin_rps > 0 then rps = spin_rps end -- 2. Handle "Fake Burst" Logic (Paige/Doorman) -- If they have a burst interval, but only 1 bullet per burst, -- the game ignores that interval for Buildup calculation. local burst_count = tonumber(hero.Weapon.BulletsPerBurst or 1) local burst_interval = tonumber(hero.Weapon.BurstInterShotInterval or 0) if burst_count == 1 and burst_interval > 0 and rps > 0 then -- Convert RPS back to time local total_time = 1 / rps -- Remove the interval local effective_time = total_time - burst_interval -- Prevent division by zero if something is weird if effective_time > 0.001 then rps = 1 / effective_time end end -- 3. Handle Silver (Transformed) - uses base form's RPS for buildup if hero.Name == "Silver (Transformed)" then rps = 1.1111 -- Base Silver's RoundsPerSecond end if rps == 0 then return 0, 1 end local bullets_per_shot = get_bullets_per_shot(hero) -- Original Formula: 100 / (BB * (RPS + 1)) -- This calculates the buildup per trigger pull assuming all pellets connect local bps_per_shot = 100 / (bb * (rps + 1)) -- Divide by bullets/pellets per shot to get the per-bullet buildup local bps_per_bullet = bps_per_shot / bullets_per_shot return bps_per_bullet, bullets_per_shot end --{{#invoke:Buildup|get_bps|HERO_NAME|ITEM_NAME}} --Returns a single float value (rounded to 1 decimal) representing buildup PER BULLET p.get_bps = function(frame) local hero_name = frame.args[1] or frame.args['hero'] local item_name = frame.args[2] or frame.args['item'] local hero = get_hero_data(hero_name) if not hero then return "Hero Not Found" end local bb = get_item_bb(item_name) if not bb then return "Item Not Found" end local result, _ = calculate_bps(hero, bb) return string.format("%.1f", result) end --{{#invoke:Buildup|write_buildup_table|ITEM_NAME}} --Generates a sortable wikitable for all heroes showing per-bullet buildup p.write_buildup_table = function(frame) local item_name = frame.args[1] local bb = get_item_bb(item_name) if not bb then return "Error: Item '" .. (item_name or "nil") .. "' not found." end local hero_list = {} for key, hero in pairs(heroes_data) do local is_dev = hero["InDevelopment"] == true local is_disabled = hero["IsDisabled"] == true if not is_dev and not is_disabled and hero["Weapon"] and hero["Name"] then local val, bullets_per_shot = calculate_bps(hero, bb) if val > 0 then -- Shots to proc assumes every bullet in the shot connects local per_shot = val * bullets_per_shot local shots = math.ceil(100 / per_shot) table.insert(hero_list, { name = hero["Name"], bps = val, bullets_per_shot = bullets_per_shot, shots = shots }) end end end -- Sorting Logic table.sort(hero_list, function(a, b) -- Helper to strip "The " from names just for sorting local function clean_sort_name(name) if string.sub(name, 1, 4) == "The " then return string.sub(name, 5) end return name end return clean_sort_name(a.name) < clean_sort_name(b.name) end) -- Build Table local html = mw.html.create('table') html:addClass('wikitable sortable mw-collapsible') if item_name then html:tag('caption'):wikitext('Buildup Per Bullet: ' .. item_name) end -- Headers local headerRow = html:tag('tr') headerRow:tag('th'):wikitext('Hero') headerRow:tag('th'):wikitext('% per bullet') headerRow:tag('th'):wikitext('Bullets/Shot') headerRow:tag('th'):wikitext('Shots to Proc<br/><small>(all bullets hit)</small>') -- Rows for _, h in ipairs(hero_list) do local row = html:tag('tr') local hero_display if h.name == "Silver (Transformed)" then -- Detect page language from subpage (e.g. /ru) local currentTitle = mw.title.getCurrentTitle().fullText local langCode = currentTitle:match("/([^/]+)$") or "en" local isRussian = (langCode == "ru") local displayName = isRussian and "Сильвер (Трансформация)" or "Silver (Transformed)" local linkTarget = isRussian and "Silver (Transformed)/ru" or "Silver (Transformed)" local icon_file = string.format('[[File:Silver.png|20px|link=%s]]', linkTarget) local name_link = string.format('[[%s|%s]]', linkTarget, displayName) hero_display = string.format( '<span style="white-space:nowrap;">' .. '<span style="position:relative; bottom:2px;">%s</span>' .. ' %s' .. '</span>', icon_file, name_link ) else hero_display = frame:expandTemplate{ title = 'HeroIcon', args = { h.name } } end row:tag('td') :attr('data-sort-value', h.name) :wikitext(hero_display) row:tag('td'):wikitext(string.format("%.1f", h.bps)) -- Show "—" for normal single-bullet weapons, the actual count for shotguns/bursts if h.bullets_per_shot > 1 then row:tag('td'):wikitext(tostring(h.bullets_per_shot)) else row:tag('td'):wikitext('—') end row:tag('td'):wikitext(tostring(h.shots)) end return tostring(html) end -- Main entry point for the template -- Decides whether to return a single value or a full table based on arguments p.main = function(frame) local args = frame:getParent().args -- Handle direct #invoke calls vs Template calls if not args[1] and not args['item'] then args = frame.args end local arg1 = args[1] or args['hero'] local arg2 = args[2] or args['item'] -- If both Hero and pItem are present -> Return Single Number if arg1 and arg2 then -- Manually setting args for the helper function to read frame.args = {arg1, arg2} return p.get_bps(frame) -- If only one arg (Item) is present -> Return Table elseif arg1 then frame.args = {arg1} return p.write_buildup_table(frame) else return "Error: Provide [Item Name] for a table, or [Hero Name] [Item Name] for a value." end end return p
Summary:
Please note that all contributions to The Deadlock Wiki are considered to be released under the Creative Commons Attribution-NonCommercial-ShareAlike (see
Deadlock:Copyrights
for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Preview page with this template
Pages included on this page:
Template:ItemIcon
(
edit
)
Module:Buildup
(
edit
)
Module:Buildup/doc
(
edit
)
Module:Dictionary
(
edit
)
Module:Icon
(
edit
)
Module:Icon/data
(
edit
)
Module:Lang
(
edit
)
Module:Utilities
(
edit
)
Data:Dictionary
(
edit
)
Data:HeroData.json
(
view source
) (⧼restriction-level-bot+⧽)
Data:ItemData.json
(
view source
) (⧼restriction-level-bot+⧽)
Data:LangCodes.json
(
view source
) (⧼restriction-level-bot+⧽)
Data:ResourceLookup.json
(
edit
)
Data:ResourceLookup2.json
(
edit
)
Navigation menu
Personal tools
Create account
Log in
associated-pages
Module
Discussion
English
Views
Read
Edit source
History
Tools
Search
Discord
Discord
Navigation
Main page
About us
Random page
Special pages
Recent changes
Grey Talon
3h ago
·
NotVeryTerse
Damage Amplification
3h ago
·
Gammaton32
Vindicta/Voice lines
4h ago
·
Mr. Mindish
The Doorman/Sounds
4h ago
·
Gammaton32
Show more...
Interface Admin
Common CSS
Vector CSS
Minerva CSS
Citizen CSS
Brown theme CSS
Gadgets
Gadgets definition
Editing
How to edit
Style guide
All guides
New files
Unresolved feedback
Tools
What links here
Related changes
Page information