diff --git a/Wow.exe b/Wow.exe index 46870af..fb862d7 100644 Binary files a/Wow.exe and b/Wow.exe differ diff --git a/make_modes_in_exe.py b/make_modes_in_exe.py new file mode 100644 index 0000000..fdbf1a6 --- /dev/null +++ b/make_modes_in_exe.py @@ -0,0 +1,339 @@ +""" +Wow.exe binary patcher for MoonWell custom features. + +Patches: + 1. Script_CreateCharacter: reads lua_tonumber(L, 2) as outfitId, + stores to global, passes to CMSG_CHAR_CREATE packet instead of 0. + 2. GetCharacterInfo: adds 11th return value — charFlags as a Lua number, + read from struct_offset +0x170 (same field as ghost flag 0x2000). + Lua checks bit 0x40000000 (CHARACTER_FLAG_UNK31) for traitor status. + +Usage: + python make_modes_in_exe.py + +A backup (Wow.exe.bak) is created before patching. +""" + +import struct +import sys +import shutil +from pathlib import Path + + +# --------------------------------------------------------------------------- +# PE helpers +# --------------------------------------------------------------------------- + +def _u16(data, off): + return struct.unpack_from("= size consecutive CC bytes after search_from_va.""" + text = next((s for s in sections if s[0] == ".text"), None) + if not text is None: + _, va0, vs, ro, rs = text + else: + raise ValueError("No .text section") + + rva_start = max(search_from_va - image_base, va0) + off_start = ro + (rva_start - va0) + off_end = ro + min(vs, rs) + + i = off_start + while i <= off_end - size: + if data[i] != 0xcc: + i += 1 + continue + j = i + while j < off_end and data[j] == 0xcc: + j += 1 + if j - i >= size: + return offset_to_va(i, sections, image_base) + i = j + raise ValueError(f"No {size}-byte code cave found from VA 0x{search_from_va:08x}") + + +# --------------------------------------------------------------------------- +# Patch 1 & 2: outfitId in CMSG_CHAR_CREATE (fixed addresses) +# --------------------------------------------------------------------------- + +_FIXED_PATCHES = [ + ( + 0x004e0c60, + bytes.fromhex( + "558bec568b75086a0156e8f1d23600" + "83c40885c0740d6a006a0156e860d4" + "360083c40c6a006a0156e853d43600" + "50e8edf6ffff83c41033c05e5dc3cc" + "cccccccc" + ), + bytes.fromhex( + "558bec568b75086a0256e8c1d33600" + "db1c245883c404a221 42ac006a006a" + "0156e85bd4360050e8f5f6ffff83c4" + "1033c05e5dc38855f08a1521 42ac00" + "8855f4c3" + ).replace(b" ", b""), # spaces stripped for readability + "Script_CreateCharacter: read outfitId from Lua arg 2 -> global", + ), + ( + 0x004e042f, + bytes.fromhex("8855f0c645f400"), + bytes.fromhex("e85f08000090 90").replace(b" ", b""), + "Packet builder: CALL helper -> load face + outfitId from global", + ), +] + +# --------------------------------------------------------------------------- +# Patch 3: GetCharacterInfo — add 11th return value (charFlags as number) +# --------------------------------------------------------------------------- +# +# Assembly context (FUN_004e3170 epilogue, valid branch): +# +# 004e31cd 56 PUSH ESI ← saves caller's ESI +# 004e31ce 8b f0 MOV ESI, EAX ← ESI = char struct ptr +# ... [function body — ESI used throughout for char struct] ... +# 004e32e5 8b 8e 70010000 MOV ECX, [ESI+0x170] ← charFlags (ghost flag check) +# ... +# 004e332d 83 c4 2c ADD ESP, 0x2c ← clean accumulated args ← PATCH HERE +# 004e3330 5e POP ESI ← restores caller's ESI (ESI valid until here) +# 004e3331 b8 0a 00 00 00 MOV EAX, 0xa (dead after patch) +# 004e3336 5f POP EDI ← JMP back target +# 004e3337 8b e5 MOV ESP, EBP +# 004e3339 5d POP EBP +# 004e333a c3 RET +# +# KEY: ESI = char struct ptr up to and including ADD ESP,0x2c (004e332d). +# After POP ESI (004e3330) it is caller's ESI — NOT char struct. +# Previous approach: CALL cave at 004e3331 (after POP ESI) -> ESI already wrong. +# Fix: JMP cave at 004e332d (before POP ESI) -> ESI still valid in cave. +# +# New approach: patch 5 bytes at 004e332d with JMP cave. +# Old bytes: 83 c4 2c (ADD ESP,0x2c) + 5e (POP ESI) + b8 (MOV EAX first byte) +# New bytes: e9 XX XX XX XX JMP cave +# The 4 dead bytes at 004e3332-004e3335 are unreachable. +# +# Cave (30 bytes, found automatically via CC scan over entire .text): +# 83 ec 08 SUB ESP, 8 ; make room for double +# db 86 70 01 00 00 FILD [ESI+0x170] ; load charFlags into FPU (ESI valid here!) +# dd 1c 24 FSTP [ESP] ; store as double +# 57 PUSH EDI ; lua_State* L +# e8 XX XX XX XX CALL FUN_0084e2a0 ; lua_pushnumber(L, charFlags) +# 83 c4 38 ADD ESP, 0x38 ; merged: own 0xc + stolen 0x2c +# 5e POP ESI ; stolen: restore caller's ESI +# 6a 0b PUSH 0xb ; \ EAX = 11 in 3 bytes +# 58 POP EAX ; / (vs MOV EAX,0xb = 5 bytes) +# e9 XX XX XX XX JMP 004e3336 ; continue epilogue (POP EDI ...) +# +# Lua code reads info[11] and checks bit 0x40000000 (CHARACTER_FLAG_UNK31 = traitor). +# charFlags confirmed at [ESI+0x170]: same field used for ghost flag (AND ECX,0x2000). + +_CHARINFO_PATCH_VA = 0x004e332d # ADD ESP,0x2c (5 bytes including POP ESI + MOV EAX[0]) +_CHARINFO_JMPBACK_VA = 0x004e3336 # POP EDI — resume epilogue after cave +_CHARINFO_CAVE_SIZE = 30 +_CHARINFO_CAVE_SEARCH_FROM = 0x00401000 # search entire .text for first 35-byte CC block +_LUA_PUSHNUMBER_VA = 0x0084e2a0 # lua_pushnumber + + +def _build_charinfo_patches(data, sections, image_base): + """ + Build the dynamic GetCharacterInfo patches. + Returns list of (va, old_bytes, new_bytes, description), [] if already applied, + or None on unrecoverable error. + """ + patch_off = va_to_offset(_CHARINFO_PATCH_VA, sections, image_base) + current = bytes(data[patch_off:patch_off + 5]) + + # Already patched with new JMP approach? + if current[0:1] == b"\xe9": + return [] + + # Verify first 4 bytes look like the epilogue (ADD ESP,0x2c + POP ESI). + # Accept both unpatched (b8 at [4]) and old-CALL-patched (e8 at [4]) states. + if current[0:4] != bytes.fromhex("83c42c5e"): + print(f"[WARN] 0x{_CHARINFO_PATCH_VA:08x}: unexpected bytes {current.hex(' ')}") + print(" Expected ADD ESP,0x2c + POP ESI at this address.") + print(" Restore Wow.exe.bak and re-run.") + return None + + old_b = current # exact 5 bytes currently in file (b8 or e8 at index 4) + + # Find a 35-byte code cave in .text + cave_va = find_cave(data, sections, image_base, + _CHARINFO_CAVE_SIZE, _CHARINFO_CAVE_SEARCH_FROM) + + # Cave layout offsets (30 bytes total): + # 0 SUB ESP,8 (3) + # 3 FILD [ESI+0x170] (6) + # 9 FSTP [ESP] (3) + # 12 PUSH EDI (1) + # 13 CALL lua_pushnumber (5) — next instr at 18 + # 18 ADD ESP, 0x38 (3) merged: own 0xc + stolen 0x2c + # 21 POP ESI (1) stolen + # 22 PUSH 0xb (2) \ shorter than MOV EAX,0xb (5 bytes) + # 24 POP EAX (1) / + # 25 JMP 004e3336 (5) — next instr at cave_va+30 + call_rel = _LUA_PUSHNUMBER_VA - (cave_va + 18) + jmp_back_rel = _CHARINFO_JMPBACK_VA - (cave_va + 30) + + cave_bytes = ( + bytes.fromhex("83ec08") # SUB ESP, 8 (3) + + bytes.fromhex("db8670010000") # FILD [ESI+0x170] (6) + + bytes.fromhex("dd1c24") # FSTP [ESP] (3) + + bytes.fromhex("57") # PUSH EDI (1) + + b"\xe8" + struct.pack(" EAX=11 (1) + + b"\xe9" + struct.pack("") + sys.exit(1) + + exe_path = Path(sys.argv[1]) + if not exe_path.exists(): + print(f"Error: file not found: {exe_path}") + sys.exit(1) + + data = bytearray(exe_path.read_bytes()) + image_base, sections = parse_pe_sections(data) + + print(f"Image base: 0x{image_base:08x}") + print(f"Sections: {len(sections)}") + for n, va, vs, ro, rs in sections: + print(f" {n:8s} VA=0x{va:08x} VSize=0x{vs:08x} Raw=0x{ro:08x} RSize=0x{rs:08x}") + print() + + charinfo_patches = _build_charinfo_patches(data, sections, image_base) + if charinfo_patches is None: + sys.exit(1) + all_patches = list(_FIXED_PATCHES) + charinfo_patches + + # Verify all first + ok = True + for va, old_b, new_b, desc in all_patches: + off = va_to_offset(va, sections, image_base) + cur = bytes(data[off:off + len(old_b)]) + if cur == new_b: + print(f"[SKIP] 0x{va:08x}: already patched — {desc}") + elif cur == old_b: + print(f"[ OK ] 0x{va:08x}: verified — {desc}") + else: + print(f"[FAIL] 0x{va:08x}: {desc}") + print(f" Expected: {old_b.hex(' ')}") + print(f" Found: {cur.hex(' ')}") + ok = False + + if not ok: + print("\nByte mismatch — aborting. Is this the correct Wow.exe (3.3.5a build 12340)?") + sys.exit(1) + + # Backup + bak = exe_path.with_suffix(".exe.bak") + if not bak.exists(): + shutil.copy2(exe_path, bak) + print(f"\nBackup: {bak}") + else: + print(f"\nBackup already exists: {bak}") + + # Apply + applied = 0 + for va, old_b, new_b, desc in all_patches: + off = va_to_offset(va, sections, image_base) + cur = bytes(data[off:off + len(old_b)]) + if cur == new_b: + continue + data[off:off + len(old_b)] = new_b + applied += 1 + print(f"[PATCH] 0x{va:08x}: {desc}") + + if applied == 0: + print("\nNothing to patch.") + else: + exe_path.write_bytes(data) + print(f"\n{applied} patch(es) written to {exe_path}") + + print("Done!") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/Data/ruRU/patch-ruRU-4/Interface/GlueXML/AccountLogin.lua b/src/Data/ruRU/patch-ruRU-4/Interface/GlueXML/AccountLogin.lua index 95963b1..b6e1666 100644 --- a/src/Data/ruRU/patch-ruRU-4/Interface/GlueXML/AccountLogin.lua +++ b/src/Data/ruRU/patch-ruRU-4/Interface/GlueXML/AccountLogin.lua @@ -1,742 +1,1000 @@ -FADE_IN_TIME = 2; -DEFAULT_TOOLTIP_COLOR = {0.8, 0.8, 0.8, 0.09, 0.09, 0.09}; -MAX_PIN_LENGTH = 10; +-- ============================================================================================== +-- MoonWell - SISTEMA DE AUTOLOGIN CON BOTONES DE REDES SOCIALES CON ANIMACIÓN BLP Y ESCENA 3D +-- ============================================================================================== +local Config = { + FADE_IN_TIME = 2, + DEFAULT_TOOLTIP_COLOR = {0.8, 0.8, 0.8, 0.09, 0.09, 0.09}, + MAX_PIN_LENGTH = 10, + AUTO_LOGIN_DELAY = 3.0, + BACKGROUND_TEXTURE = "Interface/Loginscreen/Background.blp", + LOGIN_AMBIENCE = false, + + ENABLE_BLP_ANIMATION = false, + FRAME_COUNT = 3, + ANIMATION_DURATION = 16.0, + FPS_LIMIT = 30, + ANIMATION_PATH = "Interface\\Loginscreen\\Scene\\", + + MODEL_UPDATE_INTERVAL = 0.1, + MODEL_UPDATE_COUNT_REQUIRED = 2, + SCROLL_THRESHOLD = 20, + FADE_DURATION = 0.5, + LOGO_TEXTURE = "Interface\\Glues\\Common\\glues-wow-wotlklogo", + LOGO_SIZE = 225, + LOGO_POSITION_X = 60, + LOGO_POSITION_Y = 40, + CUSTOM_PANEL_WIDTH = 352, + CUSTOM_PANEL_SCROLL_WIDTH = 300, + DEFAULT_FRAME_LEVEL = 2, + AMBIENCE_FADE_TIME = 5.0, + UNDEAD_AMBIENCE_FADE_TIME = 4.0, + SFX_STOP_TIME = 1.0, + TOS_FRAME_WIDTH = 640, + TOS_FRAME_HEIGHT = 512, + TOS_SCROLL_WIDTH = 540, + TOS_SCROLL_HEIGHT = 407, + TOS_HEADER_WIDTH = 300, + TOS_TITLE_OFFSET = 12, + TOS_TEXT_OFFSET = 56, + BUTTON_HEIGHT_SMALL = 38, + BUTTON_HEIGHT_LARGE = 55, + CINEMATICS_BUTTON_HEIGHT = 80, + CINEMATICS_BACKGROUND_HEIGHT_BASE = 70 +} + +local LoginState = { + autoLoginTimer = nil, autoLoginDelay = Config.AUTO_LOGIN_DELAY, autoLoginAttempted = false, musicTimer = 0, sceneTimer = 0, currentFrame = 0, lastUpdateTime = 0, currentScene = 1 +} + +local ModelManager = { + models = {}, loginModels = {} +} + +local UICache = { + accountEdit = nil, passwordEdit = nil, saveAccountName = nil, savePassword = nil, autoLogin = nil, autoLoginText = nil, loginButton = nil, versionText = nil, realmName = nil, upgradeButton = nil, tosFrame = nil, tosAccept = nil, tosDecline = nil, backgroundTexture = nil, animatedTexture = nil, newLogo = nil, newLogoFrame = nil +} + +LOGIN_MODEL_LIGHTS = { + [0] = {1, 0, 0, -0.707, -0.707, 0.7, 1.0, 1.0, 1.0, 0, 1.0, 1.0, 0.8}, +} +LOGIN_MODEL_STRUCT = { + SCENE_ID = 1, POS_Y = 2, POS_Z = 3, POS_X = 4, FACING = 5, SCALE = 6, ALPHA = 7, LIGHT = 8, SEQUENCE = 9, WIDTH_SQUISH = 10, HEIGHT_SQUISH = 11, MODEL_PATH = 12, +} + +LOGIN_MODELS = { + {1, 0.000, 0.300, 0.285, 0.684, 0.085, 1.000, LOGIN_MODEL_LIGHTS[0], 1, 1, 1, "Environments\\Stars\\icecrownarthasdeathsky.m2"}, + {1, -0.712, 0.800, 0.000, 6.245, 0.100, 0.400, LOGIN_MODEL_LIGHTS[0], 1, 1, 1, "Environments\\Stars\\aurorayellowgreen.m2"}, + {1, -0.712, -0.750, 0.000, 6.245, 0.100, 0.500, LOGIN_MODEL_LIGHTS[0], 1, 1, 1, "Environments\\Stars\\auroraorange.m2"}, +} + +BACKGROUND_MODELS = { + ["Environments\\Stars\\icecrownarthasdeathsky.m2"] = { frameLevel = 0 }, +} +-- ==================== CONFIGURACIÓN ADICIONAL ==================== +local function InitializeUICache() + UICache.accountEdit = _G["AccountLoginAccountEdit"] + UICache.passwordEdit = _G["AccountLoginPasswordEdit"] + UICache.saveAccountName = _G["AccountLoginSaveAccountName"] + UICache.savePassword = _G["AccountLoginSavePassword"] + UICache.autoLogin = _G["AccountLoginAutoLogin"] + UICache.autoLoginText = _G["AccountLoginAutoLoginText"] + UICache.loginButton = _G["AccountLoginLoginButton"] + UICache.versionText = _G["AccountLoginVersion"] + UICache.realmName = _G["AccountLoginRealmName"] + UICache.upgradeButton = _G["AccountLoginUpgradeAccountButton"] + UICache.tosFrame = _G["TOSFrame"] + UICache.tosAccept = _G["TOSAccept"] + UICache.tosDecline = _G["TOSDecline"] +end + +function GetLoginConfig() + return Config +end + +function GetLoginState() + return LoginState +end +-- ============================================================================ +-- SISTEMA DE ANIMACIÓN BLP +-- ============================================================================ +local function UpdateBackgroundAnimation(self, elapsed) + if not Config.ENABLE_BLP_ANIMATION or Config.FRAME_COUNT <= 0 then + return + end + + local currentTime = GetTime() + if (currentTime - LoginState.lastUpdateTime) < (1 / Config.FPS_LIMIT) then + return + end + + LoginState.lastUpdateTime = currentTime + LoginState.currentFrame = (LoginState.currentFrame + 1) % Config.FRAME_COUNT + + if self.animatedTexture then + local texturePath = Config.ANIMATION_PATH .. string.format("%04d.blp", LoginState.currentFrame) + self.animatedTexture:SetTexture(texturePath) + end +end +-- ============================================================================ +-- DIÁLOGOS +-- ============================================================================ +GlueDialogTypes["REMEMBER_PASSWORD"] = { + text = SAVE_PASSWORD_NOTICE, + button1 = OKAY, + button2 = CANCEL, + OnAccept = function() + UICache.autoLoginText:Show() + UICache.autoLogin:Show() + end, + OnCancel = function() + UICache.savePassword:SetChecked(0) + UICache.autoLoginText:Hide() + UICache.autoLogin:Hide() + UICache.autoLogin:SetChecked(0) + end, +} + +GlueDialogTypes["AUTO_LOGIN"] = { + text = SAVE_AUTOLOGIN_NOTICE, + button1 = OKAY, + button2 = CANCEL, + OnAccept = function() + end, + OnCancel = function() + UICache.autoLogin:SetChecked(0) + end, +} +-- ============================================================================ +-- GESTIÓN DE MODELOS 3D +-- ============================================================================ +local function CreateLoginModel(parent, modelData) + local model = CreateFrame("Model", nil, parent) + local width, height = parent:GetSize() + + model:SetSize( + width * (modelData[LOGIN_MODEL_STRUCT.WIDTH_SQUISH] or 1), + height * (modelData[LOGIN_MODEL_STRUCT.HEIGHT_SQUISH] or 1) + ) + model:SetPoint("CENTER") + model:SetModel("Character/Human/Male/HumanMale.mdx") + model:SetCamera(1) + model:SetModel(modelData[LOGIN_MODEL_STRUCT.MODEL_PATH]) + model:SetPosition( + modelData[LOGIN_MODEL_STRUCT.POS_X], + modelData[LOGIN_MODEL_STRUCT.POS_Y], + modelData[LOGIN_MODEL_STRUCT.POS_Z] + ) + model:SetFacing(modelData[LOGIN_MODEL_STRUCT.FACING]) + model:SetModelScale(modelData[LOGIN_MODEL_STRUCT.SCALE]) + model:SetAlpha(modelData[LOGIN_MODEL_STRUCT.ALPHA]) + model:SetSequence(modelData[LOGIN_MODEL_STRUCT.SEQUENCE]) + + if modelData[LOGIN_MODEL_STRUCT.LIGHT] then + model:SetLight(unpack(modelData[LOGIN_MODEL_STRUCT.LIGHT])) + end + + return model +end + +local function InitializeLoginScene(parent) + for _, model in ipairs(ModelManager.loginModels) do + model:Hide() + model:SetParent(nil) + end + ModelManager.loginModels = {} + + for _, modelData in ipairs(LOGIN_MODELS) do + if modelData[LOGIN_MODEL_STRUCT.SCENE_ID] == LoginState.currentScene then + local model = CreateLoginModel(parent, modelData) + table.insert(ModelManager.loginModels, model) + end + end +end +-- ============================================================================ +-- ACTUALIZACIÓN DE LA ESCENA +-- ============================================================================ +function LoginScene_OnUpdate(self, elapsed) + if Config.LOGIN_AMBIENCE and not self.ambiencePlayed then + PlayGlueAmbience(Config.LOGIN_AMBIENCE, Config.AMBIENCE_FADE_TIME) + self.ambiencePlayed = true + end + + if LoginState.autoLoginTimer and LoginState.autoLoginTimer < LoginState.autoLoginDelay then + LoginState.autoLoginTimer = LoginState.autoLoginTimer + elapsed + if LoginState.autoLoginTimer >= LoginState.autoLoginDelay then + AccountLogin_Login() + LoginState.autoLoginTimer = nil + end + end + UpdateBackgroundAnimation(self, elapsed) + + if not self.modelsInitialized and self.Models then + self.modelUpdateTimer = (self.modelUpdateTimer or 0) + elapsed + + if self.modelUpdateTimer >= Config.MODEL_UPDATE_INTERVAL then + self.modelUpdateTimer = 0 + self.modelUpdateCount = (self.modelUpdateCount or 0) + 1 + + if self.modelUpdateCount == 1 then + for i = 1, #self.Models do + local model = self.Models[i] + local data = LOGIN_MODELS[i] + + if model and data then + model:SetModel(data[LOGIN_MODEL_STRUCT.MODEL_PATH]) + model:SetPosition(data[LOGIN_MODEL_STRUCT.POS_X], data[LOGIN_MODEL_STRUCT.POS_Y], data[LOGIN_MODEL_STRUCT.POS_Z]) + model:SetFacing(data[LOGIN_MODEL_STRUCT.FACING]) + model:SetModelScale(data[LOGIN_MODEL_STRUCT.SCALE]) + model:SetSequence(data[LOGIN_MODEL_STRUCT.SEQUENCE]) + if data[LOGIN_MODEL_STRUCT.LIGHT] then + model:SetLight(unpack(data[LOGIN_MODEL_STRUCT.LIGHT])) + end + model:Show() + end + end + end + if self.modelUpdateCount >= Config.MODEL_UPDATE_COUNT_REQUIRED then + self.modelsInitialized = true + self.modelsCreated = true + self.modelUpdateTimer = nil + self.modelUpdateCount = nil + end + end + end + LoginState.sceneTimer = LoginState.sceneTimer + elapsed +end +-- ============================================================================ +-- INICIALIZACIÓN Y EVENTOS +-- ============================================================================ +local function isBackgroundModel(modelPath) + return BACKGROUND_MODELS[modelPath] ~= nil +end + +local function getModelFrameLevel(modelPath) + return isBackgroundModel(modelPath) and BACKGROUND_MODELS[modelPath].frameLevel or Config.DEFAULT_FRAME_LEVEL +end function AccountLogin_OnLoad(self) - TOSFrame.noticeType = "EULA"; + InitializeUICache() + + AccountLogin_SetupServerAlert() + + UICache.tosFrame.noticeType = "EULA" + self:RegisterEvent("SHOW_SERVER_ALERT") + self:RegisterEvent("SHOW_SURVEY_NOTIFICATION") + self:RegisterEvent("CLIENT_ACCOUNT_MISMATCH") + self:RegisterEvent("CLIENT_TRIAL") + self:RegisterEvent("SCANDLL_ERROR") + self:RegisterEvent("SCANDLL_FINISHED") + + local versionType, buildType, version, internalVersion, date = GetBuildInfo() + UICache.versionText:SetText(buildType.." "..version.." ("..internalVersion..")") + + local backdropColor = Config.DEFAULT_TOOLTIP_COLOR + UICache.accountEdit:SetBackdropBorderColor(backdropColor[1], backdropColor[2], backdropColor[3]) + UICache.accountEdit:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6]) + UICache.passwordEdit:SetBackdropBorderColor(backdropColor[1], backdropColor[2], backdropColor[3]) + UICache.passwordEdit:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6]) - self:RegisterEvent("SHOW_SERVER_ALERT"); - self:RegisterEvent("SHOW_SURVEY_NOTIFICATION"); - self:RegisterEvent("CLIENT_ACCOUNT_MISMATCH"); - self:RegisterEvent("CLIENT_TRIAL"); - self:RegisterEvent("SCANDLL_ERROR"); - self:RegisterEvent("SCANDLL_FINISHED"); + self.Models = {} + for i = 1, #LOGIN_MODELS do + local data = LOGIN_MODELS[i] + local model = CreateFrame("Model", "AccountLoginModel"..i, self) - local versionType, buildType, version, internalVersion, date = GetBuildInfo(); - AccountLoginVersion:SetFormattedText(VERSION_TEMPLATE, versionType, version, internalVersion, buildType, date); + model:SetModel("Character/Human/Male/HumanMale.mdx") + model:SetPoint("CENTER", 0, 0) + model:SetSize(self:GetWidth() / (data[LOGIN_MODEL_STRUCT.WIDTH_SQUISH] or 1), + self:GetHeight() / (data[LOGIN_MODEL_STRUCT.HEIGHT_SQUISH] or 1)) + model:SetCamera(1) + + if data[LOGIN_MODEL_STRUCT.LIGHT] then + model:SetLight(unpack(data[LOGIN_MODEL_STRUCT.LIGHT])) + end + model:SetAlpha(data[LOGIN_MODEL_STRUCT.ALPHA]) + + local frameLevel = getModelFrameLevel(data[LOGIN_MODEL_STRUCT.MODEL_PATH]) + model:SetFrameLevel(frameLevel) + + if frameLevel == 0 then + model:SetFrameStrata("LOW") + end + model:Hide() + self.Models[i] = model + end + self.modelUpdateCount = 0 + self.modelUpdateTimer = 0 + self.modelsInitialized = false + self.ambiencePlayed = false + self.modelsCreated = false - -- Color edit box backdrops - local backdropColor = DEFAULT_TOOLTIP_COLOR; - AccountLoginAccountEdit:SetBackdropBorderColor(backdropColor[1], backdropColor[2], backdropColor[3]); - AccountLoginAccountEdit:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6]); - AccountLoginPasswordEdit:SetBackdropBorderColor(backdropColor[1], backdropColor[2], backdropColor[3]); - AccountLoginPasswordEdit:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6]); - AccountLoginTokenEdit:SetBackdropBorderColor(backdropColor[1], backdropColor[2], backdropColor[3]); - AccountLoginTokenEdit:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6]); - TokenEnterDialogBackgroundEdit:SetBackdropBorderColor(backdropColor[1], backdropColor[2], backdropColor[3]); - TokenEnterDialogBackgroundEdit:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6]); - - self:SetCamera(0); - self:SetSequence(0); - - if (IsStreamingTrial()) then - AccountLoginCinematicsButton:Disable(); - AccountLogin:SetModel("Interface\\Glues\\Models\\UI_MainMenu\\UI_MainMenu.m2"); - else - AccountLogin:SetModel("Interface\\Glues\\Models\\UI_RS_NightElf\\UI_RS_NightElf.m2"); - end + AcceptTOS() + AcceptEULA() end function AccountLogin_OnShow(self) - self:SetSequence(0); - PlayGlueMusic(CurrentGlueMusic); - PlayGlueAmbience(GlueAmbienceTracks["DARKPORTAL"], 4.0); + self:Show() + self:SetAlpha(1) + WorldOfWarcraftRating:Hide() + if not self.backgroundTexture then + self.backgroundTexture = self:CreateTexture("AccountLoginBackground", "BACKGROUND") + self.backgroundTexture:SetTexture(Config.BACKGROUND_TEXTURE) + self.backgroundTexture:SetAllPoints(self) + self.backgroundTexture:SetTexCoord(0, 1, 0, 1) + UICache.backgroundTexture = self.backgroundTexture + else + self.backgroundTexture:Show() + end - -- Try to show the EULA or the TOS - AccountLogin_ShowUserAgreements(); - - local serverName = GetServerName(); - if(serverName) then - AccountLoginRealmName:SetText(serverName); - else - AccountLoginRealmName:Hide() - end + if Config.ENABLE_BLP_ANIMATION and Config.FRAME_COUNT > 0 then + if not self.animatedTexture then + self.animatedTexture = self:CreateTexture("AccountLoginAnimatedBackground", "BACKGROUND") + self.animatedTexture:SetAllPoints(self) + self.animatedTexture:SetTexture(Config.ANIMATION_PATH .. "0000.blp") + UICache.animatedTexture = self.animatedTexture + LoginState.currentFrame = 0 + LoginState.lastUpdateTime = GetTime() + else + self.animatedTexture:Show() + LoginState.currentFrame = 0 + LoginState.lastUpdateTime = GetTime() + end + elseif self.animatedTexture then + self.animatedTexture:Hide() + end + AccountLoginUI:Show() + AccountLoginUI:SetAlpha(1) - local accountName = GetSavedAccountName(); - - AccountLoginAccountEdit:SetText(accountName); - AccountLoginPasswordEdit:SetText(""); - AccountLoginTokenEdit:SetText(""); - if ( accountName and accountName ~= "" and GetUsesToken() ) then - AccountLoginTokenEdit:Show() - else - AccountLoginTokenEdit:Hide() - end - - AccountLogin_SetupAccountListDDL(); - - if ( accountName == "" ) then - AccountLogin_FocusAccountName(); - else - AccountLogin_FocusPassword(); - end - - if( IsTrialAccount() ) then - AccountLoginUpgradeAccountButton:Show(); - else - AccountLoginUpgradeAccountButton:Hide(); - end + if not self.newLogo then + self.newLogoFrame = CreateFrame("Frame", nil, self) + self.newLogoFrame:SetSize(Config.LOGO_SIZE, Config.LOGO_SIZE) + self.newLogoFrame:SetPoint("TOPLEFT", Config.LOGO_POSITION_X, Config.LOGO_POSITION_Y) + + self.newLogo = self.newLogoFrame:CreateTexture("AccountLoginNewLogo", "OVERLAY") + self.newLogo:SetTexture(Config.LOGO_TEXTURE) + self.newLogo:SetAllPoints(self.newLogoFrame) + self.newLogo:Show() + UICache.newLogo = self.newLogo + UICache.newLogoFrame = self.newLogoFrame + else + self.newLogoFrame:Show() + end - ACCOUNT_MSG_NUM_AVAILABLE = 0; - ACCOUNT_MSG_PRIORITY = 0; - ACCOUNT_MSG_HEADERS_LOADED = false; - ACCOUNT_MSG_BODY_LOADED = false; - ACCOUNT_MSG_CURRENT_INDEX = nil; + if self.Models then + for i = 1, #self.Models do + local model = self.Models[i] + if model then + model:Show() + end + end + end + + if self.modelsCreated then + self.modelsInitialized = true + else + self.modelsInitialized = false + end + self.modelUpdateCount = 0 + self.modelUpdateTimer = 0 + + local accountName, password = unpack(string_explode(GetSavedAccountName(), "#&|&#")) + UICache.accountEdit:SetText(accountName or "") + UICache.passwordEdit:SetText(password or "") + + PlayGlueAmbience("GlueScreenUndead", Config.UNDEAD_AMBIENCE_FADE_TIME) + AccountLogin_ShowUserAgreements() + + local serverName = GetServerName() + if serverName then + UICache.realmName:SetText(serverName) + else + UICache.realmName:SetText("No Recent Server") + end + + if accountName == "" then + AccountLogin_FocusAccountName() + else + AccountLogin_FocusPassword() + end + + if UICache.savePassword:GetChecked() then + UICache.autoLoginText:Show() + UICache.autoLogin:Show() + else + UICache.autoLoginText:Hide() + UICache.autoLogin:Hide() + end + + if IsTrialAccount() then + UICache.upgradeButton:Show() + else + UICache.upgradeButton:Hide() + end + ACCOUNT_MSG_NUM_AVAILABLE = 0 + ACCOUNT_MSG_PRIORITY = 0 + ACCOUNT_MSG_HEADERS_LOADED = false + ACCOUNT_MSG_BODY_LOADED = false + ACCOUNT_MSG_CURRENT_INDEX = nil + + AccountLogin_CheckAutoLogin() + self:SetScript("OnUpdate", LoginScene_OnUpdate) end function AccountLogin_OnHide(self) - --Stop the sounds from the login screen (like the dragon roaring etc) - StopAllSFX( 1.0 ); - if ( not AccountLoginSaveAccountName:GetChecked() ) then - SetSavedAccountList(""); - end + StopAllSFX(Config.SFX_STOP_TIME) + if not UICache.saveAccountName:GetChecked() then + SetSavedAccountList("") + end + self:SetScript("OnUpdate", nil) + + if self.Models then + for i = 1, #self.Models do + local model = self.Models[i] + if model then + model:Hide() + end + end + end + self.modelsInitialized = false + self.ambiencePlayed = false + + if UICache.backgroundTexture then + UICache.backgroundTexture:Hide() + end + if UICache.animatedTexture then + UICache.animatedTexture:Hide() + end + if UICache.newLogoFrame then + UICache.newLogoFrame:Hide() + end + StopGlueAmbience() end function AccountLogin_FocusPassword() - AccountLoginPasswordEdit:SetFocus(); + UICache.passwordEdit:SetFocus() end function AccountLogin_FocusAccountName() - AccountLoginAccountEdit:SetFocus(); + UICache.accountEdit:SetFocus() end function AccountLogin_OnKeyDown(key) - if ( key == "ESCAPE" ) then - if ( ConnectionHelpFrame:IsShown() ) then - ConnectionHelpFrame:Hide(); - AccountLoginUI:Show(); - elseif ( SurveyNotificationFrame:IsShown() ) then - -- do nothing - else - AccountLogin_Exit(); - end - elseif ( key == "ENTER" ) then - if ( not TOSAccepted() ) then - return; - elseif ( TOSFrame:IsShown() or ConnectionHelpFrame:IsShown() ) then - return; - elseif ( SurveyNotificationFrame:IsShown() ) then - AccountLogin_SurveyNotificationDone(1); - end - AccountLogin_Login(); - elseif ( key == "PRINTSCREEN" ) then - Screenshot(); - end + if key == "ESCAPE" then + if ConnectionHelpFrame:IsShown() then + ConnectionHelpFrame:Hide() + AccountLoginUI:Show() + elseif SurveyNotificationFrame:IsShown() then + else + AccountLogin_Exit() + end + elseif key == "ENTER" then + if not TOSAccepted() then + return + elseif TOSFrame:IsShown() or ConnectionHelpFrame:IsShown() then + return + elseif SurveyNotificationFrame:IsShown() then + AccountLogin_SurveyNotificationDone(1) + end + AccountLogin_Login() + elseif key == "PRINTSCREEN" then + Screenshot() + end end function AccountLogin_OnEvent(event, arg1, arg2, arg3) - if ( event == "SHOW_SERVER_ALERT" ) then - ServerAlertText:SetText(arg1); - ServerAlertFrame:Show(); - elseif ( event == "SHOW_SURVEY_NOTIFICATION" ) then - AccountLogin_ShowSurveyNotification(); - elseif ( event == "CLIENT_ACCOUNT_MISMATCH" ) then - local accountExpansionLevel = arg1; - local installationExpansionLevel = arg2; - if ( accountExpansionLevel == 1 ) then - GlueDialog_Show("CLIENT_ACCOUNT_MISMATCH", CLIENT_ACCOUNT_MISMATCH_BC); - else - GlueDialog_Show("CLIENT_ACCOUNT_MISMATCH", CLIENT_ACCOUNT_MISMATCH_LK); - end - elseif ( event == "CLIENT_TRIAL" ) then - GlueDialog_Show("CLIENT_TRIAL"); - elseif ( event == "SCANDLL_ERROR" ) then - GlueDialog:Hide(); - ScanDLLContinueAnyway(); - AccountLoginUI:Show(); - elseif ( event == "SCANDLL_FINISHED" ) then - if ( arg1 == "OK" ) then - GlueDialog:Hide(); - AccountLoginUI:Show(); - else - AccountLogin.hackURL = _G["SCANDLL_URL_"..arg1]; - AccountLogin.hackName = arg2; - AccountLogin.hackType = arg1; - local formatString = _G["SCANDLL_MESSAGE_"..arg1]; - if ( arg3 == 1 ) then - formatString = _G["SCANDLL_MESSAGE_HACKNOCONTINUE"]; - end - local msg = format(formatString, AccountLogin.hackName, AccountLogin.hackURL); - if ( arg3 == 1 ) then - GlueDialog_Show("SCANDLL_HACKFOUND_NOCONTINUE", msg); - else - GlueDialog_Show("SCANDLL_HACKFOUND", msg); - end - PlaySoundFile("Sound\\Creature\\MobileAlertBot\\MobileAlertBotIntruderAlert01.wav"); - end - end + if event == "SHOW_SERVER_ALERT" then + ServerAlertText:SetText(arg1) + ServerAlertFrame:Show() + elseif event == "SHOW_SURVEY_NOTIFICATION" then + AccountLogin_ShowSurveyNotification() + elseif event == "CLIENT_ACCOUNT_MISMATCH" then + local accountExpansionLevel = arg1 + local installationExpansionLevel = arg2 + if accountExpansionLevel == 1 then + GlueDialog_Show("CLIENT_ACCOUNT_MISMATCH", CLIENT_ACCOUNT_MISMATCH_BC) + else + GlueDialog_Show("CLIENT_ACCOUNT_MISMATCH", CLIENT_ACCOUNT_MISMATCH_LK) + end + elseif event == "CLIENT_TRIAL" then + GlueDialog_Show("CLIENT_TRIAL") + elseif event == "SCANDLL_ERROR" then + GlueDialog:Hide() + ScanDLLContinueAnyway() + AccountLoginUI:Show() + elseif event == "SCANDLL_FINISHED" then + if arg1 == "OK" then + GlueDialog:Hide() + AccountLoginUI:Show() + else + AccountLogin.hackURL = _G["SCANDLL_URL_"..arg1] + AccountLogin.hackName = arg2 + AccountLogin.hackType = arg1 + local formatString = _G["SCANDLL_MESSAGE_"..arg1] + if arg3 == 1 then + formatString = _G["SCANDLL_MESSAGE_HACKNOCONTINUE"] + end + local msg = format(formatString, AccountLogin.hackName, AccountLogin.hackURL) + if arg3 == 1 then + GlueDialog_Show("SCANDLL_HACKFOUND_NOCONTINUE", msg) + else + GlueDialog_Show("SCANDLL_HACKFOUND", msg) + end + PlaySoundFile("Sound\\Creature\\MobileAlertBot\\MobileAlertBotIntruderAlert01.wav") + end + end end - +-- ============================================================================ +-- SISTEMA DE LOGIN CON GUARDADO DE CONTRASEÑA +-- ============================================================================ function AccountLogin_Login() - PlaySound("gsLogin"); - DefaultServerLogin(AccountLoginAccountEdit:GetText(), AccountLoginPasswordEdit:GetText()); - AccountLoginPasswordEdit:SetText(""); - - if ( AccountLoginSaveAccountName:GetChecked() ) then - SetSavedAccountName(AccountLoginAccountEdit:GetText()); - else - SetSavedAccountName(""); - SetUsesToken(false); - end + PlaySound("gsLogin") + local accountName = UICache.accountEdit:GetText() + local password = UICache.passwordEdit:GetText() + local savedData = "" + + if UICache.saveAccountName:GetChecked() then + if UICache.savePassword:GetChecked() then + local autoLoginFlag = UICache.autoLogin:GetChecked() and "1" or "0" + savedData = accountName.."#&|&#"..password.."#&|&#"..autoLoginFlag + else + local autoLoginFlag = UICache.autoLogin:GetChecked() and "1" or "0" + savedData = accountName.."#&|&#".."".."#&|&#"..autoLoginFlag + end + else + if UICache.autoLogin:GetChecked() then + GlueDialog_Show("AUTO_LOGIN_NEEDS_ACCOUNT") + UICache.autoLogin:SetChecked(0) + end + SetSavedAccountName("") + SetUsesToken(false) + end + + if savedData ~= "" then + SetSavedAccountName(savedData) + end + DefaultServerLogin(accountName, password) +end +-- ============================================================================ +-- SISTEMA DE AUTOLOGIN +-- ============================================================================ +function AccountLogin_CheckAutoLogin() + if not LoginState.autoLoginAttempted then + LoginState.autoLoginAttempted = true + local savedAccountInfo = GetSavedAccountName() + + if savedAccountInfo and savedAccountInfo ~= "" then + local accountData = string_explode(savedAccountInfo, "#&|&#") + local accountName = accountData[1] or "" + local password = accountData[2] or "" + local autoLogin = accountData[3] or "0" + + if autoLogin == "1" and accountName ~= "" and password ~= "" then + LoginState.autoLoginTimer = 0 + LoginState.autoLoginDelay = Config.AUTO_LOGIN_DELAY + else + LoginState.autoLoginTimer = nil + end + end + end +end +-- ============================================================================ +-- ANIMACIÓN PARA SERVER ALERT FRAME +-- ============================================================================ +function AccountLogin_ToggleServerAlert() + local frame = ServerAlertFrame + if not frame then return end + + if frame.isAnimating then + return + end + + if frame.fadeInfo then + frame:SetScript("OnUpdate", nil) + frame.fadeInfo = nil + end + + frame.isAnimating = true + + local logoTexture = UICache.newLogo + + if frame:IsShown() then + local startWidth = frame:GetWidth() + local scrollFrame = _G["ServerAlertScrollFrame"] + + if not scrollFrame then + frame:Hide() + frame.isAnimating = false + return + end + + local startScrollWidth = scrollFrame:GetWidth() + + frame.fadeInfo = { + mode = "OUT", + timeToFade = 0.5, + startAlpha = 1, + endAlpha = 0, + startWidth = startWidth, + endWidth = 0, + startScrollWidth = startScrollWidth, + endScrollWidth = 0, + scrollFrame = scrollFrame, + savedWidth = startWidth, + savedScrollWidth = startScrollWidth, + logoAlpha = logoTexture and logoTexture:GetAlpha() or 1, + logoEndAlpha = 0 + } + + frame:SetScript("OnUpdate", function(self, elapsed) + if not self.fadeInfo then return end + local fadeInfo = self.fadeInfo + fadeInfo.elapsed = (fadeInfo.elapsed or 0) + elapsed + + if fadeInfo.elapsed < fadeInfo.timeToFade then + local progress = fadeInfo.elapsed / fadeInfo.timeToFade + self:SetAlpha(fadeInfo.startAlpha + (fadeInfo.endAlpha - fadeInfo.startAlpha) * progress) + + if logoTexture then + local logoProgress = progress + local logoAlpha = fadeInfo.logoAlpha + (fadeInfo.logoEndAlpha - fadeInfo.logoAlpha) * logoProgress + logoTexture:SetAlpha(logoAlpha) + end + + local currentWidth = fadeInfo.startWidth + (fadeInfo.endWidth - fadeInfo.startWidth) * progress + self:SetWidth(currentWidth) + + local currentScrollWidth = fadeInfo.startScrollWidth + (fadeInfo.endScrollWidth - fadeInfo.startScrollWidth) * progress + if fadeInfo.scrollFrame then + fadeInfo.scrollFrame:SetWidth(currentScrollWidth) + end + else + self:SetAlpha(fadeInfo.endAlpha) + self:SetWidth(fadeInfo.endWidth) + + if logoTexture then + logoTexture:SetAlpha(fadeInfo.logoEndAlpha) + end + + if fadeInfo.scrollFrame then + fadeInfo.scrollFrame:SetWidth(fadeInfo.endScrollWidth) + end + + self:Hide() + self:SetWidth(fadeInfo.savedWidth or 341) + if fadeInfo.scrollFrame then + fadeInfo.scrollFrame:SetWidth(fadeInfo.savedScrollWidth or 300) + end + + self:SetScript("OnUpdate", nil) + self.fadeInfo = nil + self.isAnimating = false + end + end) + else + local targetWidth = 341 + local targetScrollWidth = 300 + + local scrollFrame = _G["ServerAlertScrollFrame"] + if not scrollFrame then + frame:Show() + frame.isAnimating = false + return + end + + frame:SetWidth(0) + scrollFrame:SetWidth(0) + frame:SetAlpha(0) + frame:Show() + + if logoTexture then + logoTexture:SetAlpha(0) + logoTexture:Show() + end + + frame.fadeInfo = { + mode = "IN", + timeToFade = 0.5, + startAlpha = 0, + endAlpha = 1, + startWidth = 0, + endWidth = targetWidth, + startScrollWidth = 0, + endScrollWidth = targetScrollWidth, + scrollFrame = scrollFrame, + logoAlpha = 0, + logoEndAlpha = 1 + } + + frame:SetScript("OnUpdate", function(self, elapsed) + if not self.fadeInfo then return end + local fadeInfo = self.fadeInfo + fadeInfo.elapsed = (fadeInfo.elapsed or 0) + elapsed + + if fadeInfo.elapsed < fadeInfo.timeToFade then + local progress = fadeInfo.elapsed / fadeInfo.timeToFade + self:SetAlpha(fadeInfo.startAlpha + (fadeInfo.endAlpha - fadeInfo.startAlpha) * progress) + + if logoTexture then + local logoProgress = progress + local logoAlpha = fadeInfo.logoAlpha + (fadeInfo.logoEndAlpha - fadeInfo.logoAlpha) * logoProgress + logoTexture:SetAlpha(logoAlpha) + end + + local currentWidth = fadeInfo.startWidth + (fadeInfo.endWidth - fadeInfo.startWidth) * progress + self:SetWidth(currentWidth) + + local currentScrollWidth = fadeInfo.startScrollWidth + (fadeInfo.endScrollWidth - fadeInfo.startScrollWidth) * progress + if fadeInfo.scrollFrame then + fadeInfo.scrollFrame:SetWidth(currentScrollWidth) + end + else + self:SetAlpha(fadeInfo.endAlpha) + self:SetWidth(fadeInfo.endWidth) + + if logoTexture then + logoTexture:SetAlpha(fadeInfo.logoEndAlpha) + end + + if fadeInfo.scrollFrame then + fadeInfo.scrollFrame:SetWidth(fadeInfo.endScrollWidth) + end + + self:SetScript("OnUpdate", nil) + self.fadeInfo = nil + self.isAnimating = false + end + end) + end + PlaySound("gsLoginNewAccount") end +function AccountLogin_SetupServerAlert() + if ServerAlertFrame then + ServerAlertFrame.isAnimating = false + ServerAlertFrame.fadeInfo = nil + end +end +-- ============================================================================ +-- FUNCIONES ADICIONALES +-- ============================================================================ function AccountLogin_TOS() - if ( not GlueDialog:IsShown() ) then - PlaySound("gsLoginNewAccount"); - AccountLoginUI:Hide(); - TOSFrame:Show(); - TOSScrollFrameScrollBar:SetValue(0); - TOSScrollFrame:Show(); - TOSFrameTitle:SetText(TOS_FRAME_TITLE); - TOSText:Show(); - end + if not GlueDialog:IsShown() then + PlaySound("gsLoginNewAccount") + AccountLoginUI:Hide() + UICache.tosFrame:Show() + TOSScrollFrameScrollBar:SetValue(0) + TOSScrollFrame:Show() + TOSFrameTitle:SetText(TOS_FRAME_TITLE) + TOSText:Show() + end end function AccountLogin_ManageAccount() - PlaySound("gsLoginNewAccount"); - LaunchURL(AUTH_NO_TIME_URL); + PlaySound("gsLoginNewAccount") + LaunchURL(AUTH_NO_TIME_URL) end function AccountLogin_LaunchCommunitySite() - PlaySound("gsLoginNewAccount"); - LaunchURL(COMMUNITY_URL); + PlaySound("gsLoginNewAccount") + LaunchURL(COMMUNITY_URL) end function CharacterSelect_UpgradeAccount() - PlaySound("gsLoginNewAccount"); - LaunchURL(AUTH_NO_TIME_URL); + PlaySound("gsLoginNewAccount") + LaunchURL(AUTH_NO_TIME_URL) end function AccountLogin_Credits() - CreditsFrame.creditsType = 3; - PlaySound("gsTitleCredits"); - SetGlueScreen("credits"); + CreditsFrame.creditsType = 3 + PlaySound("gsTitleCredits") + SetGlueScreen("credits") end function AccountLogin_Cinematics() - if ( not GlueDialog:IsShown() ) then - PlaySound("gsLoginNewAccount"); - if ( CinematicsFrame.numMovies > 1 ) then - CinematicsFrame:Show(); - else - MovieFrame.version = 1; - SetGlueScreen("movie"); - end - end + if not GlueDialog:IsShown() then + PlaySound("gsLoginNewAccount") + MOVIE_RETURN_SCREEN = "login" + if CinematicsFrame.numMovies > 1 then + CinematicsFrame:Show() + else + MovieFrame.version = 1 + SetGlueScreen("movie") + end + end end function AccountLogin_Options() - PlaySound("gsTitleOptions"); + PlaySound("gsTitleOptions") end function AccountLogin_Exit() --- PlaySound("gsTitleQuit"); - QuitGame(); + QuitGame() end function AccountLogin_ShowSurveyNotification() - GlueDialog:Hide(); - AccountLoginUI:Hide(); - SurveyNotificationAccept:Enable(); - SurveyNotificationDecline:Enable(); - SurveyNotificationFrame:Show(); + GlueDialog:Hide() + AccountLoginUI:Hide() + SurveyNotificationAccept:Enable() + SurveyNotificationDecline:Enable() + SurveyNotificationFrame:Show() end function AccountLogin_SurveyNotificationDone(accepted) - SurveyNotificationFrame:Hide(); - SurveyNotificationAccept:Disable(); - SurveyNotificationDecline:Disable(); - SurveyNotificationDone(accepted); - AccountLoginUI:Show(); + SurveyNotificationFrame:Hide() + SurveyNotificationAccept:Disable() + SurveyNotificationDecline:Disable() + SurveyNotificationDone(accepted) + AccountLoginUI:Show() end function AccountLogin_ShowUserAgreements() - TOSScrollFrame:Hide(); - EULAScrollFrame:Hide(); - TerminationScrollFrame:Hide(); - ScanningScrollFrame:Hide(); - ContestScrollFrame:Hide(); - TOSText:Hide(); - EULAText:Hide(); - TerminationText:Hide(); - ScanningText:Hide(); - if ( not EULAAccepted() ) then - if ( ShowEULANotice() ) then - TOSNotice:SetText(EULA_NOTICE); - TOSNotice:Show(); - end - AccountLoginUI:Hide(); - TOSFrame.noticeType = "EULA"; - TOSFrameTitle:SetText(EULA_FRAME_TITLE); - TOSFrameHeader:SetWidth(TOSFrameTitle:GetWidth()); - EULAScrollFrame:Show(); - EULAText:Show(); - TOSFrame:Show(); - elseif ( not TOSAccepted() ) then - if ( ShowTOSNotice() ) then - TOSNotice:SetText(TOS_NOTICE); - TOSNotice:Show(); - end - AccountLoginUI:Hide(); - TOSFrame.noticeType = "TOS"; - TOSFrameTitle:SetText(TOS_FRAME_TITLE); - TOSFrameHeader:SetWidth(TOSFrameTitle:GetWidth()); - TOSScrollFrame:Show(); - TOSText:Show(); - TOSFrame:Show(); - elseif ( not TerminationWithoutNoticeAccepted() and SHOW_TERMINATION_WITHOUT_NOTICE_AGREEMENT ) then - if ( ShowTerminationWithoutNoticeNotice() ) then - TOSNotice:SetText(TERMINATION_WITHOUT_NOTICE_NOTICE); - TOSNotice:Show(); - end - AccountLoginUI:Hide(); - TOSFrame.noticeType = "TERMINATION"; - TOSFrameTitle:SetText(TERMINATION_WITHOUT_NOTICE_FRAME_TITLE); - TOSFrameHeader:SetWidth(TOSFrameTitle:GetWidth()); - TerminationScrollFrame:Show(); - TerminationText:Show(); - TOSFrame:Show(); - elseif ( not ScanningAccepted() and SHOW_SCANNING_AGREEMENT ) then - if ( ShowScanningNotice() ) then - TOSNotice:SetText(SCANNING_NOTICE); - TOSNotice:Show(); - end - AccountLoginUI:Hide(); - TOSFrame.noticeType = "SCAN"; - TOSFrameTitle:SetText(SCAN_FRAME_TITLE); - TOSFrameHeader:SetWidth(TOSFrameTitle:GetWidth()); - ScanningScrollFrame:Show(); - ScanningText:Show(); - TOSFrame:Show(); - elseif ( not ContestAccepted() and SHOW_CONTEST_AGREEMENT ) then - if ( ShowContestNotice() ) then - TOSNotice:SetText(CONTEST_NOTICE); - TOSNotice:Show(); - end - AccountLoginUI:Hide(); - TOSFrame.noticeType = "CONTEST"; - TOSFrameTitle:SetText(CONTEST_FRAME_TITLE); - TOSFrameHeader:SetWidth(TOSFrameTitle:GetWidth()); - ContestScrollFrame:Show(); - ContestText:Show(); - TOSFrame:Show(); - elseif ( not IsScanDLLFinished() ) then - AccountLoginUI:Hide(); - TOSFrame:Hide(); - local dllURL = ""; - if ( IsWindowsClient() ) then dllURL = SCANDLL_URL_WIN32_SCAN_DLL; end - ScanDLLStart(SCANDLL_URL_LAUNCHER_TXT, dllURL); - else - AccountLoginUI:Show(); - TOSFrame:Hide(); - end + TOSScrollFrame:Hide() + EULAScrollFrame:Hide() + TerminationScrollFrame:Hide() + ScanningScrollFrame:Hide() + ContestScrollFrame:Hide() + TOSText:Hide() + EULAText:Hide() + TerminationText:Hide() + ScanningText:Hide() + + if not EULAAccepted() then + if ShowEULANotice() then + TOSNotice:SetText(EULA_NOTICE) + TOSNotice:Show() + end + AccountLoginUI:Hide() + TOSFrame.noticeType = "EULA" + TOSFrameTitle:SetText(EULA_FRAME_TITLE) + TOSFrameHeader:SetWidth(TOSFrameTitle:GetWidth()) + EULAScrollFrame:Show() + EULAText:Show() + TOSFrame:Show() + elseif not TOSAccepted() then + if ShowTOSNotice() then + TOSNotice:SetText(TOS_NOTICE) + TOSNotice:Show() + end + AccountLoginUI:Hide() + TOSFrame.noticeType = "TOS" + TOSFrameTitle:SetText(TOS_FRAME_TITLE) + TOSFrameHeader:SetWidth(TOSFrameTitle:GetWidth()) + TOSScrollFrame:Show() + TOSText:Show() + TOSFrame:Show() + elseif not IsScanDLLFinished() then + AccountLoginUI:Hide() + TOSFrame:Hide() + local dllURL = "" + if IsWindowsClient() then + dllURL = SCANDLL_URL_WIN32_SCAN_DLL + end + ScanDLLStart(SCANDLL_URL_LAUNCHER_TXT, dllURL) + else + AccountLoginUI:Show() + TOSFrame:Hide() + end end function AccountLogin_UpdateAcceptButton(scrollFrame, isAcceptedFunc, noticeType) - local scrollbar = _G[scrollFrame:GetName().."ScrollBar"]; - local min, max = scrollbar:GetMinMaxValues(); - - -- HACK: scrollbars do not handle max properly - -- DO NOT CHANGE - without speaking to Mikros/Barris/Thompson - if (scrollbar:GetValue() >= max - 20) then - TOSAccept:Enable(); - else - if ( not isAcceptedFunc() and TOSFrame.noticeType == noticeType ) then - TOSAccept:Disable(); - end - end -end - -function ChangedOptionsDialog_OnShow(self) - if ( not ShowChangedOptionWarnings() ) then - self:Hide(); - return; - end - - local options = ChangedOptionsDialog_BuildWarningsString(GetChangedOptionWarnings()); - if ( options == "" ) then - self:Hide(); - return; - end - - -- set text - ChangedOptionsDialogText:SetText(options); - - -- resize the background to fit the text - local textHeight = ChangedOptionsDialogText:GetHeight(); - local titleHeight = ChangedOptionsDialogTitle:GetHeight(); - local buttonHeight = ChangedOptionsDialogOkayButton:GetHeight(); - ChangedOptionsDialogBackground:SetHeight(26 + titleHeight + 16 + textHeight + 8 + buttonHeight + 16); - self:Raise(); + local scrollbar = _G[scrollFrame:GetName().."ScrollBar"] + local min, max = scrollbar:GetMinMaxValues() + + if scrollbar:GetValue() >= max - Config.SCROLL_THRESHOLD then + UICache.tosAccept:Enable() + else + if not isAcceptedFunc() and UICache.tosFrame.noticeType == noticeType then + UICache.tosAccept:Disable() + end + end end - -function ChangedOptionsDialog_OnKeyDown(self,key) - if ( key == "PRINTSCREEN" ) then - Screenshot(); - return; - end - - if ( key == "ESCAPE" or key == "ENTER" ) then - ChangedOptionsDialogOkayButton:Click(); - end -end - -function ChangedOptionsDialog_BuildWarningsString(...) - local options = ""; - for i=1, select("#", ...) do - if ( i == 1 ) then - options = select(1, ...); - else - options = options.."\n\n"..select(i, ...); - end - end - return options; -end - --- Virtual keypad functions -function VirtualKeypadFrame_OnEvent(event, ...) - if ( event == "PLAYER_ENTER_PIN" ) then - for i=1, 10 do - _G["VirtualKeypadButton"..i]:SetText(select(i,...)); - end - end - -- Randomize location to prevent hacking (yeah right) - local xPadding = 5; - local yPadding = 10; - local xPos = random(xPadding, GlueParent:GetWidth()-VirtualKeypadFrame:GetWidth()-xPadding); - local yPos = random(yPadding, GlueParent:GetHeight()-VirtualKeypadFrame:GetHeight()-yPadding); - VirtualKeypadFrame:SetPoint("TOPLEFT", GlueParent, "TOPLEFT", xPos, -yPos); - - VirtualKeypadFrame:Show(); - VirtualKeypad_UpdateButtons(); -end - -function VirtualKeypadButton_OnClick(self) - local text = VirtualKeypadText:GetText(); - if ( not text ) then - text = ""; - end - VirtualKeypadText:SetText(text.."*"); - VirtualKeypadFrame.PIN = VirtualKeypadFrame.PIN..self:GetID(); - VirtualKeypad_UpdateButtons(); -end - -function VirtualKeypadOkayButton_OnClick() - local PIN = VirtualKeypadFrame.PIN; - local numNumbers = strlen(PIN); - local pinNumber = {}; - for i=1, MAX_PIN_LENGTH do - if ( i <= numNumbers ) then - pinNumber[i] = strsub(PIN,i,i); - else - pinNumber[i] = nil; - end - end - PINEntered(pinNumber[1] , pinNumber[2], pinNumber[3], pinNumber[4], pinNumber[5], pinNumber[6], pinNumber[7], pinNumber[8], pinNumber[9], pinNumber[10]); - VirtualKeypadFrame:Hide(); -end - -function VirtualKeypad_UpdateButtons() - local numNumbers = strlen(VirtualKeypadFrame.PIN); - if ( numNumbers >= 4 and numNumbers <= MAX_PIN_LENGTH ) then - VirtualKeypadOkayButton:Enable(); - else - VirtualKeypadOkayButton:Disable(); - end - if ( numNumbers == 0 ) then - VirtualKeypadBackButton:Disable(); - else - VirtualKeypadBackButton:Enable(); - end - if ( numNumbers >= MAX_PIN_LENGTH ) then - for i=1, MAX_PIN_LENGTH do - _G["VirtualKeypadButton"..i]:Disable(); - end - else - for i=1, MAX_PIN_LENGTH do - _G["VirtualKeypadButton"..i]:Enable(); - end - end -end - -TOKEN_SEED = - "idobdfillpkiimdgkclhnlibgnepalcbpccdkhloipdoeebccnoeedefgmljndai".. - "epicgamehpoifjbggbcihfanenmhkemffilglaebddmbakkhblpencadlaiepoga".. - "ecpjojaijcefflabhilmmpgjiecbhamoceponkbjiogaodhnagencenlaeljhbna".. - "ciglpffdnfgaaidccjjgbgiihhnbbjcbanhfdjadljkhmfknfnmpjblnelbfnnjf".. - "dpakjehajomgjahhljnmnhnpadfkbopppiicnkkkhblkbibgajfmemhhimpjgcoe".. - "mbkpilkleedkmpnckkcdbhnoanhpjeneinehgknalgglcbdcjdcppbjhgkahamgk".. - "gijkofghdhopbkjjghmndfdpiadcdigefikbgccfhgkkbmkollbhlkbdobhaofbh".. - "adbiepfnpiibfkcpflpkjpfmmhbopkcbcblaadaoodnoodgfhjpedmpballngmoo".. - "bbmkgghdgmhdngbfpmikijmdjgddkeahhidkofihemfmolbcojpiapfkogbdenfc".. - "cmahmfhlclfkeijbndcllbnffbjbbkfgdboiffhpkfgjckliookjlonenifdbenn".. - "epeicoloceldnilhlkameoeceiobfnpeccaihhgjdgagjhmeljacpfljlhgnlhkj".. - "dbihegomcbifklmmhmbaodnaehnbkikcjkloebkhmkhejakcdklndeiinidlgdhc".. - "ddfbafimcpddekndmbcfemcpfihngpkoccjniboomialmgejaalnfogjofbfgbdk".. - "poibhankhndpgeldkkdjgbknnahfdbcjhkmaciajeadkfmjcgaipjcilhhlagjcp".. - "lnbeodabfpofdabnhckmnbjnofopfhglgiociaehalfcclkmjmobmjdbillmompm".. - "jfgppnfgfancjglolkhoejogfjljnknoeiniiiimcifhlpiefmkkmhonbnppdndl".. - "hmgpgcniinbaanciifdggklbgoanaihndbjpnannabbmfjkdjfkhimpccelcpjed".. - "kgmpmpfnbmleiejkgbbknnnhambkmomlbjbhpkegehdfacdnbdfcmfagadbcaemg".. - "ddhpjoacekfnakamgafmkodcplnhbhblcllikeglfnedlmkcoiegldlhikoncmca".. - "bloiejelafbjjgmhapobofongodoojelpnkgfjdgpfckjglfbgaipbdpmbpjlcje".. - "jcpgagffnmappkacgacmokedaicjklinmemijkojchoojjandkcdmjigjeldpepl".. - "ihpenljefeechdndbdjkcipajcajghnhjackcjnoofebnmhimajekangghkfgcjm".. - "hndedmcpmdilipgljglplhppcogaidkfaeibkedaihckjodddfblfonfnnljgcbi".. - "hmnojjolaljebgiegnmjcficnkjchoakajkdhnchbljhonghjffebdobdcahpdjp".. - "bmhpmnamkgpfjfbfgghjnabakoilmlbkhjoiegldbcdlijakkmehoemokdeafgjl".. - "khmdjmbkdckdlidapcigbomjikehjddpblijhdgooegdfeinhaiponemlnffcnif".. - "bkbnihminfmkfhbdneaaegofpacckahbgnmobgehalklcfkncogkanff"; - --- TOKEN SYSTEM -function TokenEntryOkayButton_OnLoad(self) - self:RegisterEvent("PLAYER_ENTER_TOKEN"); -end - -function TokenEntryOkayButton_OnEvent(self, event) - if (event == "PLAYER_ENTER_TOKEN") then - if ( AccountLoginSaveAccountName:GetChecked() ) then - if ( GetUsesToken() ) then - if ( AccountLoginTokenEdit:GetText() ~= "" ) then - TokenEntered(AccountLoginTokenEdit:GetText()); - return; - end - else - SetUsesToken(true); - end - end - self:Show(); - end -end - -function TokenEntryOkayButton_OnShow() - TokenEnterDialogBackgroundEdit:SetText(""); - TokenEnterDialogBackgroundEdit:SetFocus(); -end - -function TokenEntryOkayButton_OnKeyDown(self, key) - if ( key == "ENTER" ) then - TokenEntry_Okay(self); - elseif ( key == "ESCAPE" ) then - TokenEntry_Cancel(self); - end -end - -function TokenEntry_Okay(self) - TokenEntered(TokenEnterDialogBackgroundEdit:GetText()); - TokenEnterDialog:Hide(); -end - -function TokenEntry_Cancel(self) - TokenEnterDialog:Hide(); - CancelLogin(); -end - --- WOW Account selection -function WoWAccountSelect_OnLoad(self) - self:RegisterEvent("GAME_ACCOUNTS_UPDATED"); - self:RegisterEvent("OPEN_STATUS_DIALOG"); - WoWAccountSelectDialogBackgroundContainerScrollFrame.offset = 0 - CURRENT_SELECTED_WOW_ACCOUNT = 1; -end - -function WoWAccountSelect_OnShow (self) - AccountLoginAccountEdit:SetFocus(); - AccountLoginAccountEdit:ClearFocus(); - CURRENT_SELECTED_WOW_ACCOUNT = 1; - WoWAccountSelect_Update(); -end - -function WoWAccountSelectButton_OnClick(self) - CURRENT_SELECTED_WOW_ACCOUNT = self:GetID(); - WoWAccountSelect_Update(); -end - -function WoWAccountSelectButton_OnDoubleClick(self) - WoWAccountSelect_SelectAccount(self:GetID()); -end - -function WoWAccountSelect_OnEvent(self, event) - if ( event == "GAME_ACCOUNTS_UPDATED" ) then - local str, selectedIndex, selectedName = "" - for i = 1, GetNumGameAccounts() do - local name = GetGameAccountInfo(i); - if ( name == GlueDropDownMenu_GetText(AccountLoginDropDown) ) then - selectedName = name; - selectedIndex = i; - end - str = str .. name .. "|"; - end - - if ( str == strreplace(GetSavedAccountList(), "!", "") and selectedIndex ) then - WoWAccountSelect_SelectAccount(selectedIndex); - return; - else - self:Show(); - end - else - self:Hide(); - end -end - -function WoWAccountSelect_SelectAccount(index) - if ( AccountLoginSaveAccountName:GetChecked() ) then - WowAccountSelect_UpdateSavedAccountNames(index); - else - SetSavedAccountList(""); - end - WoWAccountSelectDialog:Hide(); - SetGameAccount(index); -end - -function WowAccountSelect_UpdateSavedAccountNames(selectedIndex) - local count = GetNumGameAccounts(); - - local str = "" - for i = 1, count do - local name = GetGameAccountInfo(i); - if ( i == selectedIndex ) then - str = str .. "!" .. name .. "|"; - else - str = str .. name .. "|"; - end - end - SetSavedAccountList(str); -end - -ACCOUNTNAME_BUTTON_HEIGHT = 20; - -function WoWAccountSelect_OnVerticalScroll (self, offset) - local scrollbar = _G[self:GetName().."ScrollBar"]; - scrollbar:SetValue(offset); - WoWAccountSelectDialogBackgroundContainerScrollFrame.offset = floor((offset / ACCOUNTNAME_BUTTON_HEIGHT) + 0.5); - WoWAccountSelect_Update(); -end - -MAX_ACCOUNTS_DISPLAYED = 8; -function WoWAccountSelect_Update() - local count = GetNumGameAccounts(); - - local offset = WoWAccountSelectDialogBackgroundContainerScrollFrame.offset; - for index=1, MAX_ACCOUNTS_DISPLAYED do - local button = _G["WoWAccountSelectDialogBackgroundContainerButton" .. index]; - local name, regionID = GetGameAccountInfo(index + offset); - button:SetButtonState("NORMAL"); - button.BG_Highlight:Hide(); - if ( name ) then - button:SetID(index + offset); - button:SetText(name); - button.regionID = regionID; - button:Show(); - if ( index == CURRENT_SELECTED_WOW_ACCOUNT) then - button.BG_Highlight:Show(); - end - else - button:Hide(); - end - end - - GlueScrollFrame_Update(WoWAccountSelectDialogBackgroundContainerScrollFrame, count, MAX_ACCOUNTS_DISPLAYED, ACCOUNTNAME_BUTTON_HEIGHT); -end - -function WoWAccountSelect_AccountButton_OnClick(self, button) - CURRENT_SELECTED_WOW_ACCOUNT = self:GetID(); - WoWAccountSelect_Accept(); -end - -function WoWAccountSelect_OnKeyDown(self, key) - if ( key == "ESCAPE" ) then - WoWAccountSelect_OnCancel(self); - elseif ( key == "UP" ) then - CURRENT_SELECTED_WOW_ACCOUNT = max(1, CURRENT_SELECTED_WOW_ACCOUNT - 1); - WoWAccountSelect_Update() - elseif ( key == "DOWN" ) then - CURRENT_SELECTED_WOW_ACCOUNT = min(GetNumGameAccounts(), CURRENT_SELECTED_WOW_ACCOUNT + 1); - WoWAccountSelect_Update() - elseif ( key == "ENTER" ) then - WoWAccountSelect_SelectAccount(CURRENT_SELECTED_WOW_ACCOUNT); - elseif ( key == "PRINTSCREEN" ) then - Screenshot(); - end -end - -function WoWAccountSelect_OnCancel (self) - self:Hide(); - GlueDialog:Hide(); - CancelLogin(); -end - -function WoWAccountSelect_Accept() - WoWAccountSelect_SelectAccount(CURRENT_SELECTED_WOW_ACCOUNT); -end - -function AccountLoginDropDown_OnClick(self) - GlueDropDownMenu_SetSelectedValue(AccountLoginDropDown, self.value); -end - -function AccountLoginDropDown_Initialize() - local selectedValue = GlueDropDownMenu_GetSelectedValue(AccountLoginDropDown); - local info; - - for i = 1, #AccountList do - AccountList[i].checked = (AccountList[i].text == selectedValue); - GlueDropDownMenu_AddButton(AccountList[i]); - end -end - -AccountList = {}; -function AccountLogin_SetupAccountListDDL() - if ( GetSavedAccountName() ~= "" and GetSavedAccountList() ~= "" ) then - AccountLoginPasswordEdit:SetPoint("BOTTOM", 0, 255); - AccountLoginLoginButton:SetPoint("BOTTOM", 0, 150); - AccountLoginDropDown:Show(); - else - AccountLoginPasswordEdit:SetPoint("BOTTOM", 0, 275); - AccountLoginLoginButton:SetPoint("BOTTOM", 0, 170); - AccountLoginDropDown:Hide(); - return; - end - - AccountList = {}; - local i = 1; - for str in string.gmatch(GetSavedAccountList(), "([%w!]+)|?") do - local selected = false; - if ( strsub(str, 1, 1) == "!" ) then - selected = true; - str = strsub(str, 2, #str); - GlueDropDownMenu_SetSelectedName(AccountLoginDropDown, str); - GlueDropDownMenu_SetText(str, AccountLoginDropDown); - end - AccountList[i] = { ["text"] = str, ["value"] = str, ["selected"] = selected, func = AccountLoginDropDown_OnClick }; - i = i + 1; - end -end - +-- ============================================================================ +-- FUNCIONES DE CINEMATICS +-- ============================================================================ function CinematicsFrame_OnLoad(self) - local numMovies = GetClientExpansionLevel(); - CinematicsFrame.numMovies = numMovies; - if ( numMovies < 2 ) then - return; - end - - for i = 1, numMovies do - _G["CinematicsButton"..i]:Show(); - end - CinematicsBackground:SetHeight(numMovies * 40 + 70); + local numMovies = GetClientExpansionLevel() + CinematicsFrame.numMovies = numMovies + if numMovies < 2 then + return + end + + for i = 1, numMovies do + _G["CinematicsButton"..i]:Show() + end + CinematicsBackground:SetHeight(numMovies * 40 + 70) end function CinematicsFrame_OnKeyDown(key) - if ( key == "PRINTSCREEN" ) then - Screenshot(); - else - PlaySound("igMainMenuOptionCheckBoxOff"); - CinematicsFrame:Hide(); - end + if key == "PRINTSCREEN" then + Screenshot() + else + PlaySound("igMainMenuOptionCheckBoxOff") + CinematicsFrame:Hide() + end end function Cinematics_PlayMovie(self) - CinematicsFrame:Hide(); - PlaySound("gsTitleOptionOK"); - MovieFrame.version = self:GetID(); - SetGlueScreen("movie"); -end \ No newline at end of file + CinematicsFrame:Hide() + PlaySound("gsTitleOptionOK") + MovieFrame.version = self:GetID() + SetGlueScreen("movie") +end +-- ============================================================================ +-- FUNCIONES AUXILIARES +-- ============================================================================ +function string_explode(str, div) + assert(type(str) == "string" and type(div) == "string", "invalid arguments") + local o = {} + while true do + local pos1, pos2 = str:find(div, 1, true) + if not pos1 then + o[#o+1] = str + break + end + o[#o+1], str = str:sub(1, pos1-1), str:sub(pos2+1) + end + return o +end +-- ============================================================================ +-- TOKEN SYSTEM - FUNCIONES SIMPLES +-- ============================================================================ +function TokenEnterDialog_Okay(self) + local editBox = TokenEnterDialogBackgroundEdit + if not editBox then return end + + local text = editBox:GetText() + if not text or string.len(text) < 6 then return end + + TokenEntered(text) + TokenEnterDialog:Hide() +end + +function TokenEnterDialog_Cancel(self) + if TokenEnterDialog then + TokenEnterDialog:Hide() + end + CancelLogin() +end + +function TokenEntry_Okay(self) + TokenEnterDialog_Okay(self) +end + +function TokenEntry_Cancel(self) + TokenEnterDialog_Cancel(self) +end + +function TokenEntryOkayButton_OnLoad(self) + self:RegisterEvent("PLAYER_ENTER_TOKEN") +end + +function TokenEntryOkayButton_OnEvent(self, event) + if event == "PLAYER_ENTER_TOKEN" then + if AccountLoginSaveAccountName:GetChecked() then + if GetUsesToken() then + if AccountLoginTokenEdit:GetText() ~= "" then + TokenEntered(AccountLoginTokenEdit:GetText()) + return + end + else + SetUsesToken(true) + end + end + self:Show() + end +end + +function TokenEntryOkayButton_OnShow() + if TokenEnterDialogBackgroundEdit then + TokenEnterDialogBackgroundEdit:SetText("") + TokenEnterDialogBackgroundEdit:SetFocus() + end +end + +function TokenEntryOkayButton_OnKeyDown(self, key) + if key == "ENTER" then + TokenEntry_Okay(self) + elseif key == "ESCAPE" then + TokenEntry_Cancel(self) + end +end +-- ============================================================================ diff --git a/src/Data/ruRU/patch-ruRU-4/Interface/GlueXML/AccountLogin.xml b/src/Data/ruRU/patch-ruRU-4/Interface/GlueXML/AccountLogin.xml index 9a63648..9c86b56 100644 --- a/src/Data/ruRU/patch-ruRU-4/Interface/GlueXML/AccountLogin.xml +++ b/src/Data/ruRU/patch-ruRU-4/Interface/GlueXML/AccountLogin.xml @@ -1,175 +1,128 @@ - -