Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
191c1047c1 | ||
|
|
437a4ef561 | ||
|
|
8b7aa45813 | ||
|
|
e504f88167 | ||
|
|
13d77d77c9 |
+107
-46
@@ -249,7 +249,6 @@ function Autologin_PrevPage()
|
|||||||
Autologin_UpdateUI();
|
Autologin_UpdateUI();
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
FADE_IN_TIME = 2;
|
FADE_IN_TIME = 2;
|
||||||
DEFAULT_TOOLTIP_COLOR = {0.8, 0.8, 0.8, 0.09, 0.09, 0.09};
|
DEFAULT_TOOLTIP_COLOR = {0.8, 0.8, 0.8, 0.09, 0.09, 0.09};
|
||||||
MAX_PIN_LENGTH = 10;
|
MAX_PIN_LENGTH = 10;
|
||||||
@@ -258,11 +257,13 @@ function AccountLogin_OnLoad()
|
|||||||
this:SetSequence(0);
|
this:SetSequence(0);
|
||||||
this:SetCamera(0);
|
this:SetCamera(0);
|
||||||
|
|
||||||
|
TOSFrame.noticeType = "EULA";
|
||||||
|
|
||||||
this:RegisterEvent("SHOW_SERVER_ALERT");
|
this:RegisterEvent("SHOW_SERVER_ALERT");
|
||||||
this:RegisterEvent("SHOW_SURVEY_NOTIFICATION");
|
this:RegisterEvent("SHOW_SURVEY_NOTIFICATION");
|
||||||
|
|
||||||
local versionType, buildType, version, internalVersion, date = GetBuildInfo();
|
local versionType, buildType, version, internalVersion, date = GetBuildInfo();
|
||||||
AccountLoginVersion:SetText(format(VERSION_TEMPLATE, versionType, version, internalVersion, buildType, date));
|
AccountLoginVersion:SetText(format(TEXT(VERSION_TEMPLATE), versionType, version, internalVersion, buildType, date));
|
||||||
|
|
||||||
-- Color edit box backdrops
|
-- Color edit box backdrops
|
||||||
local backdropColor = DEFAULT_TOOLTIP_COLOR;
|
local backdropColor = DEFAULT_TOOLTIP_COLOR;
|
||||||
@@ -270,15 +271,14 @@ function AccountLogin_OnLoad()
|
|||||||
AccountLoginAccountEdit:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6]);
|
AccountLoginAccountEdit:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6]);
|
||||||
AccountLoginPasswordEdit:SetBackdropBorderColor(backdropColor[1], backdropColor[2], backdropColor[3]);
|
AccountLoginPasswordEdit:SetBackdropBorderColor(backdropColor[1], backdropColor[2], backdropColor[3]);
|
||||||
AccountLoginPasswordEdit:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6]);
|
AccountLoginPasswordEdit:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6]);
|
||||||
VirtualKeypadText:SetBackdropBorderColor(backdropColor[1], backdropColor[2], backdropColor[3]);
|
|
||||||
VirtualKeypadText:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6]);
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function AccountLogin_OnShow()
|
function AccountLogin_OnShow()
|
||||||
CurrentGlueMusic = "Sound\\Music\\GlueScreenMusic\\wow_main_theme.mp3";
|
CurrentGlueMusic = "Sound\\Music\\GlueScreenMusic\\wow_main_theme.mp3";
|
||||||
|
|
||||||
AcceptTOS();
|
-- Try to show the EULA or the TOS
|
||||||
AcceptEULA();
|
-- AccountLogin_ShowUserAgreements();
|
||||||
|
|
||||||
local serverName = GetServerName();
|
local serverName = GetServerName();
|
||||||
if(serverName) then
|
if(serverName) then
|
||||||
AccountLoginRealmName:SetText(serverName);
|
AccountLoginRealmName:SetText(serverName);
|
||||||
@@ -286,6 +286,9 @@ function AccountLogin_OnShow()
|
|||||||
AccountLoginRealmName:Hide()
|
AccountLoginRealmName:Hide()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Autologin OnShow. Load sets `Autologin_SelectedIdx` from the
|
||||||
|
-- last-used account name (via GetSavedAccountName), so honor that
|
||||||
|
-- here instead of unconditionally picking row 1.
|
||||||
Autologin_Load();
|
Autologin_Load();
|
||||||
Autologin_PasswordFieldForced = false;
|
Autologin_PasswordFieldForced = false;
|
||||||
if ( table.getn(Autologin_Table) ~= 0 ) then
|
if ( table.getn(Autologin_Table) ~= 0 ) then
|
||||||
@@ -304,6 +307,9 @@ function AccountLogin_OnShow()
|
|||||||
elseif ( AccountLoginPasswordEdit:IsVisible() ) then
|
elseif ( AccountLoginPasswordEdit:IsVisible() ) then
|
||||||
AccountLogin_FocusPassword();
|
AccountLogin_FocusPassword();
|
||||||
end
|
end
|
||||||
|
-- If the password field is hidden (saved-account autologin), don't
|
||||||
|
-- grab focus — Enter will still trigger Login via the parent frame's
|
||||||
|
-- OnKeyDown handler, and the user can click the name field to edit.
|
||||||
end
|
end
|
||||||
|
|
||||||
function AccountLogin_FocusPassword()
|
function AccountLogin_FocusPassword()
|
||||||
@@ -327,7 +333,7 @@ function AccountLogin_OnKeyDown()
|
|||||||
else
|
else
|
||||||
AccountLogin_Exit();
|
AccountLogin_Exit();
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif ( arg1 == "ENTER" ) then
|
elseif ( arg1 == "ENTER" ) then
|
||||||
if ( not TOSAccepted() ) then
|
if ( not TOSAccepted() ) then
|
||||||
return;
|
return;
|
||||||
@@ -357,34 +363,14 @@ function AccountLogin_Login()
|
|||||||
Autologin_OnLogin();
|
Autologin_OnLogin();
|
||||||
end
|
end
|
||||||
|
|
||||||
function AccountLogin_Turtle_Armory_Website()
|
function AccountLogin_ManageAccount()
|
||||||
PlaySound("gsLoginNewAccount");
|
PlaySound("gsLoginNewAccount");
|
||||||
LaunchURL(TURTLE_ARMORY_WEBSITE);
|
LaunchURL(AUTH_NO_TIME_URL);
|
||||||
end
|
end
|
||||||
|
|
||||||
function AccountLogin_Turtle_Website()
|
function AccountLogin_LaunchCommunitySite()
|
||||||
PlaySound("gsLoginNewAccount");
|
PlaySound("gsLoginNewAccount");
|
||||||
LaunchURL(AUTH_TURTLE_WEBSITE);
|
LaunchURL(COMMUNITY_URL);
|
||||||
end
|
|
||||||
|
|
||||||
function AccountLogin_Turtle_Knowledge_Database()
|
|
||||||
PlaySound("gsLoginNewAccount");
|
|
||||||
LaunchURL(TURTLE_KNOWLEDGE_DATABASE_WEBSITE);
|
|
||||||
end
|
|
||||||
|
|
||||||
function AccountLogin_Turtle_Community_Forum()
|
|
||||||
PlaySound("gsLoginNewAccount");
|
|
||||||
LaunchURL(TURTLE_COMMUNITY_FORUM_WEBSITE);
|
|
||||||
end
|
|
||||||
|
|
||||||
function AccountLogin_Turtle_Discord()
|
|
||||||
PlaySound("gsLoginNewAccount");
|
|
||||||
LaunchURL(TURTLE_DISCORD_WEBSITE);
|
|
||||||
end
|
|
||||||
|
|
||||||
function AccountLogin_Turtle_Reddit()
|
|
||||||
PlaySound("gsLoginNewAccount");
|
|
||||||
LaunchURL(TURTLE_REDDIT_WEBSITE);
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function AccountLogin_Credits()
|
function AccountLogin_Credits()
|
||||||
@@ -426,12 +412,73 @@ function AccountLogin_SurveyNotificationDone(accepted)
|
|||||||
AccountLoginUI:Show();
|
AccountLoginUI:Show();
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function AccountLogin_ShowUserAgreements()
|
||||||
|
TOSScrollFrame:Hide();
|
||||||
|
EULAScrollFrame:Hide();
|
||||||
|
ScanningScrollFrame:Hide();
|
||||||
|
ContestScrollFrame:Hide();
|
||||||
|
TOSText:Hide();
|
||||||
|
EULAText: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() + 310);
|
||||||
|
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() + 310);
|
||||||
|
TOSScrollFrame:Show();
|
||||||
|
TOSText: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() + 310);
|
||||||
|
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() + 310);
|
||||||
|
ContestScrollFrame:Show();
|
||||||
|
ContestText:Show();
|
||||||
|
TOSFrame:Show();
|
||||||
|
else
|
||||||
|
AccountLoginUI:Show();
|
||||||
|
TOSFrame:Hide();
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Virtual keypad functions
|
-- Virtual keypad functions
|
||||||
local buttonText = {}
|
|
||||||
function VirtualKeypadFrame_OnEvent(event)
|
function VirtualKeypadFrame_OnEvent(event)
|
||||||
if ( event == "PLAYER_ENTER_PIN" ) then
|
if ( event == "PLAYER_ENTER_PIN" ) then
|
||||||
for i=1, 10 do
|
for i=1, 10 do
|
||||||
buttonText[i] = _G["arg"..i]
|
getglobal("VirtualKeypadButton"..i):SetText(getglobal("arg"..i));
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Randomize location to prevent hacking (yeah right)
|
-- Randomize location to prevent hacking (yeah right)
|
||||||
@@ -439,8 +486,8 @@ function VirtualKeypadFrame_OnEvent(event)
|
|||||||
local yPadding = 10;
|
local yPadding = 10;
|
||||||
local xPos = random(xPadding, GlueParent:GetWidth()-VirtualKeypadFrame:GetWidth()-xPadding);
|
local xPos = random(xPadding, GlueParent:GetWidth()-VirtualKeypadFrame:GetWidth()-xPadding);
|
||||||
local yPos = random(yPadding, GlueParent:GetHeight()-VirtualKeypadFrame:GetHeight()-yPadding);
|
local yPos = random(yPadding, GlueParent:GetHeight()-VirtualKeypadFrame:GetHeight()-yPadding);
|
||||||
--VirtualKeypadFrame:SetPoint("TOPLEFT", GlueParent, "TOPLEFT", xPos, -yPos);
|
VirtualKeypadFrame:SetPoint("TOPLEFT", GlueParent, "TOPLEFT", xPos, -yPos);
|
||||||
|
|
||||||
VirtualKeypadFrame:Show();
|
VirtualKeypadFrame:Show();
|
||||||
VirtualKeypad_UpdateButtons();
|
VirtualKeypad_UpdateButtons();
|
||||||
end
|
end
|
||||||
@@ -450,31 +497,45 @@ function VirtualKeypadButton_OnClick()
|
|||||||
if ( not text ) then
|
if ( not text ) then
|
||||||
text = "";
|
text = "";
|
||||||
end
|
end
|
||||||
|
VirtualKeypadText:SetText(text.."*");
|
||||||
VirtualKeypadFrame.PIN = VirtualKeypadFrame.PIN..this:GetID();
|
VirtualKeypadFrame.PIN = VirtualKeypadFrame.PIN..this:GetID();
|
||||||
VirtualKeypadText:SetText(VirtualKeypadFrame.PIN);
|
|
||||||
VirtualKeypad_UpdateButtons();
|
VirtualKeypad_UpdateButtons();
|
||||||
end
|
end
|
||||||
|
|
||||||
function VirtualKeypadOkayButton_OnClick()
|
function VirtualKeypadOkayButton_OnClick()
|
||||||
local PIN = VirtualKeypadText:GetText();
|
local PIN = VirtualKeypadFrame.PIN;
|
||||||
local numNumbers = strlen(PIN);
|
local numNumbers = strlen(PIN);
|
||||||
if numNumbers < 6 then return end
|
|
||||||
local pinNumber = {};
|
local pinNumber = {};
|
||||||
for i=1, MAX_PIN_LENGTH do
|
for i=1, MAX_PIN_LENGTH do
|
||||||
if ( i <= numNumbers ) then
|
if ( i <= numNumbers ) then
|
||||||
pinNumber[i] = nil;
|
pinNumber[i] = strsub(PIN,i,i);
|
||||||
for j=1, 10 do
|
|
||||||
if tonumber(buttonText[j]) == tonumber(strsub(PIN,i,i)) then
|
|
||||||
pinNumber[i] = j-1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
pinNumber[i] = nil;
|
pinNumber[i] = nil;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
PINEntered(pinNumber[1], pinNumber[2], pinNumber[3], pinNumber[4], pinNumber[5], pinNumber[6], pinNumber[7], pinNumber[8], pinNumber[9], pinNumber[10]);
|
PINEntered(pinNumber[1] , pinNumber[2], pinNumber[3], pinNumber[4], pinNumber[5], pinNumber[6], pinNumber[7], pinNumber[8], pinNumber[9], pinNumber[10]);
|
||||||
VirtualKeypadFrame:Hide();
|
VirtualKeypadFrame:Hide();
|
||||||
end
|
end
|
||||||
|
|
||||||
function VirtualKeypad_UpdateButtons()
|
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
|
||||||
|
getglobal("VirtualKeypadButton"..i):Disable();
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for i=1, MAX_PIN_LENGTH do
|
||||||
|
getglobal("VirtualKeypadButton"..i):Enable();
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+793
-105
File diff suppressed because it is too large
Load Diff
+59
-44
@@ -8,6 +8,21 @@ MAX_CHARACTERS_PER_REALM = 10;
|
|||||||
|
|
||||||
AUTO_DRAG_TIME = 0.5;
|
AUTO_DRAG_TIME = 0.5;
|
||||||
|
|
||||||
|
-- Per-account character autoselect was removed alongside the plaintext
|
||||||
|
-- credential store; the AutologinSaveCharacterButton checkbox in
|
||||||
|
-- CharacterSelect.xml is now permanently hidden, and the two functions
|
||||||
|
-- below are no-op wrappers around `EnterWorld` to keep the existing
|
||||||
|
-- call sites working.
|
||||||
|
function Autologin_OnCharactersLoad()
|
||||||
|
if ( AutologinSaveCharacterButton ) then
|
||||||
|
AutologinSaveCharacterButton:Hide();
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Autologin_EnterWorld()
|
||||||
|
EnterWorld();
|
||||||
|
end
|
||||||
|
|
||||||
function CharacterSelect_OnLoad()
|
function CharacterSelect_OnLoad()
|
||||||
this:SetSequence(0);
|
this:SetSequence(0);
|
||||||
this:SetCamera(0);
|
this:SetCamera(0);
|
||||||
@@ -44,7 +59,7 @@ function CharacterSelect_OnLoad()
|
|||||||
local backdropColor = DEFAULT_TOOLTIP_COLOR;
|
local backdropColor = DEFAULT_TOOLTIP_COLOR;
|
||||||
CharacterSelectCharacterFrame:SetBackdropBorderColor(backdropColor[1], backdropColor[2], backdropColor[3]);
|
CharacterSelectCharacterFrame:SetBackdropBorderColor(backdropColor[1], backdropColor[2], backdropColor[3]);
|
||||||
CharacterSelectCharacterFrame:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6], 0.85);
|
CharacterSelectCharacterFrame:SetBackdropColor(backdropColor[4], backdropColor[5], backdropColor[6], 0.85);
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function CharacterSelect_OnShow()
|
function CharacterSelect_OnShow()
|
||||||
@@ -57,7 +72,7 @@ function CharacterSelect_OnShow()
|
|||||||
local serverType = "";
|
local serverType = "";
|
||||||
if ( serverName ) then
|
if ( serverName ) then
|
||||||
if( not connected ) then
|
if( not connected ) then
|
||||||
serverName = serverName.."\n("..SERVER_DOWN..")";
|
serverName = serverName.."\n("..TEXT(SERVER_DOWN)..")";
|
||||||
end
|
end
|
||||||
if ( isPVP ) then
|
if ( isPVP ) then
|
||||||
if ( isRP ) then
|
if ( isRP ) then
|
||||||
@@ -89,7 +104,7 @@ function CharacterSelect_OnShow()
|
|||||||
else
|
else
|
||||||
local billingTimeLeft = GetBillingTimeRemaining();
|
local billingTimeLeft = GetBillingTimeRemaining();
|
||||||
-- Set default text for the payment plan
|
-- Set default text for the payment plan
|
||||||
local billingText = _G["BILLING_TEXT"..paymentPlan];
|
local billingText = getglobal("BILLING_TEXT"..paymentPlan);
|
||||||
if ( paymentPlan == 1 ) then
|
if ( paymentPlan == 1 ) then
|
||||||
-- Recurring account
|
-- Recurring account
|
||||||
billingTimeLeft = ceil(billingTimeLeft/(60 * 24));
|
billingTimeLeft = ceil(billingTimeLeft/(60 * 24));
|
||||||
@@ -100,7 +115,7 @@ function CharacterSelect_OnShow()
|
|||||||
-- Free account
|
-- Free account
|
||||||
if ( billingTimeLeft < (24 * 60) ) then
|
if ( billingTimeLeft < (24 * 60) ) then
|
||||||
billingText = format(BILLING_FREE_TIME_EXPIRE, billingTimeLeft.." "..GetText("MINUTES_ABBR", nil, billingTimeLeft));
|
billingText = format(BILLING_FREE_TIME_EXPIRE, billingTimeLeft.." "..GetText("MINUTES_ABBR", nil, billingTimeLeft));
|
||||||
end
|
end
|
||||||
elseif ( paymentPlan == 3 ) then
|
elseif ( paymentPlan == 3 ) then
|
||||||
-- Fixed but not recurring
|
-- Fixed but not recurring
|
||||||
if ( isGameRoom == 1 ) then
|
if ( isGameRoom == 1 ) then
|
||||||
@@ -115,7 +130,7 @@ function CharacterSelect_OnShow()
|
|||||||
billingText = BILLING_FIXED_LASTDAY;
|
billingText = BILLING_FIXED_LASTDAY;
|
||||||
else
|
else
|
||||||
billingText = format(billingText, MinutesToTime(billingTimeLeft));
|
billingText = format(billingText, MinutesToTime(billingTimeLeft));
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif ( paymentPlan == 4 ) then
|
elseif ( paymentPlan == 4 ) then
|
||||||
-- Usage plan
|
-- Usage plan
|
||||||
@@ -195,6 +210,7 @@ function CharacterSelect_OnEvent()
|
|||||||
end
|
end
|
||||||
UpdateCharacterList();
|
UpdateCharacterList();
|
||||||
CharSelectCharacterName:SetText(GetCharacterInfo(GetCharIDFromIndex(this.selectedIndex)));
|
CharSelectCharacterName:SetText(GetCharacterInfo(GetCharIDFromIndex(this.selectedIndex)));
|
||||||
|
Autologin_OnCharactersLoad();
|
||||||
elseif ( event == "UPDATE_SELECTED_CHARACTER" ) then
|
elseif ( event == "UPDATE_SELECTED_CHARACTER" ) then
|
||||||
if ( arg1 == 0 ) then
|
if ( arg1 == 0 ) then
|
||||||
CharSelectCharacterName:SetText("");
|
CharSelectCharacterName:SetText("");
|
||||||
@@ -219,9 +235,7 @@ function CharacterSelect_OnEvent()
|
|||||||
GlueDialog_Show("SUGGEST_REALM");
|
GlueDialog_Show("SUGGEST_REALM");
|
||||||
elseif ( event == "FORCE_RENAME_CHARACTER" ) then
|
elseif ( event == "FORCE_RENAME_CHARACTER" ) then
|
||||||
CharacterRenameDialog:Show();
|
CharacterRenameDialog:Show();
|
||||||
CharacterRenameBackground:SetHeight(16 + CharacterRenameText1:GetHeight() + CharacterRenameText2:GetHeight() + 23 + CharacterRenameEditBox:GetHeight() + 8 + CharacterRenameButton1:GetHeight() + 16);
|
CharacterRenameText1:SetText(getglobal(arg1));
|
||||||
|
|
||||||
CharacterRenameText1:SetText(_G[arg1]);
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -231,50 +245,56 @@ function CharacterSelect_UpdateModel()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UpdateCharacterSelection()
|
function UpdateCharacterSelection()
|
||||||
|
-- Drag-aware: during a drag, dim every slot except the one currently
|
||||||
|
-- holding the dragged character, and override the highlight to track
|
||||||
|
-- the drag rather than the engine-side "selected" character.
|
||||||
local draggedIndex = CharacterSelect.draggedIndex;
|
local draggedIndex = CharacterSelect.draggedIndex;
|
||||||
local highlightIndex = draggedIndex or CharacterSelect.selectedIndex;
|
local highlightIndex = draggedIndex or CharacterSelect.selectedIndex;
|
||||||
|
|
||||||
for i=1, MAX_CHARACTERS_DISPLAYED, 1 do
|
for i=1, MAX_CHARACTERS_DISPLAYED, 1 do
|
||||||
local btn = _G["CharSelectCharacterButton"..i];
|
local btn = getglobal("CharSelectCharacterButton"..i);
|
||||||
btn:UnlockHighlight();
|
btn:UnlockHighlight();
|
||||||
if ( draggedIndex and i ~= draggedIndex ) then
|
if ( draggedIndex and i ~= draggedIndex ) then
|
||||||
btn:SetAlpha(0.4);
|
btn:SetAlpha(0.6);
|
||||||
else
|
else
|
||||||
btn:SetAlpha(1);
|
btn:SetAlpha(1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if ( (highlightIndex > 0) and (highlightIndex <= MAX_CHARACTERS_DISPLAYED) ) then
|
|
||||||
_G["CharSelectCharacterButton"..highlightIndex]:LockHighlight();
|
if ( highlightIndex and (highlightIndex > 0) and (highlightIndex <= MAX_CHARACTERS_DISPLAYED) ) then
|
||||||
|
getglobal("CharSelectCharacterButton"..highlightIndex):LockHighlight();
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function UpdateCharacterList()
|
function UpdateCharacterList()
|
||||||
local numChars = GetNumCharacters();
|
local numChars = GetNumCharacters();
|
||||||
local index = 1;
|
local index = 1;
|
||||||
|
local coords;
|
||||||
for i=1, numChars, 1 do
|
for i=1, numChars, 1 do
|
||||||
local name, race, class, level, zone, fileString, gender, ghost = GetCharacterInfo(GetCharIDFromIndex(i));
|
local name, race, class, level, zone, fileString, gender, ghost = GetCharacterInfo(GetCharIDFromIndex(i));
|
||||||
|
if ( gender == 0 ) then
|
||||||
local button = _G["CharSelectCharacterButton"..index];
|
gender = "MALE";
|
||||||
|
else
|
||||||
|
gender = "FEMALE";
|
||||||
|
end
|
||||||
|
local button = getglobal("CharSelectCharacterButton"..index);
|
||||||
if ( not name ) then
|
if ( not name ) then
|
||||||
button:SetText("ERROR - Tell Jeremy");
|
button:SetText("ERROR - Tell Jeremy");
|
||||||
else
|
else
|
||||||
if ( not zone ) then
|
if ( not zone ) then
|
||||||
zone = "";
|
zone = "";
|
||||||
end
|
end
|
||||||
|
local classToken = TW_CLASS_TOKEN and TW_CLASS_TOKEN[class];
|
||||||
local classColor
|
if ( classToken and CLASS_COLORS[classToken] ) then
|
||||||
local classToken = TW_CLASS_TOKEN and TW_CLASS_TOKEN[class]
|
class = CLASS_COLORS[classToken] .. class .. "|r";
|
||||||
if classToken and CLASS_COLORS[classToken] then
|
|
||||||
classColor = CLASS_COLORS[classToken]
|
|
||||||
class = classColor .. class .. "|r"
|
|
||||||
end
|
end
|
||||||
_G["CharSelectCharacterButton"..index.."ButtonTextName"]:SetText(name);
|
getglobal("CharSelectCharacterButton"..index.."ButtonTextName"):SetText(name);
|
||||||
if ( ghost ) then
|
if( ghost ) then
|
||||||
_G["CharSelectCharacterButton"..index.."ButtonTextInfo"]:SetText(format(CHARACTER_SELECT_INFO_GHOST, level, class));
|
getglobal("CharSelectCharacterButton"..index.."ButtonTextInfo"):SetText(format(TEXT(CHARACTER_SELECT_INFO_GHOST), level, class));
|
||||||
else
|
else
|
||||||
_G["CharSelectCharacterButton"..index.."ButtonTextInfo"]:SetText(format(CHARACTER_SELECT_INFO, level, class));
|
getglobal("CharSelectCharacterButton"..index.."ButtonTextInfo"):SetText(format(TEXT(CHARACTER_SELECT_INFO), level, class));
|
||||||
end
|
end
|
||||||
_G["CharSelectCharacterButton"..index.."ButtonTextLocation"]:SetText(zone);
|
getglobal("CharSelectCharacterButton"..index.."ButtonTextLocation"):SetText(zone);
|
||||||
end
|
end
|
||||||
button:Show();
|
button:Show();
|
||||||
|
|
||||||
@@ -293,18 +313,18 @@ function UpdateCharacterList()
|
|||||||
end
|
end
|
||||||
|
|
||||||
CharacterSelect.createIndex = 0;
|
CharacterSelect.createIndex = 0;
|
||||||
CharSelectCreateCharacterButton:Hide();
|
CharSelectCreateCharacterButton:Hide();
|
||||||
|
|
||||||
local connected = IsConnectedToServer();
|
local connected = IsConnectedToServer();
|
||||||
for i=index, MAX_CHARACTERS_DISPLAYED, 1 do
|
for i=index, MAX_CHARACTERS_DISPLAYED, 1 do
|
||||||
local button = _G["CharSelectCharacterButton"..index];
|
local button = getglobal("CharSelectCharacterButton"..index);
|
||||||
if ( (CharacterSelect.createIndex == 0) and (numChars < MAX_CHARACTERS_PER_REALM) ) then
|
if ( (CharacterSelect.createIndex == 0) and (numChars < MAX_CHARACTERS_PER_REALM) ) then
|
||||||
CharacterSelect.createIndex = index;
|
CharacterSelect.createIndex = index;
|
||||||
if ( connected ) then
|
if ( connected ) then
|
||||||
--If can create characters position and show the create button
|
--If can create characters position and show the create button
|
||||||
CharSelectCreateCharacterButton:SetID(index);
|
CharSelectCreateCharacterButton:SetID(index);
|
||||||
--CharSelectCreateCharacterButton:SetPoint("TOP", button, "TOP", 0, -5);
|
--CharSelectCreateCharacterButton:SetPoint("TOP", button, "TOP", 0, -5);
|
||||||
CharSelectCreateCharacterButton:Show();
|
CharSelectCreateCharacterButton:Show();
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
button:Hide();
|
button:Hide();
|
||||||
@@ -332,6 +352,8 @@ function CharacterSelect_OnChar()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function CharacterSelectButton_OnClick()
|
function CharacterSelectButton_OnClick()
|
||||||
|
-- A drag just ended on top of this button — eat the click so the
|
||||||
|
-- drop doesn't also re-select the character at the new slot.
|
||||||
if ( CharacterSelect.suppressNextClick ) then
|
if ( CharacterSelect.suppressNextClick ) then
|
||||||
CharacterSelect.suppressNextClick = nil;
|
CharacterSelect.suppressNextClick = nil;
|
||||||
return;
|
return;
|
||||||
@@ -355,10 +377,10 @@ function CharacterSelectButton_OnDoubleClick()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function CharacterSelect_TabResize()
|
function CharacterSelect_TabResize()
|
||||||
local buttonMiddle = _G[this:GetName().."Middle"];
|
local buttonMiddle = getglobal(this:GetName().."Middle");
|
||||||
local buttonMiddleDisabled = _G[this:GetName().."MiddleDisabled"];
|
local buttonMiddleDisabled = getglobal(this:GetName().."MiddleDisabled");
|
||||||
local width = this:GetTextWidth() - 8;
|
local width = this:GetTextWidth() - 8;
|
||||||
local leftWidth = _G[this:GetName().."Left"]:GetWidth();
|
local leftWidth = getglobal(this:GetName().."Left"):GetWidth();
|
||||||
buttonMiddle:SetWidth(width);
|
buttonMiddle:SetWidth(width);
|
||||||
buttonMiddleDisabled:SetWidth(width);
|
buttonMiddleDisabled:SetWidth(width);
|
||||||
this:SetWidth(width + (2 * leftWidth));
|
this:SetWidth(width + (2 * leftWidth));
|
||||||
@@ -386,14 +408,14 @@ end
|
|||||||
|
|
||||||
function CharacterDeleteDialog_OnShow()
|
function CharacterDeleteDialog_OnShow()
|
||||||
local name, race, class, level = GetCharacterInfo(GetCharIDFromIndex(CharacterSelect.selectedIndex));
|
local name, race, class, level = GetCharacterInfo(GetCharIDFromIndex(CharacterSelect.selectedIndex));
|
||||||
CharacterDeleteText1:SetText(format(CONFIRM_CHAR_DELETE, name, level, class));
|
CharacterDeleteText1:SetText(format(TEXT(CONFIRM_CHAR_DELETE), name, level, class));
|
||||||
CharacterDeleteBackground:SetHeight(16 + CharacterDeleteText1:GetHeight() + CharacterDeleteText2:GetHeight() + 23 + CharacterDeleteEditBox:GetHeight() + 8 + CharacterDeleteButton1:GetHeight() + 16);
|
CharacterDeleteBackground:SetHeight(16 + CharacterDeleteText1:GetHeight() + CharacterDeleteText2:GetHeight() + 23 + CharacterDeleteEditBox:GetHeight() + 8 + CharacterDeleteButton1:GetHeight() + 16);
|
||||||
CharacterDeleteButton1:Disable();
|
CharacterDeleteButton1:Disable();
|
||||||
end
|
end
|
||||||
|
|
||||||
function CharacterSelect_EnterWorld()
|
function CharacterSelect_EnterWorld()
|
||||||
PlaySound("gsCharacterSelectionEnterWorld");
|
PlaySound("gsCharacterSelectionEnterWorld");
|
||||||
EnterWorld();
|
Autologin_EnterWorld();
|
||||||
end
|
end
|
||||||
|
|
||||||
function CharacterSelect_Exit()
|
function CharacterSelect_Exit()
|
||||||
@@ -408,7 +430,7 @@ end
|
|||||||
|
|
||||||
function CharacterSelect_TechSupport()
|
function CharacterSelect_TechSupport()
|
||||||
PlaySound("gsCharacterSelectionAcctOptions");
|
PlaySound("gsCharacterSelectionAcctOptions");
|
||||||
LaunchURL(TECH_SUPPORT_URL);
|
LaunchURL(TEXT(TECH_SUPPORT_URL));
|
||||||
end
|
end
|
||||||
|
|
||||||
function CharacterSelect_Delete()
|
function CharacterSelect_Delete()
|
||||||
@@ -469,10 +491,9 @@ end
|
|||||||
|
|
||||||
function CharacterSelect_ManageAccount()
|
function CharacterSelect_ManageAccount()
|
||||||
PlaySound("gsCharacterSelectionAcctOptions");
|
PlaySound("gsCharacterSelectionAcctOptions");
|
||||||
LaunchURL(AUTH_NO_TIME_URL);
|
LaunchURL(TEXT(AUTH_NO_TIME_URL));
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- ---------------------------------------------------------------------------
|
-- ---------------------------------------------------------------------------
|
||||||
-- Character reordering
|
-- Character reordering
|
||||||
-- ---------------------------------------------------------------------------
|
-- ---------------------------------------------------------------------------
|
||||||
@@ -685,12 +706,6 @@ function CharacterOrder_Save()
|
|||||||
local realm = GetServerName() or "";
|
local realm = GetServerName() or "";
|
||||||
if ( realm == "" ) then return; end
|
if ( realm == "" ) then return; end
|
||||||
local numChars = GetNumCharacters();
|
local numChars = GetNumCharacters();
|
||||||
-- Skip when the list is empty. CHARACTER_LIST_UPDATE can fire in a
|
|
||||||
-- transient state (returning to glue after logout, before the server's
|
|
||||||
-- SMSG_CHAR_ENUM populates the list) where numChars is briefly 0.
|
|
||||||
-- Writing an empty string here would wipe the saved order before the
|
|
||||||
-- real update arrives to Apply it.
|
|
||||||
if ( numChars == 0 ) then return; end
|
|
||||||
local names = {};
|
local names = {};
|
||||||
for i = 1, numChars do
|
for i = 1, numChars do
|
||||||
local name = GetCharacterInfo(GetCharIDFromIndex(i));
|
local name = GetCharacterInfo(GetCharIDFromIndex(i));
|
||||||
|
|||||||
+50
-14
@@ -125,16 +125,52 @@
|
|||||||
CharacterSelect_EnterWorld();
|
CharacterSelect_EnterWorld();
|
||||||
</OnClick>
|
</OnClick>
|
||||||
</Scripts>
|
</Scripts>
|
||||||
<NormalText>
|
|
||||||
<Anchors>
|
|
||||||
<Anchor point="CENTER">
|
|
||||||
<Offset>
|
|
||||||
<AbsDimension x="-1" y="3"/>
|
|
||||||
</Offset>
|
|
||||||
</Anchor>
|
|
||||||
</Anchors>
|
|
||||||
</NormalText>
|
|
||||||
</Button>
|
</Button>
|
||||||
|
<CheckButton name="AutologinSaveCharacterButton">
|
||||||
|
<Size>
|
||||||
|
<AbsDimension x="20" y="20"/>
|
||||||
|
</Size>
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="LEFT" relativeTo="CharSelectEnterWorldButton" relativePoint="RIGHT"/>
|
||||||
|
</Anchors>
|
||||||
|
<Layers>
|
||||||
|
<Layer level="ARTWORK">
|
||||||
|
<FontString inherits="GlueFontNormalSmall" text="Auto-login this character">
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="LEFT">
|
||||||
|
<Offset>
|
||||||
|
<AbsDimension x="24" y="0"/>
|
||||||
|
</Offset>
|
||||||
|
</Anchor>
|
||||||
|
</Anchors>
|
||||||
|
<FontHeight>
|
||||||
|
<AbsValue val="10"/>
|
||||||
|
</FontHeight>
|
||||||
|
<Shadow>
|
||||||
|
<Offset>
|
||||||
|
<AbsDimension x="1" y="-1"/>
|
||||||
|
</Offset>
|
||||||
|
<Color r="0" g="0" b="0"/>
|
||||||
|
</Shadow>
|
||||||
|
<Color r="1.0" g="0.78" b="0"/>
|
||||||
|
</FontString>
|
||||||
|
</Layer>
|
||||||
|
</Layers>
|
||||||
|
<Scripts>
|
||||||
|
<OnClick>
|
||||||
|
if ( this:GetChecked() ) then
|
||||||
|
PlaySound("igMainMenuOptionCheckBoxOff");
|
||||||
|
else
|
||||||
|
PlaySound("igMainMenuOptionCheckBoxOn");
|
||||||
|
end
|
||||||
|
</OnClick>
|
||||||
|
</Scripts>
|
||||||
|
<NormalTexture file="Interface\Buttons\UI-CheckBox-Up"/>
|
||||||
|
<PushedTexture file="Interface\Buttons\UI-CheckBox-Down"/>
|
||||||
|
<HighlightTexture file="Interface\Buttons\UI-CheckBox-Highlight" alphaMode="ADD"/>
|
||||||
|
<CheckedTexture file="Interface\Buttons\UI-CheckBox-Check"/>
|
||||||
|
<DisabledCheckedTexture file="Interface\Buttons\UI-CheckBox-Check-Disabled"/>
|
||||||
|
</CheckButton>
|
||||||
<Button name="CharacterSelectRotateLeft">
|
<Button name="CharacterSelectRotateLeft">
|
||||||
<Size>
|
<Size>
|
||||||
<AbsDimension x="50" y="50"/>
|
<AbsDimension x="50" y="50"/>
|
||||||
@@ -607,7 +643,7 @@
|
|||||||
<Anchors>
|
<Anchors>
|
||||||
<Anchor point="LEFT">
|
<Anchor point="LEFT">
|
||||||
<Offset>
|
<Offset>
|
||||||
<AbsDimension x="12" y="4"/>
|
<AbsDimension x="12" y="10"/>
|
||||||
</Offset>
|
</Offset>
|
||||||
</Anchor>
|
</Anchor>
|
||||||
</Anchors>
|
</Anchors>
|
||||||
@@ -615,7 +651,7 @@
|
|||||||
</Layer>
|
</Layer>
|
||||||
</Layers>
|
</Layers>
|
||||||
<Frames>
|
<Frames>
|
||||||
<Button name="CharacterDeleteButton1" inherits="GlueDialogButtonTemplate" id="1" text="CONFIRM">
|
<Button name="CharacterDeleteButton1" inherits="GlueDialogButtonTemplate" id="1" text="OKAY">
|
||||||
<Anchors>
|
<Anchors>
|
||||||
<Anchor point="BOTTOMRIGHT" relativeTo="CharacterDeleteBackground" relativePoint="BOTTOM">
|
<Anchor point="BOTTOMRIGHT" relativeTo="CharacterDeleteBackground" relativePoint="BOTTOM">
|
||||||
<Offset>
|
<Offset>
|
||||||
@@ -695,7 +731,7 @@
|
|||||||
else
|
else
|
||||||
CharacterDeleteButton1:Disable();
|
CharacterDeleteButton1:Disable();
|
||||||
end
|
end
|
||||||
</OnTextChanged>
|
</OnTextChanged>
|
||||||
<OnEnterPressed>
|
<OnEnterPressed>
|
||||||
if ( CharacterDeleteButton1:IsEnabled() == 1 ) then
|
if ( CharacterDeleteButton1:IsEnabled() == 1 ) then
|
||||||
CharacterSelect_DeleteCharacter();
|
CharacterSelect_DeleteCharacter();
|
||||||
@@ -775,7 +811,7 @@
|
|||||||
<Anchors>
|
<Anchors>
|
||||||
<Anchor point="LEFT">
|
<Anchor point="LEFT">
|
||||||
<Offset>
|
<Offset>
|
||||||
<AbsDimension x="12" y="4"/>
|
<AbsDimension x="12" y="10"/>
|
||||||
</Offset>
|
</Offset>
|
||||||
</Anchor>
|
</Anchor>
|
||||||
</Anchors>
|
</Anchors>
|
||||||
@@ -783,7 +819,7 @@
|
|||||||
</Layer>
|
</Layer>
|
||||||
</Layers>
|
</Layers>
|
||||||
<Frames>
|
<Frames>
|
||||||
<Button name="CharacterRenameButton1" inherits="GlueDialogButtonTemplate" id="1" text="CONFIRM">
|
<Button name="CharacterRenameButton1" inherits="GlueDialogButtonTemplate" id="1" text="OKAY">
|
||||||
<Anchors>
|
<Anchors>
|
||||||
<Anchor point="BOTTOMRIGHT" relativeTo="CharacterRenameBackground" relativePoint="BOTTOM">
|
<Anchor point="BOTTOMRIGHT" relativeTo="CharacterRenameBackground" relativePoint="BOTTOM">
|
||||||
<Offset>
|
<Offset>
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
# Octo GlueXML
|
|
||||||
|
|
||||||
Custom login and character-select UI for [Octo](https://octowow.st). Overlays
|
|
||||||
a small subset of the stock glue files with three features; everything else in
|
|
||||||
`Interface/GlueXML/` is loaded unchanged from the base MPQs.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- **Saved-account login.** The login screen shows a scrollable list of
|
|
||||||
previously-used accounts with their last-used timestamp. Clicking a row fills
|
|
||||||
the account name and hides the password field; a login without a typed
|
|
||||||
password logs in using the credential stored in the Windows Credential
|
|
||||||
Manager. A "Change password" button reveals the field on demand when you
|
|
||||||
need to update a saved credential.
|
|
||||||
- **Character reordering.** Hold on a character in the select screen for half
|
|
||||||
a second to enter drag mode, then move it up or down. Order is saved
|
|
||||||
per-realm and restored on the next login.
|
|
||||||
|
|
||||||
## ClassicAPI dependency
|
|
||||||
|
|
||||||
The saved-login and character-order features rely on Lua bindings exposed by
|
|
||||||
the ClassicAPI DLL, which is loaded alongside the client. Both features guard
|
|
||||||
their entry points with `type(fn) ~= "function"` checks so the UI still
|
|
||||||
functions when the DLL isn't present — you just lose persistence.
|
|
||||||
|
|
||||||
### Saved login — Windows Credential Manager
|
|
||||||
|
|
||||||
Passwords never live in Lua or in `WTF/`. They go straight from the password
|
|
||||||
field into the OS credential vault, and login submits are dispatched from C so
|
|
||||||
the plaintext never crosses back.
|
|
||||||
|
|
||||||
| Binding | Purpose |
|
|
||||||
|---|---|
|
|
||||||
| `SaveAccount(name, password)` | Writes a credential-vault entry. Called when the user types a password (either a first-time save or a "Change password" update). |
|
|
||||||
| `LoginWithSavedAccount(name)` | C-side dispatch of the login using the vault password for `name`. |
|
|
||||||
| `GetSavedAccounts()` | Returns `{ {name=…, lastUsed=epochSeconds}, … }` — `lastUsed` is the Windows `LastWritten` timestamp on the vault entry, auto-refreshed by `LoginWithSavedAccount`. |
|
|
||||||
| `DeleteAccount(name)` | Removes a vault entry (backs the "Remove account" button). |
|
|
||||||
| `GetSavedAccountName()` / `SetSavedAccountName(name)` | Persists just the *last-used* account name (via `SavedVariables`) so the same row is pre-selected on next launch. No password, no character map — those were dropped alongside the plaintext store. |
|
|
||||||
|
|
||||||
### Character sort order — per-realm WTF persistence
|
|
||||||
|
|
||||||
Persistence is keyed by character *name*, not by server-assigned charID. Slots
|
|
||||||
renumber every time a character is added or deleted, so name is the only
|
|
||||||
stable identifier.
|
|
||||||
|
|
||||||
| Binding | Purpose |
|
|
||||||
|---|---|
|
|
||||||
| `GetSavedCharacterOrder(realm)` | Reads a `\|`-separated name string for the current realm. |
|
|
||||||
| `SetSavedCharacterOrder(realm, names)` | Writes it back. |
|
|
||||||
|
|
||||||
On every `CHARACTER_LIST_UPDATE` the code loads the saved string, resolves
|
|
||||||
each name to the current charID, drops names the server no longer knows about
|
|
||||||
(deletions), appends any characters not in the saved list (creations), and
|
|
||||||
re-saves. That means the on-disk order self-cleans without a hook in the
|
|
||||||
delete path.
|
|
||||||
|
|
||||||
## Releases
|
|
||||||
|
|
||||||
Push a `v*` tag to trigger the
|
|
||||||
[mpq-packager](https://octowow.st/git/paste/mpq-packager) Gitea Action
|
|
||||||
(`.gitea/workflows/release.yml`), which packages this repo into a
|
|
||||||
`patch-Z.mpq` via StormLib according to `mpq.yaml`. `Z` sorts after Blizzard's
|
|
||||||
stock MPQs, so its files win on conflict. Only `.lua`, `.xml`, and `.toc`
|
|
||||||
files are placed in the MPQ — this README, workflow files, and build config
|
|
||||||
are excluded.
|
|
||||||
Reference in New Issue
Block a user