Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DarkoniusXNG/Legends-of-Dota-Redux/llms.txt

Use this file to discover all available pages before exploring further.

Overview

pregame.lua is the most important file in Redux. It handles everything that happens before the game clock starts: the lobby phase, hero selection, skill selection, banning, draft arrays, contributor/patron loading, and the initial spawn of heroes. The file also bootstraps the entire scripting layer — it calls require for every other module and registers all Lua modifiers with LinkLuaModifier.

The Pregame class

Pregame is a Lua class defined with Valve’s class({}) helper:
Pregame = class({})
All functionality is added as methods on this singleton. The class is instantiated and Pregame:init() is called from addon_game_mode.lua when the server first activates.

KV loading

Before Pregame:init() runs, the top level of pregame.lua populates GameRules.KVs with every KeyValues file the game needs:
GameRules.KVs = {}
GameRules.KVs["npc_abilities"]          = util.abilityKVs
GameRules.KVs["npc_abilities_custom"]   = LoadKeyValues('scripts/npc/npc_abilities_custom.txt')
GameRules.KVs["npc_abilities_override"] = LoadKeyValues('scripts/npc/npc_abilities_override.txt')
GameRules.KVs.herolist                  = LoadKeyValues('scripts/npc/herolist.txt')
GameRules.KVs.abilitylist              = LoadKeyValues('scripts/kv/abilities.kv')
Other modules access ability data through GameRules.KVs["npc_abilities"] or via util:getAbilityKV().

Modifier registration

All Lua-backed modifiers are registered at the top of pregame.lua before any unit can be given one:
LinkLuaModifier("modifier_neutral_power",
    "abilities/modifiers/modifier_neutral_power.lua",
    LUA_MODIFIER_MOTION_NONE)

LinkLuaModifier("modifier_vampirism_mutator",
    "abilities/mutators/modifier_vampirism_mutator.lua",
    LUA_MODIFIER_MOTION_NONE)

LinkLuaModifier("modifier_hunter_mutator",
    "abilities/mutators/modifier_hunter_mutator.lua",
    LUA_MODIFIER_MOTION_NONE)
-- ... (all mutator modifiers follow the same pattern)

Pregame:init()

Initialises all pregame state. Called once at game start.
function Pregame:init()
    -- Shared option store
    self.optionStore = {}

    -- Write the current map name into OptionManager
    OptionManager:SetOption('mapname', GetMapName())

    -- Redirect single-player lobbies to bot mode
    if util:isSinglePlayerMode() and not IsInToolsMode() then
        CustomNetTables:SetTableValue('phase_pregame', 'forceBots', {value=true})
    end

    -- Hero / skill selection state
    self.selectedHeroes       = {}
    self.selectedPlayerAttr   = {}
    self.selectedSkills       = {}
    self.selectedRandomBuilds = {}

    -- Draft configuration
    self.useDraftArrays   = false
    self.maxDraftHeroes   = 30
    self.maxDraftSkills   = 0

    -- Ban tracking
    self.bannedAbilities  = {}
    self.bannedHeroes     = {}
    self.usedBans         = {}
    self.playerBansList   = {}

    -- Ready state
    self.isReady          = {}

    -- Load sound list
    self.soundList = util:swapTable(LoadKeyValues('scripts/kv/sounds.kv'))

    -- Begin data fetch and move to loading phase
    self:preparePlayerDataFetch()
    self:setPhase(constants.PHASE_LOADING)

    -- Disable automatic game-setup launch
    GameRules:SetCustomGameSetupTimeout(-1)
    GameRules:EnableCustomGameSetupAutoLaunch(false)

    -- Send contributor / patron data to clients
    self:sendContributors()
    self:sendPatrons()
    self:sendPatreonFeatures()
end

Key instance fields

FieldTypeDescription
optionStoretablePer-session option overrides
selectedHeroestableMaps playerID → heroName
selectedPlayerAttrtableMaps playerID → primary attribute
selectedSkillstableMaps playerID → {abilityName, ...}
selectedRandomBuildstableBuilds generated for random picks
bannedAbilitiestableSet of banned ability names
bannedHeroestableSet of banned hero names
usedBanstableNumber of bans used per player
isReadytableMaps playerID → bool
useDraftArraysboolWhether the draft whitelist is active
maxDraftHeroesnumberMax heroes offered in a draft (default 30)
spawnedHeroesFortablePlayer IDs whose heroes have already spawned

Vote option presets

Pregame:init() also populates self.optionVoteSettings with preset lambdas for common game-mode votes. For example:
self.optionVoteSettings = {
    allPick = {
        onselected = function(self)
            self:setOption('lodOptionGamemode', 1, true)
            self:setOption('lodOptionLimitPassives', 1, true)
            self:setOption('lodOptionBalanceMode', 0, true)
        end,
        onunselected = function(self)
            self:setOption('lodOptionGamemode', 5, true)
        end
    },
    -- ... additional presets
}

Function reference

Bootstraps all pregame state, sets the loading phase, and dispatches contributor/patron data to clients. Called once by addon_game_mode.lua.
Transitions the game to the given phase constant (e.g. constants.PHASE_LOADING, constants.PHASE_SELECTION). Broadcasts the new phase to all clients via net tables.
Begins an async HTTP request to fetch historical player data (win rates, abandons) used for display in the pre-game UI.
Pushes contributor, patron, and Patreon feature lists loaded from KV files to the Panorama UI via CustomNetTables.
Writes key → value into self.optionStore and (unless noNetwork is true) broadcasts the change to all clients.
Handles a request from the Panorama ingame hero builder. Respawns the player’s hero with the new build when keys.ingamePicking is true.

Build docs developers (and LLMs) love