diff --git a/CHANGELOG.md b/CHANGELOG.md index 02c78108..847ab841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # CHANGELOG +## v4.0.0 + +- MAJOR: introducing a brand new view mode called Map Mode, check it out by right-clicking the TW II window, select MODE and then MAP VIEW +- enhance: adding new notification window notifying of changes in installed update +- enhance: adding some region labels to U46 skill data for EN/DE/FR/RU +- enhance: vendor and skillname updates from U46.0.1 for FR + ## v3.2.0 - enhance: window positioning is happening now relative to screen rather than absolute - positioning will work now much better if screen resolutions changes diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..f0986f95 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,2 @@ +all plugin files have to be lua files, the plugin environment cannot read any other format or file extension + diff --git a/TravelWindowII.plugin b/TravelWindowII.plugin index 0fc550f5..6f72e3b7 100644 --- a/TravelWindowII.plugin +++ b/TravelWindowII.plugin @@ -3,7 +3,7 @@ Travel Window II Hyos and WhiteRabbit963 - v3.2.0 + v4.0.0 This plugin creates a single window that contains all the available travel skills, including the race, class and reputation skills. It is a further development of Travel Window, that has been worked on by multiple authors before. diff --git a/TravelWindowII.plugincompendium b/TravelWindowII.plugincompendium index d9a998d0..ae3e925d 100644 --- a/TravelWindowII.plugincompendium +++ b/TravelWindowII.plugincompendium @@ -2,7 +2,7 @@ 1113 Travel Window II - v3.2.0 + v4.0.0 Hyos and WhiteRabbit963 http://www.lotrointerface.com/downloads/info1113 http://www.lotrointerface.com/downloads/download1113 diff --git a/doc/lotroforums.txt b/doc/lotroforums.txt index 5af2398f..ee7adac8 100644 --- a/doc/lotroforums.txt +++ b/doc/lotroforums.txt @@ -1,14 +1,13 @@ -A new version is available! +A new MAJOR version is available! -v3.2.0 +v4.0.0 -- enhance: window positioning is happening now relative to screen rather than absolute - positioning will work now much better if screen resolutions changes -- enhance: add new skills from U46 in EN/DE/FR -- enhance: add skills from U45.X in RU -- enhance: adjust Annak-Khurfu map location -- fix: updated to support skills renamed in U45.X in EN/DE/FR/RU +- MAJOR: introducing a brand new view mode called Map Mode, check it out by right-clicking the TW II window, select MODE and then MAP VIEW +- enhance: adding new notification window notifying of changes in installed update +- enhance: adding some region labels to U46 skill data for EN/DE/FR/RU +- enhance: vendor and skillname updates from U46.0.1 for FR -Help with further translations for DE, FR and RU clients is welcome. Ideally submitted as pull requests on GitHub, but any way can be accomodated really. +Help with further translations for DE, FR and RU clients is always welcome. Ideally submitted as pull requests on GitHub, but any way can be accomodated really. Download it at [url=https://www.lotrointerface.com/downloads/fileinfo.php?id=1113]Lotrointerface[/url], [url=https://github.com/wduda/TravelWindowII/releases]GitHub[/url], via [url=https://github.com/JeremyStepp/OneLauncher]OneLauncher[/url] or via [url=https://www.lotrointerface.com/downloads/info663-LOTROPluginCompendium.html]Plugin Compendium[/url]. diff --git a/doc/lotrointerface.txt b/doc/lotrointerface.txt index e474e8a3..0e587270 100644 --- a/doc/lotrointerface.txt +++ b/doc/lotrointerface.txt @@ -1,8 +1,8 @@ This plugin creates a single window that contains available travel skills, including race, class, housing, and reputation skills. -The plugin has four modes of operation - icon grid, text list, pulldown list and carousel. These can be switched from the menu that opens when you right-click the plugin. +The plugin has five modes of operation - icon grid, map view, text list, pulldown list and carousel. These can be switched from the menu that opens when you right-click the plugin. This menu also gives you access to the options window. -It is a further development of the "Travel Window" plugin, that has been worked on by multiple authors before. +The plugin is a continuation of the "Travel Window" plugin, that has been worked on by multiple authors before. [B]Since this plugin is a 100% replacement for "Travel Window" you should not have both enabled at the same time. You can keep them both installed though.[/B] [SIZE="3"]Installation:[/SIZE] @@ -20,7 +20,6 @@ Why does the plugin crash on brand new Creep characters? Those have zero travel skills. After completing the tutorial you obtain the first travel skill and the plugin will load. [/LIST] - How do I use the Carousel mode? [LIST] Use the mousewheel while hovering over the travel skill icon to change the selected skill. @@ -28,17 +27,16 @@ Use the mousewheel while hovering over the travel skill icon to change the selec Version history: -v3.2.0 +v4.0.0 -- enhance: window positioning is happening now relative to screen rather than absolute - positioning will work now much better if screen resolutions changes -- enhance: add new skills from U46 in EN/DE/FR -- enhance: add skills from U45.X in RU -- enhance: adjust Annak-Khurfu map location -- fix: updated to support skills renamed in U45.X in EN/DE/FR/RU +- MAJOR UPDATE: introducing a brand new view mode called Map Mode, check it out by right-clicking the TW II window, select MODE and then MAP VIEW +- enhance: adding new notification window notifying of changes in installed update +- enhance: adding some region labels to U46 skill data for EN/DE/FR/RU +- enhance: vendor and skillname updates from U46.0.1 for FR Rest of changelog found [URL="https://github.com/wduda/TravelWindowII/blob/master/CHANGELOG.md"]here[/URL]. -Help with further translations for DE, FR and RU clients is welcome. Ideally submitted as pull requests on GitHub, but any way can be accomodated really. +Help with further translations for DE, FR and RU clients is always welcome. Ideally submitted as pull requests on GitHub, but any way can be accomodated really. Other than contacting here on lotrointerface, you can also do that on the [url=https://forums.lotro.com/index.php?threads/plugin-travel-window-ii.1400/]official forums thread[/url], on [url=https://github.com/wduda/TravelWindowII/discussions]GitHub[/url] where you will also find the source code, and I also monitor a post on the official [url=https://discord.com/channels/1253092003218985092/1339975894902505523]LOTRO Discord[/url]. diff --git a/screenshots/eriador-map.png b/screenshots/eriador-map.png index 89fdfee0..bba90eb4 100644 Binary files a/screenshots/eriador-map.png and b/screenshots/eriador-map.png differ diff --git a/src/ChangelogData.lua b/src/ChangelogData.lua new file mode 100644 index 00000000..28086347 --- /dev/null +++ b/src/ChangelogData.lua @@ -0,0 +1,188 @@ +-- Changelog data structure for update notifications +-- Versions are ordered newest first +-- Each entry: {version = "v3.x.x", changes = {"line1", "line2", ...}} + +ChangelogData = { + { + version = "v4.0.0", + changes = { + "MAJOR: introducing a brand new view mode called Map Mode", + "MAJOR: check it out by right-clicking the TW II window, select MODE and then MAP VIEW", + "enhance: adding new notification window notifying of changes in installed update", + "enhance: adding some region labels to U46 skill data for EN/DE/FR/RU", + "enhance: vendor and skillname updates from U46.0.1 for FR" + } + }, + { + version = "v3.2.0", + changes = { + "enhance: window positioning is happening now relative to screen rather than absolute - positioning will work now much better if screen resolutions changes", + "enhance: add new skills from U46 in EN/DE/FR", + "enhance: add skills from U45.X in RU", + "enhance: adjust Annak-Khurfu map location", + "fix: updated to support skills renamed in U45.X in EN/DE/FR/RU" + } + }, + { + version = "v3.1.0", + changes = { + "enhance: the skill type is now an optional part of the skill label and can be turned off - affects text list and tab pulldown view only", + "enhance: the text list view now does not force line breaks forcing inconsistent line height", + "enhance: the pulldown tab view can now be resized horizontally", + "fix: map window is again loading for creep characters", + "fix: the reputation requirement for King's Gondor version of Dol Amroth is correctly shown as friend", + "fix: the Find tab now shows updated lower levels for Hunter skills learned earlier after rework", + "fix: all skills for travel to King's Gondor version of Dol Amroth will be recognized again in all languages official languagaes" + } + }, + { + version = "v3.0.0", + changes = { + "enhance: the Find tab in options now has information on all obtainable skills and their sources", + "enhance: the Find tab in options now has full support for all four supported langauges", + "enhance: the Find tab in options now has better formatting of source entries", + "enhance: added new travel skills from U44 in EN/DE/FR", + "enhance: mini window can now be scaled down to width of one skill", + "fix: Mariner skill for Lothlorien now has proper duplicate detection" + } + }, + { + version = "v2.6.0", + changes = { + "enhance: added new travel skills from U43 in EN/DE/FR", + "enhance: adding labels for eight more barter currencies for skill source tab" + } + }, + { + version = "v2.5.1", + changes = { + "enhance: added Ikorbani faction, adding rep level required for U42 skills", + "enhance: adding some tokennames to DE and FR to start filling the acquisition tab", + "enhance: open pull-down list upwards/downwards based on screen check so it does not go off screen", + "fix: wrong label for Guide to Jirush" + } + }, + { + version = "v2.5.0", + changes = { + "enhance: U42 travel skills added for EN/FR/DE for all classes, with map coords, overlap settings and aquisition source", + "enhance: removed no longer needed buttons and options menu for \"Check Trained Skills\" as TW II now reliably autodetects skill acquisition", + "fix: Dol Amroth and Halrax now have correct coordinates on Haradwaith map for guide/muster/sail skills", + "fix: Bej Magha skills will now be detected again after being renamed by SSG in U42" + } + }, + { + version = "v2.4.4", + changes = { + "enhance: UI texts in RU - skill acquisition data tab should now be complete" + } + }, + { + version = "v2.4.3", + changes = { + "enhance: minor enhancements to skill acquisition data for Find Skills tab in EN (skill acquisition data data should now be complete)", + "enhance: updated most UI texts in DE (skill acquisition data still not fully supported)", + "enhance: updated most UI texts in RU (skill acquisition data should now be complete)" + } + }, + { + version = "v2.4.2", + changes = { + "enhance: plugin will be more resilient against mistakes by authors when adding new text for labels", + "enhance: added many new text labels for RU client support (RU support is still unfinished and in beta status)", + "enhance: skill info labels on learnable skills tab will be more readable (tab is fully functional in EN only, beta in DE/FR/RU)", + "fix: new skill acquisition detection will now work in RU client", + "fix: Ledger-Keepers in DE client now have a German label", + "fix: multiple fixes to currency names and minor typos" + } + }, + { + version = "v2.4.1", + changes = { + "fix: plugin will no longer fail to load in DE and FR client" + } + }, + { + version = "v2.4.0", + changes = { + "add: newly learned skills will be detected automatically and become visible and usable in TW II", + "add: new option to use skill name as label instead of location name", + "add: incorporated RU translations by Svertalf", + "add: new options tab with list of still learnable travel skills", + "add: acquisition method for skills on still learnable skills tab (beta, EN only)", + "enhance: checkboxes in options now have better labels so checkbox marked means \"turned on\"", + "enhance: minor improvements to main window, mostly fixing scaling issues" + } + }, + { + version = "v2.3.1", + changes = { + "add: option to turn off zone names in labels", + "fix: icons on maps sometimes not turning on/off properly" + } + }, + { + version = "v2.3.0", + changes = { + "add: grid tab sorting through drag & drop", + "add: all travel skill labels now also have data for the zone (i.e. \"Michel Delving\" is in zone \"Shire\")", + "add: enabled list now has labelled sections", + "add: options window position can be locked now", + "add: toggle button position can be locked now", + "add: Bej Maghda travel skill and map location in EN/DE/FR client", + "enhance: code cleanup in multiple methods under the hood", + "fix: rare case for window width snapping that was adding extra padding", + "fix: scroll height calculation for scroll bar", + "fix: ambiguity in Beorning racial skill in EN/DE/FR client", + "fix: Mariner Tharbad skill name & label in FR client" + } + }, + { + version = "v2.2.0", + changes = { + "add: sorting alphabetically by skill label", + "add: sorting by zone level", + "add: move skill in sort list up/down by 10 slots", + "enhance: saving globals properly remembers hunter/mariner/warden skills for those classes", + "enhance: smooth out grid resize snapping around a column midpoint", + "enhance: remove dependency on Turbine utils, these can be removed if you do not need them for other plugins", + "enhance: significantly improved skill data storage in codebase to prevent human mistakes when creating new releases", + "fix: saving and loading globals will save properly every time and not mess up sort order", + "fix: plugin will load again for creep characters", + "fix: updated creep travel skills in EN/DE/FR" + } + }, + { + version = "v2.1.0", + changes = { + "add: default and alphabetic ordering buttons in sorting tab (note: sort by name sorts by ingame name, not by TW II label)", + "add: a fade out delay and option slider to control duration of that delay", + "enhance: mini and legacy windows having the same minimum size", + "enhance: resize hitbox now has highlight on hover", + "enhance: increased size for mini-window resize hitbox", + "enhance: overlapping skills button no longer turns off Lalia's market", + "enhance: enable/disable overlapping skills buttons only show up if character has overlapping skills", + "enhance: updated labels for King's Gondor Dol Amroth in EN/DE/FR", + "enhance: download size of plugin reduced from 2MB+ to 200kb", + "fix: last entry in text list being not visible in legacy window", + "fix: made row snapping much smoother", + "fix: multiple small resizing issues" + } + }, + { + version = "v2.0.0", + changes = { + "adds a mini window option offering an alternative interface with minimal window size", + "adds skills snapping for cleaner resizing of main and mini windows", + "adds slider to control speed of fadeout to min opacity", + "adds the ability to save a global preset so main options can be transferred to alts", + "adds option to control whether Esc closes main Travel window", + "adds enable/disable all buttons in enable options tab", + "adds enable/disable button for overlapping class/reputation skills in enable options tab", + "sets default sort so racial & class skills come after general skills to get closer to level progression sorting", + "fixes Travel Window opening behind chat and Travel Button", + "fixes missing Return to Dol Amroth (Western Gondor) in DE client", + "significant code cleanup under the hood for more reliable and maintainable code" + } + }, +} diff --git a/src/LocaleData.lua b/src/LocaleData.lua index 281d1626..3f00268f 100644 --- a/src/LocaleData.lua +++ b/src/LocaleData.lua @@ -257,20 +257,20 @@ LC_DE.rep.IKORBANI = "Die Ikorbâni" LC_FR.rep.IKORBANI = "Les Ikorbâni" LC_RU.rep.IKORBANI = "Жители Икорбана" -LC_EN.rep.KINTAI_OF_SUL_MADASH = "Kintai of Sul Madásh" -LC_DE.rep.KINTAI_OF_SUL_MADASH = "Kintai von Sul Madásh" -LC_FR.rep.KINTAI_OF_SUL_MADASH = "Kintai de Sul Madash" -LC_RU.rep.KINTAI_OF_SUL_MADASH = "Кинтайцы из Сул-Мадаша" +LC_EN.rep.TEMAMIR_OF_JIRET_MENESH = "Temámir of Jiret-menêsh" +LC_DE.rep.TEMAMIR_OF_JIRET_MENESH = "Temámir von Jiret-menêsh" +LC_FR.rep.TEMAMIR_OF_JIRET_MENESH = "Temamir de Jiret-menêsh" +LC_RU.rep.TEMAMIR_OF_JIRET_MENESH = "Темамиры Джирет-Менеша" LC_EN.rep.CITY_OF_ZAJANA = "City of Zajâna" LC_DE.rep.CITY_OF_ZAJANA = "Stadt Zajâna" LC_FR.rep.CITY_OF_ZAJANA = "Cité de Zajâna" LC_RU.rep.CITY_OF_ZAJANA = "Город Заджана" -LC_EN.rep.TEMAMIR_OF_JIRET_MENESH = "Temámir of Jiret-menêsh" -LC_DE.rep.TEMAMIR_OF_JIRET_MENESH = "Temámir von Jiret-menêsh" -LC_FR.rep.TEMAMIR_OF_JIRET_MENESH = "Temamir de Jiret-menêsh" -LC_RU.rep.TEMAMIR_OF_JIRET_MENESH = "Темамиры Джирет-Менеша" +LC_EN.rep.KINTAI_OF_SUL_MADASH = "Kintai of Sul Madásh" +LC_DE.rep.KINTAI_OF_SUL_MADASH = "Kintai von Sul Madásh" +LC_FR.rep.KINTAI_OF_SUL_MADASH = "Kintai de Sul Madash" +LC_RU.rep.KINTAI_OF_SUL_MADASH = "Кинтайцы из Сул-Мадаша" LC_EN.rep.HAMAT_RENEWED = "Hamât Renewed" LC_DE.rep.HAMAT_RENEWED = "Das Erneuerte Hamât" @@ -540,4 +540,4 @@ LC_RU.token.HAMATI_URGUL = "Хаматский ургул" LC_EN.token.MUR_GHALA_SARZ = "Mûr Ghala Sârz" LC_DE.token.MUR_GHALA_SARZ = "Sârz von Mûr Ghala" LC_FR.token.MUR_GHALA_SARZ = "Sârz de Mûr Ghala" -LC_RU.token.MUR_GHALA_SARZ = "Mûr Ghala Sârz" +LC_RU.token.MUR_GHALA_SARZ = "TBD" diff --git a/src/LocaleStrings.lua b/src/LocaleStrings.lua index 8e1e44ee..c2ca2520 100644 --- a/src/LocaleStrings.lua +++ b/src/LocaleStrings.lua @@ -7,7 +7,7 @@ import "Turbine.Gameplay"; import "Turbine.UI"; import "Turbine.UI.Lotro"; -Turbine.Language.Russian = 0x10000007 -- removed in Update 22 and again in Update 34 +Turbine.Language.Russian = 0x10000007 -- officially removed in Update 22 and again in Update 34 -- Add detection for the Russian language client Turbine.Engine._GetLanguage = Turbine.Engine.GetLanguage @@ -40,16 +40,20 @@ local LC_RU = Locale[Turbine.Language.Russian] LC_EN.help = "Travel\n\ntrav show: Display the Travel Window\n" .. "trav hide: Hides the Travel Window\n" .. -"trav toggle: Toggle the Travel Window\n" +"trav toggle: Toggle the Travel Window\n" .. +"trav update: Show the update notification window\n" LC_DE.help = "Travel\n\ntrav show: Zeigt das Travel-Fenster an\n" .. "trav hide: Versteckt das Travel-Fenster\n" .. -"trav toggle: Schaltet das Travel-Fenster um\n" +"trav toggle: Schaltet das Travel-Fenster um\n" .. +"trav update: Update-Fenster anzeigen\n" LC_FR.help = "Travel\n\ntrav show: Afficher Travel Window\n" .. "trav hide: Masquer Travel Window\n" .. -"trav toggle: Toggle the Travel Window\n" +"trav toggle: Toggle the Travel Window\n" .. +"trav update: Afficher la fenêtre de actualisation\n" LC_RU.help = "Travel\n\ntrav show: Показать Travel Window\n" .. "trav hide: Спрятать Travel Window\n" .. -"trav toggle: Переключить показ Travel Window\n" +"trav toggle: Переключить показ Travel Window\n" .. +"trav update: Показать окно Обновление\n" -- window title strings LC_EN.mainTitle = "Travel" @@ -93,7 +97,7 @@ LC_DE.sortTab = "Sortierung" LC_FR.sortTab = "Tri" LC_RU.sortTab = "Сортировка" -LC_EN.hide = "Hide Travel window at startup" +LC_EN.hide = "Hide Travel Window at startup" LC_DE.hide = "Verstecke Travel-Fenster beim Start" LC_FR.hide = "Cacher la fenêtre au démarrage" LC_RU.hide = "Убрать окно Travel при старте" @@ -354,45 +358,45 @@ LC_DE.menuPull = "Pulldown-Liste" LC_FR.menuPull = "Menu déroulant" LC_RU.menuPull = "Выпадающий список" -LC_EN.mapWindow = "Maps" -LC_DE.mapWindow = "Karten" -LC_FR.mapWindow = "Destinations" -LC_RU.mapWindow = "Карты" +LC_EN.menuMap = "Map View" +LC_DE.menuMap = "Kartenansicht" +LC_FR.menuMap = "Vue de carte" +LC_RU.menuMap = "Вид карты" LC_EN.menuOptions = "Options" LC_DE.menuOptions = "Optionen" LC_FR.menuOptions = "Options" LC_RU.menuOptions = "Настройки" -LC_EN.moorMap = "Open Moor Map" -LC_DE.moorMap = "Öffne Etten-Karte" -LC_FR.moorMap = "Destinations aux Landes d'Etten" -LC_RU.moorMap = "Открыть Moor Map" +LC_EN.moorMapName = "Ettenmoors" +LC_DE.moorMapName = "Die Ettenöden" +LC_FR.moorMapName = "Les Landes d'Etten" +LC_RU.moorMapName = "Эттенские высоты" -LC_EN.eriadorMap = "Open Eriador Map" -LC_DE.eriadorMap = "Öffne Eriador-Karte" -LC_FR.eriadorMap = "Destinations en Eriador" -LC_RU.eriadorMap = "Открыть карту Эриадора" +LC_EN.eriadorMapName = "Eriador" +LC_DE.eriadorMapName = "Eriador" +LC_FR.eriadorMapName = "Eriador" +LC_RU.eriadorMapName = "Эриадора" -LC_EN.rhovanionMap = "Open Rhovanion Map" -LC_DE.rhovanionMap = "Öffne Rhovanion-Karte" -LC_FR.rhovanionMap = "Destination dans le Rhovanion" -LC_RU.rhovanionMap = "Открыть карту Рованиона" +LC_EN.rhovanionMapName = "Rhovanion" +LC_DE.rhovanionMapName = "Rhovanion" +LC_FR.rhovanionMapName = "Rhovanion" +LC_RU.rhovanionMapName = "Рованиона" -LC_EN.rohanMap = "Open Rohan Map" -LC_DE.rohanMap = "Öffne Rohan-Karte" -LC_FR.rohanMap = "Destinations dans le Rohan" -LC_RU.rohanMap = "Открыть карту Рохана" +LC_EN.rohanMapName = "Rohan" +LC_DE.rohanMapName = "Rohan" +LC_FR.rohanMapName = "Rohan" +LC_RU.rohanMapName = "Рохана" -LC_EN.gondorMap = "Open Gondor Map" -LC_DE.gondorMap = "Öffne Gondor-Karte" -LC_FR.gondorMap = "Destinations dans le Gondor" -LC_RU.gondorMap = "Открыть карту Гондора" +LC_EN.gondorMapName = "Gondor" +LC_DE.gondorMapName = "Gondor" +LC_FR.gondorMapName = "Gondor" +LC_RU.gondorMapName = "Гондора" -LC_EN.haradwaithMap = "Open Haradwaith Map" -LC_DE.haradwaithMap = "Öffne Haradwaith-Karte" -LC_FR.haradwaithMap = "Destinations dans le Haradwaith" -LC_RU.haradwaithMap = "Открыть карту Харадвайта" +LC_EN.haradwaithMapName = "Haradwaith" +LC_DE.haradwaithMapName = "Haradwaith" +LC_FR.haradwaithMapName = "Haradwaith" +LC_RU.haradwaithMapName = "Харадвайта" LC_EN.acquired = "You have acquired the (.*) skill%." LC_DE.acquired = "Ihr habt Euch die Fertigkeit (.*) angeeignet%." @@ -449,6 +453,26 @@ LC_DE.minLevel = "Mindeststufe " LC_FR.minLevel = "Niveau minimum " LC_RU.minLevel = "Минимальный уровень " +LC_EN.updateTitle = "Travel Window II Update" +LC_DE.updateTitle = "Travel Window II Update" +LC_FR.updateTitle = "Travel Window II Actualisation" +LC_RU.updateTitle = "Travel Window II Обновление" + +LC_EN.updateClose = "Close" +LC_DE.updateClose = "Schließen" +LC_FR.updateClose = "Fermer" +LC_RU.updateClose = "Закрыть" + +LC_EN.updateRemindLater = "Show Again Later" +LC_DE.updateRemindLater = "Später wieder anzeigen" +LC_FR.updateRemindLater = "Rappeler plus tard" +LC_RU.updateRemindLater = "Показать позже" + +LC_EN.updateDefaultMessage = "Travel Window II has been updated to" +LC_DE.updateDefaultMessage = "Travel Window II wurde aktualisiert auf" +LC_FR.updateDefaultMessage = "Travel Window II a été mis à jour vers" +LC_RU.updateDefaultMessage = "Travel Window II обновлён до" + -- Verify matched locale keys for lang, _ in pairs(Locale) do for k, _ in pairs(Locale[lang]) do diff --git a/src/Main.lua b/src/Main.lua index ab283e78..72f5fa54 100644 --- a/src/Main.lua +++ b/src/Main.lua @@ -53,12 +53,13 @@ end Plugins["Travel Window II"].Load = function(sender, args) Turbine.Shell.WriteLine("Travel Window II " .. Plugins["Travel Window II"]:GetVersion() .. - " by Hyoss"); + " by Hyoss and Whiterabbit963"); end -- handle unload event and save settings plugin.Unload = function() - SaveSettings(); + SaveSettings(Turbine.DataScope.Account); -- Save account-wide settings (including lastLoadedVersion) + SaveSettings(); -- Save character-specific settings end -- create a new command line command for the travel window @@ -76,6 +77,23 @@ function TravelCommand:Execute(command, arguments) _G.travel:Activate(); elseif (arguments == "scan") then _G.travel:ManualSkillScan(); + elseif (arguments == "update") then + -- Show update notification window + local currentVersion = tostring(Plugins["Travel Window II"]:GetVersion()) + local lastVersion = Settings.lastLoadedVersion or currentVersion + + TravelWindowII.src.UpdateNotificationWindow( + currentVersion, + lastVersion, + function() + -- "Close" button clicked - save new version (account-wide) + Settings.lastLoadedVersion = currentVersion + SaveSettings(Turbine.DataScope.Account) + end, + function() + -- "Show Again Later" clicked - do nothing + end + ) elseif (arguments ~= nil) then TravelCommand:GetHelp(); end diff --git a/src/MapWindow.lua b/src/MapWindow.lua deleted file mode 100644 index 69a74f12..00000000 --- a/src/MapWindow.lua +++ /dev/null @@ -1,255 +0,0 @@ -import "Turbine.Gameplay"; -import "Turbine.UI"; -import "Turbine.UI.Lotro"; -import "TravelWindowII.src.extensions"; -import "TravelWindowII.src.utils.BitOps"; - -MapWindow = class(Turbine.UI.Window); - -MapType = { - NONE = 1, - CREEPS = 2, - ERIADOR = 3, - RHOVANION = 4, - ROHAN = 5, - GONDOR = 6, - HARADWAITH = 7, -}; - -function MapWindow:Constructor(map) - Turbine.UI.Window.Constructor(self); - - -- add a check to see if we load completely - self.loaded = false; - - self.mapType = map; - self.debug = false; -- enable to position shortcuts on the map - - -- set size of window - self.width = 1024; - self.height = 768; - self.windowWidth, self.windowHeight = Turbine.UI.Display:GetSize(); - - -- table of shortcuts - self.quickslots = {}; - - -- set the default window settings - self:SetPosition(self.windowWidth / 2 - self.width / 2, self.windowHeight / 2 - self.height / 2); - self:SetSize(self.width, self.height); - self:SetBlendMode(Turbine.UI.BlendMode.Undefined); - self:SetBackColor(Turbine.UI.Color(0, 0, 0, 0)); - self:SetOpacity(1); - - self.mapLabel = Turbine.UI.Label(); - self.mapLabel:SetSize(1024, 768); - self.mapLabel:SetParent(self); - self.mapLabel:SetVisible(true); - - if self.debug then - self.debugCoords = Turbine.UI.Label(); - self.debugCoords:SetParent(self); - self.debugCoords:SetSize(75, 15); - self.debugCoords:SetPosition(30, 30); - self.debugCoords:SetBackColor(Turbine.UI.Color(1, 0, 0, 0)); - self.debugCoords:SetVisible(true); - - self.debugCoords.MouseClick = function(sender, args) - self.DebugSave(self.quickslots); - end - - self.mapLabel.MouseClick = function(sender, args) - local mX, mY = self:GetMousePosition(); - self.debugCoords:SetText(tostring(mX) .. " x " .. tostring(mY)); - end - - self.mapLabel.DragDrop = function(sender, args) - if self.debugMove then - self.debugMove = false; - -- get dropped location - local mX, mY = self:GetMousePosition(); - mX = mX - self.debugX; - mY = mY - self.debugY; - -- round to nearest multiple of 5 - local adjust = mX % 5; - if adjust > 2 then - adjust = 5 - adjust; - else - adjust = adjust * -1; - end - mX = mX + adjust; - -- round to nearest multiple of 5 - adjust = mY % 5; - if adjust > 2 then - adjust = 5 - adjust; - else - adjust = adjust * -1; - end - mY = mY + adjust; - self.quickslots[self.debugIndex]:SetPosition(mX, mY); - self.debugCoords:SetText(tostring(mX) .. "x" .. tostring(mY)); - end - end - - self.DebugSave = function(quickslots) - local coordinates = {} - for i = 1, #self.quickslots, 1 do - local shortcut = self.quickslots[i]:GetShortcut(); - local name = self:DebugNameLookup(shortcut:GetData()); - coordinates[name] = {self.quickslots[i]:GetPosition()} - end - PatchDataSave(Turbine.DataScope.Character, "TravelWindowIIDebugCoords", coordinates); - end - end - - self.CloseButton=Turbine.UI.Control(); - self.CloseButton:SetParent(self); - self.CloseButton:SetStretchMode(3); - self.CloseButton:SetBackground("TravelWindowII/src/Resources/Close.tga"); - self.CloseButton:SetSize(16, 16); - self.CloseButton:SetPosition(self:GetWidth() - 25, 10); - self.CloseButton.MouseEnter = function() - self.CloseButton:SetBackground("TravelWindowII/src/Resources/Close_hover.tga"); - end - self.CloseButton.MouseLeave = function() - self.CloseButton:SetBackground("TravelWindowII/src/Resources/Close.tga"); - end - self.CloseButton.MouseClick = function() - self:SetVisible(false); - end - - self:SetVisible(true); - - if self.mapType == MapType.ERIADOR then - self.mapLabel:SetBackground(0x41008138); - elseif self.mapType == MapType.RHOVANION then - self.mapLabel:SetBackground(0x411C2DE4); - elseif self.mapType == MapType.ROHAN then - self.mapLabel:SetBackground(0x411c2de5); - elseif self.mapType == MapType.GONDOR then - self.mapLabel:SetBackground(0x41154336); - elseif self.mapType == MapType.HARADWAITH then - self.mapLabel:SetBackground(0x4124bcd0); - elseif self.mapType == MapType.CREEPS then - self.mapLabel:SetBackground(0x41008133); - end - - self:AddShortcuts(); - - self.loaded = true; -end - -function MapWindow:AddShortcuts() - if self.mapType == MapType.CREEPS then - self:AddCreepShortcuts(); - else - self:AddClassLocations(); - self:AddReputationLocations(); - self:AddRacialLocation(); - end -end - -function MapWindow:AddLocations(skills) - local sType = Turbine.UI.Lotro.ShortcutType.Skill; - for i = 1, #skills do - local skill = skills[i]; - if skill.map ~= nil then - for r = 1, #skill.map do - local item = skill.map[r]; - if item ~= nil and #item == 3 and self.mapType == item[1] then - local id = skill.id; - self:AddSingleShortcut(item, Turbine.UI.Lotro.Shortcut(sType, id)); - end - end - end - end -end - -function MapWindow:AddClassLocations() - if PlayerClass == Turbine.Gameplay.Class.Hunter then - self:AddLocations(TravelInfo.hunter.skills); - elseif PlayerClass == Turbine.Gameplay.Class.Warden then - self:AddLocations(TravelInfo.warden.skills); - elseif PlayerClass == Turbine.Gameplay.Class.Mariner then - self:AddLocations(TravelInfo.mariner.skills); - else - -- nothing to add for other classes - return - end -end - -function MapWindow:AddReputationLocations() - self:AddLocations(TravelInfo.rep.skills); -end - -function MapWindow:AddRacialLocation() - local racial = TravelInfo.racial; - if self.mapType == racial.map[1] then - local id = racial.id - if IsShortcutTrained(id) then - local sType = Turbine.UI.Lotro.ShortcutType.Skill; - local shortcut = Turbine.UI.Lotro.Shortcut(sType, id); - self:AddSingleShortcut(racial.map, shortcut); - end - end -end - -function MapWindow:AddCreepShortcuts() - local sType = Turbine.UI.Lotro.ShortcutType.Skill; - local creep = TravelInfo.creep; - for i = 1, #creep.skills do - local map = creep.skills[i].map - local id = creep.skills[i].id; - self:AddSingleShortcut(map[1], Turbine.UI.Lotro.Shortcut(sType, id)); - end -end - -function MapWindow:AddSingleShortcut(location, shortcut) - - local index = #self.quickslots + 1; - self.quickslots[index] = Turbine.UI.Lotro.Quickslot(); - - self.quickslots[index]:SetShortcut(shortcut); - self.quickslots[index]:SetOpacity(1); - self.quickslots[index]:SetParent(self.mapLabel); - self.quickslots[index]:SetMouseVisible(true); - self.quickslots[index]:SetUseOnRightClick(false); - self.quickslots[index]:SetAllowDrop(false); - self.quickslots[index]:SetStretchMode(1); - self.quickslots[index]:SetSize(32, 32); - self.quickslots[index]:SetPosition(location[2], location[3]); - self.quickslots[index]:SetZOrder(98); - self.quickslots[index]:SetVisible(IsShortcutEnabled(shortcut:GetData())); - - self.quickslots[index].MouseClick = function(sender, args) - self:SetVisible(false); - end - - if self.debug then - self.debugMove = false; - self.quickslots[index].MouseDown = function(sender, args) - self.debugMove = true; - self.debugIndex = index; - self.debugX = args.X; - self.debugY = args.Y; - end - end -end - -function MapWindow:UpdateShortcut(id, enable) - for i = 1, #self.quickslots do - if self.quickslots[i]:GetShortcut():GetData() == id then - self.quickslots[i]:SetVisible(enable); - end - end -end - -function MapWindow:DebugNameLookup(id) - for i = 1, #TravelShortcuts, 1 do - local shortcut = TravelShortcuts[i] - if shortcut:GetData() == id then - return shortcut:GetName(); - end - end - - return "ERROR " .. id; -end diff --git a/src/OptionsPanel.lua b/src/OptionsPanel.lua index 18f8188e..8e4bf8b1 100644 --- a/src/OptionsPanel.lua +++ b/src/OptionsPanel.lua @@ -199,7 +199,12 @@ function OptionsPanel:AddMinMaxSliderOption(name, nameMin, nameMax, x, spacerY, self.options[nameMin]:SetParent(self.GeneralTab) self.options[nameMin].ValueChangedFunc = minFunc self.options[nameMin].UpdateOption = function() - self.options[nameMin]:SetValue(Settings[nameMin] * 100) + local value = Settings[nameMin] + if value ~= nil then + self.options[nameMin]:SetValue(value * 100) + else + self.options[nameMin]:SetValue(50) -- Default to 50% if not set + end end self.options[nameMin]:UpdateOption() @@ -220,7 +225,12 @@ function OptionsPanel:AddMinMaxSliderOption(name, nameMin, nameMax, x, spacerY, self.options[nameMax]:SetParent(self.GeneralTab) self.options[nameMax].ValueChangedFunc = maxFunc self.options[nameMax].UpdateOption = function() - self.options[nameMax]:SetValue(Settings[nameMax] * 100) + local value = Settings[nameMax] + if value ~= nil then + self.options[nameMax]:SetValue(value * 100) + else + self.options[nameMax]:SetValue(100) -- Default to 100% if not set + end end self.options[nameMax]:UpdateOption() end diff --git a/src/SettingsMenu.lua b/src/SettingsMenu.lua index 65bcd724..e10cec76 100644 --- a/src/SettingsMenu.lua +++ b/src/SettingsMenu.lua @@ -7,7 +7,7 @@ function SettingsMenu:Constructor(parentWindow) Turbine.UI.ContextMenu.Constructor(self); -- set the default values - self.mode = 1; + self.mode = 2; self.filters = 0x0F; self.parent = parentWindow; @@ -30,21 +30,13 @@ function SettingsMenu:Constructor(parentWindow) self.Mode2 = Turbine.UI.MenuItem(LC.menuIcon); self.Mode3 = Turbine.UI.MenuItem(LC.menuCaro); self.Mode4 = Turbine.UI.MenuItem(LC.menuPull); + self.Mode5 = Turbine.UI.MenuItem(LC.menuMap); local ModeItems = Mode:GetItems(); ModeItems:Add(self.Mode1); ModeItems:Add(self.Mode2); ModeItems:Add(self.Mode3); ModeItems:Add(self.Mode4); - - -- create the items to open the map windows - MoorMapMenu = TravelWindowII.src.extensions.DMenuList(LC.moorMap); - MapWindows = TravelWindowII.src.extensions.DMenuList(LC.mapWindow); - local MapItems = MapWindows:GetItems(); - MapItems:Add(Turbine.UI.MenuItem(LC.eriadorMap)); - MapItems:Add(Turbine.UI.MenuItem(LC.rhovanionMap)); - MapItems:Add(Turbine.UI.MenuItem(LC.rohanMap)); - MapItems:Add(Turbine.UI.MenuItem(LC.gondorMap)); - MapItems:Add(Turbine.UI.MenuItem(LC.haradwaithMap)); + ModeItems:Add(self.Mode5); -- create the menu item to open the options window OptionsMenu = TravelWindowII.src.extensions.DMenuList(LC.menuOptions); @@ -54,11 +46,9 @@ function SettingsMenu:Constructor(parentWindow) if (PlayerAlignment == Turbine.Gameplay.Alignment.MonsterPlayer) then MenuItems:Add(Mode); MenuItems:Add(OptionsMenu); - MenuItems:Add(MoorMapMenu); else MenuItems:Add(Filters); MenuItems:Add(Mode); - MenuItems:Add(MapWindows); MenuItems:Add(OptionsMenu); end @@ -103,6 +93,7 @@ function SettingsMenu:SetSelections() self.Mode2:SetChecked(self.mode == 2); self.Mode3:SetChecked(self.mode == 3); self.Mode4:SetChecked(self.mode == 4); + self.Mode5:SetChecked(self.mode == 5); end -- get the setting from the main window @@ -137,20 +128,10 @@ function SettingsMenu:Update(string) self.mode = 3; elseif (string == LC.menuPull) then self.mode = 4; + elseif (string == LC.menuMap) then + self.mode = 5; elseif (string == LC.menuOptions) then OptionsWindow:SetVisible(true); - elseif (string == LC.moorMap) then - self.parent:OpenMapWindow(MapType.CREEPS); - elseif (string == LC.eriadorMap) then - self.parent:OpenMapWindow(MapType.ERIADOR); - elseif (string == LC.rhovanionMap) then - self.parent:OpenMapWindow(MapType.RHOVANION); - elseif (string == LC.rohanMap) then - self.parent:OpenMapWindow(MapType.ROHAN); - elseif (string == LC.gondorMap) then - self.parent:OpenMapWindow(MapType.GONDOR); - elseif (string == LC.haradwaithMap) then - self.parent:OpenMapWindow(MapType.HARADWAITH); end -- set the selections @@ -195,9 +176,6 @@ function InitDefaultSettings() Settings[k] = v.defValue end end - - -- clear the maps - Settings.mapGlanVraig = nil; end function InitNumberSetting(strTable, name, forceDefault) @@ -249,6 +227,7 @@ function CreateSettingsConfig() AddSettingConfig("escapeToClose", 1) AddSettingConfig("showButton", 1) AddSettingConfig("mode", 2) + AddSettingConfig("mapViewRegion", 3) AddSettingConfig("filters", 0x0F) AddSettingConfig("mainMaxOpacity", 1) AddSettingConfig("mainMinOpacity", 0.5) @@ -333,8 +312,41 @@ function SetSettings(settingsArg, scope, importOldSettings) settingsArg = {}; end + local currentVersion = tostring(Plugins["Travel Window II"]:GetVersion()) + if (not settingsArg.lastLoadedVersion or settingsArg.lastLoadedVersion == "nil") then - settingsArg.lastLoadedVersion = tostring(Plugins["Travel Window II"]:GetVersion()); + -- First time loading - no notification + settingsArg.lastLoadedVersion = currentVersion + else + -- Check if version changed (only show notification for Account scope - account-wide behavior) + if scope == Turbine.DataScope.Account then + local lastVersionNum = GetVersionNumber(settingsArg.lastLoadedVersion) + local currentVersionNum = GetVersionNumber(currentVersion) + + if lastVersionNum < currentVersionNum then + -- Version updated - show notification window + TravelWindowII.src.UpdateNotificationWindow( + currentVersion, + settingsArg.lastLoadedVersion, -- Pass lastVersion for filtering + function() + -- "Close" button clicked - save new version (account-wide) + settingsArg.lastLoadedVersion = currentVersion + Settings.lastLoadedVersion = currentVersion + -- Settings will be saved automatically on plugin unload + end, + function() + -- "Show Again Later" clicked - don't save version + -- Do nothing, version stays as old value + end + ) + else + -- Version same or downgraded (shouldn't happen) - no notification + settingsArg.lastLoadedVersion = currentVersion + end + else + -- For Character scope, just update the version without showing notification + settingsArg.lastLoadedVersion = currentVersion + end end local screenW = Turbine.UI.Display.GetWidth() @@ -364,10 +376,6 @@ function SetSettings(settingsArg, scope, importOldSettings) end end - if (settingsArg.mapGlanVraig ~= nil) then - Settings.mapGlanVraig = settingsArg.mapGlanVraig; - end - if (not settingsArg.enabled or importOldSettings) then settingsArg.enabled = {}; end @@ -376,7 +384,10 @@ function SetSettings(settingsArg, scope, importOldSettings) settingsArg.order = {}; end - Settings.lastLoadedVersion = settingsArg.lastLoadedVersion; + -- Only set Settings.lastLoadedVersion from Account scope (account-wide behavior) + if scope == Turbine.DataScope.Account then + Settings.lastLoadedVersion = settingsArg.lastLoadedVersion; + end LoadEnabled = {} for k, v in pairs(settingsArg.enabled) do @@ -449,14 +460,19 @@ function SaveSettings(scope) end local settingsStrings = {}; - settingsStrings.lastLoadedVersion = Plugins["Travel Window II"]:GetVersion(); + + -- Only save lastLoadedVersion for Account scope (account-wide behavior) + if scope == Turbine.DataScope.Account then + -- Use the version from Settings (may be old if user clicked "Show Again Later") + settingsStrings.lastLoadedVersion = Settings.lastLoadedVersion or Plugins["Travel Window II"]:GetVersion(); + end + for k, v in pairs(SettingsConfig) do if v.save ~= nil then settingsStrings[k] = v.save(Settings[k]) end end - settingsStrings.mapGlanVraig = tostring(Settings.mapGlanVraig); settingsStrings.enabled = GetTravelEnabled(scope); settingsStrings.order = GetTravelOrder(scope); diff --git a/src/SkillData.lua b/src/SkillData.lua index 0261c4b8..d866006c 100644 --- a/src/SkillData.lua +++ b/src/SkillData.lua @@ -766,7 +766,7 @@ function TravelDictionary:CreateDictionaries() acquire={ {cost={{amount=10, token=LC.token.TOKEN_OF_LAKE_AND_RIVERS}}, EN={vendor="Quartermaster (Men of Dale Rewards)"}, - DE={vendor="Quartiermeister (Menschen von Thal - Belohnungen)"}, + DE={vendor="Quartiermeister (Menschen aus Thal - Belohnungen)"}, FR={vendor="Intendant (Récompenses des hommes de Dale)"}, RU={vendor="Интендант (Люди Дейла - награды)"}}, {cost={{amount=10, token=LC.token.TOKEN_OF_LAKE_AND_RIVERS}}, @@ -1174,7 +1174,7 @@ function TravelDictionary:CreateDictionaries() RU={vendor="Интендант Ордена орла"}}, {cost={{amount=10, token=LC.token.LEDGER_KEEPER_MARK}}, EN={vendor="Aphamâr (Allegiance Barterer)"}, - DE={vendor="Aphamâr (Bündnis-Tauschhändlerin)"}, + DE={vendor="Aphamâr (Bündnis-Tauschhändler)"}, FR={vendor="Aphamâr (Négociante d'allégeance)"}, RU={vendor="Афамар (Меновщик альянса)"}}, {cost={{amount=10, token=LC.token.LEDGER_KEEPER_MARK}}, @@ -1298,34 +1298,29 @@ function TravelDictionary:CreateDictionaries() }) self.hunter:AddSkill({ id="0x700706FA", - EN={name="Guide to Sul Madásh"}, - DE={name="Führer nach Sul Madásh"}, - FR={name="Guide vers Sul Madash"}, - RU={name="Guide to Sul Madásh"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Guide to Sul Madásh", label="Sul Madásh", zone="Harad"}, + DE={name="Führer nach Sul Madásh", label="Sul Madásh", zone="Harad"}, + FR={name="Guide vers Sul Madash", label="Sul Madásh", zone="Harad"}, + RU={name="Guide to Sul Madásh", label="Sul Madásh", zone="Harad"}, + map={{MapType.HARADWAITH, 810, 470}}, overlap={"0x70070715"}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, EN={vendor="Kintai Quartermaster"}, DE={vendor="Kintai-Quartiermeister"}, FR={vendor="Intendant des Kintai"}, - RU={vendor="Kintai Quartermaster"}}, - {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, - EN={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}, - DE={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}, - FR={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}, - RU={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}}}, + RU={vendor="Kintai Quartermaster"}}}, rep=LC.rep.KINTAI_OF_SUL_MADASH, repLevel=LC.repLevel.NEUTRAL, minLevel=150, level=150.7 }) self.hunter:AddSkill({ id="0x700706FF", - EN={name="Guide to Ahâba"}, - DE={name="Führer nach Ahâba"}, - FR={name="Guide vers Ahâba"}, - RU={name="Guide to Ahâba"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Guide to Ahâba", label="Ahâba", zone="Harad"}, + DE={name="Führer nach Ahâba", label="Ahâba", zone="Harad"}, + FR={name="Guide vers Ahâba", label="Ahâba", zone="Harad"}, + RU={name="Guide to Ahâba", label="Ahâba", zone="Harad"}, + map={{MapType.HARADWAITH, 560, 570}}, overlap={"0x70070710"}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, @@ -1339,11 +1334,11 @@ function TravelDictionary:CreateDictionaries() }) self.hunter:AddSkill({ id="0x70070717", - EN={name="Guide to Zajâna"}, - DE={name="Führer nach Zajâna"}, - FR={name="Guide vers Zajâna"}, - RU={name="Guide to Zajâna"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Guide to Zajâna", label="Zajâna", zone="Harad"}, + DE={name="Führer nach Zajâna", label="Zajâna", zone="Harad"}, + FR={name="Guide vers Zajâna", label="Zajâna", zone="Harad"}, + RU={name="Guide to Zajâna", label="Zajâna", zone="Harad"}, + map={{MapType.HARADWAITH, 680, 580}}, overlap={"0x70070702"}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, @@ -1357,11 +1352,11 @@ function TravelDictionary:CreateDictionaries() }) self.hunter:AddSkill({ id="0x70070724", - EN={name="Guide to Jiret-menêsh"}, - DE={name="Führer nach Jiret-menêsh"}, - FR={name="Guide vers Jiret-menêsh"}, - RU={name="Guide to Jiret-menêsh"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Guide to Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + DE={name="Führer nach Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + FR={name="Guide vers Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + RU={name="Guide to Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + map={{MapType.HARADWAITH, 630, 530}}, overlap={"0x700706F7"}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, @@ -2003,7 +1998,7 @@ function TravelDictionary:CreateDictionaries() acquire={ {cost={{amount=10, token=LC.token.TOKEN_OF_LAKE_AND_RIVERS}}, EN={vendor="Quartermaster (Men of Dale Rewards)"}, - DE={vendor="Quartiermeister (Menschen von Thal - Belohnungen)"}, + DE={vendor="Quartiermeister (Menschen aus Thal - Belohnungen)"}, FR={vendor="Intendant (Récompenses des hommes de Dale)"}, RU={vendor="Интендант (Люди Дейла - награды)"}}, {cost={{amount=10, token=LC.token.TOKEN_OF_LAKE_AND_RIVERS}}, @@ -2411,7 +2406,7 @@ function TravelDictionary:CreateDictionaries() RU={vendor="Интендант Ордена орла"}}, {cost={{amount=10, token=LC.token.LEDGER_KEEPER_MARK}}, EN={vendor="Aphamâr (Allegiance Barterer)"}, - DE={vendor="Aphamâr (Bündnis-Tauschhändlerin)"}, + DE={vendor="Aphamâr (Bündnis-Tauschhändler)"}, FR={vendor="Aphamâr (Négociante d'allégeance)"}, RU={vendor="Афамар (Меновщик альянса)"}}, {cost={{amount=10, token=LC.token.LEDGER_KEEPER_MARK}}, @@ -2535,11 +2530,11 @@ function TravelDictionary:CreateDictionaries() }) self.warden:AddSkill({ id="0x700706FC", - EN={name="Muster at Jiret-menêsh"}, - DE={name="Appell in Jiret-menêsh"}, - FR={name="Rassemblement à Jiret-menêsh"}, - RU={name="Muster at Jiret-menêsh"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Muster at Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + DE={name="Appell in Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + FR={name="Rassemblement à Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + RU={name="Muster at Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + map={{MapType.HARADWAITH, 630, 530}}, overlap={"0x700706F7"}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, @@ -2553,11 +2548,11 @@ function TravelDictionary:CreateDictionaries() }) self.warden:AddSkill({ id="0x70070714", - EN={name="Muster at Ahâba"}, - DE={name="Appell in Ahâba"}, - FR={name="Rassemblement à Ahâba"}, - RU={name="Muster at Ahâba"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Muster at Ahâba", label="Ahâba", zone="Harad"}, + DE={name="Appell in Ahâba", label="Ahâba", zone="Harad"}, + FR={name="Rassemblement à Ahâba", label="Ahâba", zone="Harad"}, + RU={name="Muster at Ahâba", label="Ahâba", zone="Harad"}, + map={{MapType.HARADWAITH, 560, 570}}, overlap={"0x70070710"}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, @@ -2571,34 +2566,29 @@ function TravelDictionary:CreateDictionaries() }) self.warden:AddSkill({ id="0x70070719", - EN={name="Muster at Sul Madásh"}, - DE={name="Appell in Sul Madásh"}, - FR={name="Rassemblement à Sul Madash"}, - RU={name="Muster at Sul Madásh"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Muster at Sul Madásh", label="Sul Madásh", zone="Harad"}, + DE={name="Appell in Sul Madásh", label="Sul Madásh", zone="Harad"}, + FR={name="Rassemblement à Sul Madash", label="Sul Madásh", zone="Harad"}, + RU={name="Muster at Sul Madásh", label="Sul Madásh", zone="Harad"}, + map={{MapType.HARADWAITH, 810, 470}}, overlap={"0x70070715"}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, EN={vendor="Kintai Quartermaster"}, DE={vendor="Kintai-Quartiermeister"}, FR={vendor="Intendant des Kintai"}, - RU={vendor="Kintai Quartermaster"}}, - {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, - EN={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}, - DE={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}, - FR={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}, - RU={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}}}, + RU={vendor="Kintai Quartermaster"}}}, rep=LC.rep.KINTAI_OF_SUL_MADASH, repLevel=LC.repLevel.NEUTRAL, minLevel=150, level=150.72 }) self.warden:AddSkill({ id="0x7007071F", - EN={name="Muster at Zajâna"}, - DE={name="Appell in Zajâna"}, - FR={name="Rassemblement à Zajâna"}, - RU={name="Muster at Zajâna"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Muster at Zajâna", label="Zajâna", zone="Harad"}, + DE={name="Appell in Zajâna", label="Zajâna", zone="Harad"}, + FR={name="Rassemblement à Zajâna", label="Zajâna", zone="Harad"}, + RU={name="Muster at Zajâna", label="Zajâna", zone="Harad"}, + map={{MapType.HARADWAITH, 680, 580}}, overlap={"0x70070702"}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, @@ -2803,7 +2793,7 @@ function TravelDictionary:CreateDictionaries() acquire={ {cost={{amount=10, token=LC.token.TOKEN_OF_LAKE_AND_RIVERS}}, EN={vendor="Quartermaster (Men of Dale Rewards)"}, - DE={vendor="Quartiermeister (Menschen von Thal - Belohnungen)"}, + DE={vendor="Quartiermeister (Menschen aus Thal - Belohnungen)"}, FR={vendor="Intendant (Récompenses des hommes de Dale)"}, RU={vendor="Интендант (Люди Дейла - награды)"}}, {cost={{amount=10, token=LC.token.TOKEN_OF_LAKE_AND_RIVERS}}, @@ -3024,11 +3014,11 @@ function TravelDictionary:CreateDictionaries() }) self.mariner:AddSkill({ id="0x70070705", - EN={name="Sail to Zajâna"}, - DE={name="Segelt nach Zajâna"}, - FR={name="Naviguez vers Zajâna"}, - RU={name="Sail to Zajâna"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Sail to Zajâna", label="Zajâna", zone="Harad"}, + DE={name="Segelt nach Zajâna", label="Zajâna", zone="Harad"}, + FR={name="Naviguez vers Zajâna", label="Zajâna", zone="Harad"}, + RU={name="Sail to Zajâna", label="Zajâna", zone="Harad"}, + map={{MapType.HARADWAITH, 680, 580}}, overlap={"0x70070702"}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, @@ -3042,11 +3032,11 @@ function TravelDictionary:CreateDictionaries() }) self.mariner:AddSkill({ id="0x70070707", - EN={name="Sail to Jiret-menêsh"}, - DE={name="Segelt nach Jiret-menêsh"}, - FR={name="Naviguez vers Jiret-menêsh"}, - RU={name="Sail to Jiret-menêsh"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Sail to Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + DE={name="Segelt nach Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + FR={name="Naviguez vers Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + RU={name="Sail to Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + map={{MapType.HARADWAITH, 630, 530}}, overlap={"0x700706F7"}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, @@ -3060,23 +3050,18 @@ function TravelDictionary:CreateDictionaries() }) self.mariner:AddSkill({ id="0x70070713", - EN={name="Sail to Sul Madásh"}, - DE={name="Segelt nach Sul Madásh"}, - FR={name="Naviguez vers Sul Madash"}, - RU={name="Sail to Sul Madásh"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Sail to Sul Madásh", label="Sul Madásh", zone="Harad"}, + DE={name="Segelt nach Sul Madásh", label="Sul Madásh", zone="Harad"}, + FR={name="Naviguez vers Sul Madash", label="Sul Madásh", zone="Harad"}, + RU={name="Sail to Sul Madásh", label="Sul Madásh", zone="Harad"}, + map={{MapType.HARADWAITH, 810, 470}}, overlap={"0x70070715"}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, EN={vendor="Kintai Quartermaster"}, DE={vendor="Kintai-Quartiermeister"}, FR={vendor="Intendant des Kintai"}, - RU={vendor="Kintai Quartermaster"}}, - {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, - EN={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}, - DE={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}, - FR={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}, - RU={vendor="Crafting Lore-master (Kintai Advanced Recipes)"}}}, + RU={vendor="Kintai Quartermaster"}}}, rep=LC.rep.KINTAI_OF_SUL_MADASH, repLevel=LC.repLevel.NEUTRAL, minLevel=150, level=150.52 @@ -4103,7 +4088,7 @@ function TravelDictionary:CreateDictionaries() acquire={ {cost={{amount=30, token=LC.token.TOKEN_OF_LAKE_AND_RIVERS}}, EN={vendor="Quartermaster (Men of Dale Rewards)"}, - DE={vendor="Quartiermeister (Menschen von Thal - Belohnungen)"}, + DE={vendor="Quartiermeister (Menschen aus Thal - Belohnungen)"}, FR={vendor="Intendant (Récompenses des hommes de Dale)"}, RU={vendor="Интендант (Люди Дейла - награды)"}}, {cost={{amount=30, token=LC.token.TOKEN_OF_LAKE_AND_RIVERS}}, @@ -4507,7 +4492,7 @@ function TravelDictionary:CreateDictionaries() RU={vendor="Интендант Ордена орла"}}, {cost={{amount=10, token=LC.token.LEDGER_KEEPER_MARK}}, EN={vendor="Aphamâr (Allegiance Barterer)"}, - DE={vendor="Aphamâr (Bündnis-Tauschhändlerin)"}, + DE={vendor="Aphamâr (Bündnis-Tauschhändler)"}, FR={vendor="Aphamâr (Négociante d'allégeance)"}, RU={vendor="Афамар (Меновщик альянса)"}}, {cost={{amount=10, token=LC.token.LEDGER_KEEPER_MARK}}, @@ -4659,11 +4644,11 @@ function TravelDictionary:CreateDictionaries() }) self.rep:AddSkill({ id="0x70070710", - EN={name="Return to Ahâba"}, - DE={name="Rückkehr nach Ahâba"}, - FR={name="Retour à Ahâba"}, - RU={name="Return to Ahâba"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Return to Ahâba", label="Ahâba", zone="Harad"}, + DE={name="Rückkehr nach Ahâba", label="Ahâba", zone="Harad"}, + FR={name="Retour à Ahâba", label="Ahâba", zone="Harad"}, + RU={name="Return to Ahâba", label="Ahâba", zone="Harad"}, + map={{MapType.HARADWAITH, 560, 540}}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, EN={vendor="Hamâti Quartermaster"}, @@ -4676,11 +4661,11 @@ function TravelDictionary:CreateDictionaries() }) self.rep:AddSkill({ id="0x70070702", - EN={name="Return to Zajâna"}, - DE={name="Rückkehr nach Zajâna"}, - FR={name="Retournez voir Zajâna"}, - RU={name="Return to Zajâna"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Return to Zajâna", label="Zajâna", zone="Harad"}, + DE={name="Rückkehr nach Zajâna", label="Zajâna", zone="Harad"}, + FR={name="Retournez voir Zajâna", label="Zajâna", zone="Harad"}, + RU={name="Return to Zajâna", label="Zajâna", zone="Harad"}, + map={{MapType.HARADWAITH, 650, 580}}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, EN={vendor="Zajâna Quartermaster"}, @@ -4693,11 +4678,11 @@ function TravelDictionary:CreateDictionaries() }) self.rep:AddSkill({ id="0x700706F7", - EN={name="Return to Jiret-menêsh"}, - DE={name="Rückkehr nach Jiret-menêsh"}, - FR={name="Retour à Jiret-menêsh"}, - RU={name="Return to Jiret-menêsh"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Return to Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + DE={name="Rückkehr nach Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + FR={name="Retour à Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + RU={name="Return to Jiret-menêsh", label="Jiret-menêsh", zone="Harad"}, + map={{MapType.HARADWAITH, 600, 530}}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, EN={vendor="Temámir Quartermaster"}, @@ -4710,11 +4695,11 @@ function TravelDictionary:CreateDictionaries() }) self.rep:AddSkill({ id="0x70070715", - EN={name="Return to Sul Madásh"}, - DE={name="Rückkehr nach Sul Madásh"}, - FR={name="Retour à Sul Madash"}, - RU={name="Return to Sul Madásh"}, - map={{MapType.HARADWAITH, -1, -1}}, + EN={name="Return to Sul Madásh", label="Sul Madásh", zone="Harad"}, + DE={name="Rückkehr nach Sul Madásh", label="Sul Madásh", zone="Harad"}, + FR={name="Retour à Sul Madash", label="Sul Madásh", zone="Harad"}, + RU={name="Return to Sul Madásh", label="Sul Madásh", zone="Harad"}, + map={{MapType.HARADWAITH, 780, 470}}, acquire={ {cost={{amount=10, token=LC.token.MUR_GHALA_SARZ}}, EN={vendor="Kintai Quartermaster"}, diff --git a/src/TravelCaroTab.lua b/src/TravelCaroTab.lua index bbed08d1..31b59cfb 100644 --- a/src/TravelCaroTab.lua +++ b/src/TravelCaroTab.lua @@ -2,7 +2,6 @@ import "Turbine.Gameplay"; import "Turbine.UI"; import "Turbine.UI.Lotro"; import "TravelWindowII.src.extensions"; -import "TravelWindowII.src.SettingsMenu"; import "TravelWindowII.src.utils.BitOps"; --[[ This is the window for the carousel tab of the ]] -- diff --git a/src/TravelGridTab.lua b/src/TravelGridTab.lua index 7b9e681d..befe4cbf 100644 --- a/src/TravelGridTab.lua +++ b/src/TravelGridTab.lua @@ -2,7 +2,6 @@ import "Turbine.Gameplay"; import "Turbine.UI"; import "Turbine.UI.Lotro"; import "TravelWindowII.src.extensions"; -import "TravelWindowII.src.SettingsMenu"; import "TravelWindowII.src.utils.BitOps"; --[[ This is the window for the icon grid tab of the ]] -- diff --git a/src/TravelListTab.lua b/src/TravelListTab.lua index 33b30dea..70a6ba4c 100644 --- a/src/TravelListTab.lua +++ b/src/TravelListTab.lua @@ -3,7 +3,6 @@ import "Turbine.UI"; import "Turbine.UI.Lotro"; import "TravelWindowII.src.extensions"; import "TravelWindowII.src.TravelGridTab" -import "TravelWindowII.src.SettingsMenu"; import "TravelWindowII.src.utils.FontMetric"; import "TravelWindowII.src.utils.BitOps"; diff --git a/src/TravelMapTab.lua b/src/TravelMapTab.lua new file mode 100644 index 00000000..c29a0758 --- /dev/null +++ b/src/TravelMapTab.lua @@ -0,0 +1,403 @@ +import "Turbine.Gameplay" +import "Turbine.UI" +import "Turbine.UI.Lotro" +import "TravelWindowII.src.extensions" +import "TravelWindowII.src.utils.BitOps" + +--[[ This is the window for the map tab of the Travel UI. ]] -- +--[[ It displays a regional map with travel skill shortcuts ]] -- +--[[ positioned on the map. Users can cycle through regions ]] -- +--[[ using left/right arrow buttons. ]] -- + +-- Map type enumeration (global, used by SkillData and other files) +MapType = { + NONE = 1, + CREEPS = 2, + ERIADOR = 3, + RHOVANION = 4, + ROHAN = 5, + GONDOR = 6, + HARADWAITH = 7, +} + +TravelMapTab = class(Turbine.UI.Control) + +function TravelMapTab:Constructor(toplevel) + Turbine.UI.Control.Constructor(self) + + -- need top level window in order to close it + self.parent = toplevel + + -- Map configuration + self.mapWidth = 1024 + self.mapHeight = 768 + self.navPanelHeight = 65 + self.quickslots = {} + self.panelQuickslots = {} -- For milestone/housing skills in nav panel + + -- Add border padding around map content when using Lotro window + self.mapBorder = (not self.parent.isMinWindow) and 5 or 0 + + -- Set initial region (will be loaded from settings) + if PlayerAlignment == Turbine.Gameplay.Alignment.MonsterPlayer then + self.currentRegion = MapType.CREEPS + self.regions = {MapType.CREEPS} + self.navPanelHeight = 0 + else + self.currentRegion = Settings.mapViewRegion or MapType.ERIADOR + self.regions = { + MapType.ERIADOR, + MapType.RHOVANION, + MapType.ROHAN, + MapType.GONDOR, + MapType.HARADWAITH + } + end + + -- Region names for display (just use simple names) + self.regionNames = { + [MapType.CREEPS] = LC.moorMapName, + [MapType.ERIADOR] = LC.eriadorMapName, + [MapType.RHOVANION] = LC.rhovanionMapName, + [MapType.ROHAN] = LC.rohanMapName, + [MapType.GONDOR] = LC.gondorMapName, + [MapType.HARADWAITH] = LC.haradwaithMapName + } + + -- Create the map display label (full size, no scrolling) + self.mapLabel = Turbine.UI.Label() + self.mapLabel:SetSize(self.mapWidth - (self.mapBorder * 2), self.mapHeight - (self.mapBorder * 2)) + self.mapLabel:SetParent(self) + self.mapLabel:SetVisible(true) + self.mapLabel:SetMouseVisible(true) + self.mapLabel:SetPosition(self.mapBorder, self.mapBorder) + + if self.navPanelHeight ~= 0 then + -- Create navigation panel below the map + self.navPanel = Turbine.UI.Control() + self.navPanel:SetParent(self) + self.navPanel:SetSize(self.mapWidth - (self.mapBorder * 2), self.navPanelHeight) + self.navPanel:SetBackColor(Turbine.UI.Color(0.8, 0, 0, 0)) + self.navPanel:SetZOrder(99) + self.navPanel:SetPosition(self.mapBorder, self.mapHeight + self.mapBorder) -- Position below the map with border + + -- Create 5 region buttons for direct access + self.regionButtons = {} + local buttonWidth = 195 + local buttonHeight = 25 + local spacing = 5 + local totalWidth = (buttonWidth * 5) + (spacing * 4) + local startX = ((self.mapWidth - (self.mapBorder * 2)) - totalWidth) / 2 + local startY = 5 + + -- Button configurations: {region, labelKey} + local buttonConfigs = { + {MapType.ERIADOR, "eriadorMapName"}, + {MapType.RHOVANION, "rhovanionMapName"}, + {MapType.ROHAN, "rohanMapName"}, + {MapType.GONDOR, "gondorMapName"}, + {MapType.HARADWAITH, "haradwaithMapName"} + } + + for i = 1, 5 do + local config = buttonConfigs[i] + local button = Turbine.UI.Lotro.Button() + button:SetParent(self.navPanel) + button:SetSize(buttonWidth, buttonHeight) + button:SetText(LC[config[2]]) + button:SetPosition(startX + ((i - 1) * (buttonWidth + spacing)), startY) + button.region = config[1] + button.Click = function() + self:SwitchRegion(config[1]) + end + self.regionButtons[config[1]] = button + end + end + + -- Show the menu when right clicked + self.MouseClick = function(sender, args) + if (args.Button == Turbine.UI.MouseButton.Right) then + Menu:ShowMenu() + end + end + + self.mapLabel.MouseClick = function(sender, args) + if (args.Button == Turbine.UI.MouseButton.Right) then + Menu:ShowMenu() + end + end + + -- Load the initial map + self:LoadMap() +end + +-- Switch to a specific region +function TravelMapTab:SwitchRegion(newRegion) + if self.currentRegion == newRegion then + return -- Already on this region + end + + self.currentRegion = newRegion + Settings.mapViewRegion = self.currentRegion + + -- Reload map and shortcuts (SetItems will clear old ones) + self:LoadMap() + self:SetItems() +end + +-- Load the map background for current region +function TravelMapTab:LoadMap() + if self.currentRegion == MapType.ERIADOR then + self.mapLabel:SetBackground(0x41008138) + elseif self.currentRegion == MapType.RHOVANION then + self.mapLabel:SetBackground(0x411C2DE4) + elseif self.currentRegion == MapType.ROHAN then + self.mapLabel:SetBackground(0x411c2DE5) + elseif self.currentRegion == MapType.GONDOR then + self.mapLabel:SetBackground(0x41154336) + elseif self.currentRegion == MapType.HARADWAITH then + self.mapLabel:SetBackground(0x4124BCD0) + elseif self.currentRegion == MapType.CREEPS then + self.mapLabel:SetBackground(0x41008133) + end + + -- Highlight current region button + if self.navPanelHeight ~= 0 then + for region, button in pairs(self.regionButtons) do + if region == self.currentRegion then + button:SetEnabled(false) -- Disabled state shows as pressed/selected + else + button:SetEnabled(true) + end + end + end +end + +-- Add shortcuts to the map +function TravelMapTab:SetItems() + if self.tabId ~= self.parent.MainPanel.selectedPage then + return + end + + -- Clear existing shortcuts + self:ClearItems() + + -- Add shortcuts based on current region + if self.currentRegion == MapType.CREEPS then + self:AddCreepShortcuts() + else + self:AddClassLocations() + self:AddReputationLocations() + self:AddRacialLocation() + end + + -- Add milestone/housing skills to navigation panel + -- Only recreate when skills/settings change, not on region switch + if self.parent.dirty then + self:AddPanelQuickslots() + end + + self.parent.dirty = false +end + +-- Clear all quickslots +function TravelMapTab:ClearItems() + for i = 1, #self.quickslots do + self.quickslots[i]:SetVisible(false) + self.quickslots[i]:SetParent(nil) + end + self.quickslots = {} + -- Note: panelQuickslots are NOT cleared here, only in AddPanelQuickslots when dirty +end + +-- Add class-specific locations +function TravelMapTab:AddClassLocations() + if PlayerClass == Turbine.Gameplay.Class.Hunter then + self:AddLocations(TravelInfo.hunter.skills) + elseif PlayerClass == Turbine.Gameplay.Class.Warden then + self:AddLocations(TravelInfo.warden.skills) + elseif PlayerClass == Turbine.Gameplay.Class.Mariner then + self:AddLocations(TravelInfo.mariner.skills) + end +end + +-- Add reputation-based locations +function TravelMapTab:AddReputationLocations() + self:AddLocations(TravelInfo.rep.skills) +end + +-- Add racial location +function TravelMapTab:AddRacialLocation() + local racial = TravelInfo.racial + if racial.map and #racial.map > 0 and racial.map[1] == self.currentRegion then + local id = racial.id + if IsShortcutTrained(id) then + local sType = Turbine.UI.Lotro.ShortcutType.Skill + local shortcut = Turbine.UI.Lotro.Shortcut(sType, id) + self:AddSingleShortcut(racial.map, shortcut) + end + end +end + +-- Add creep shortcuts +function TravelMapTab:AddCreepShortcuts() + local sType = Turbine.UI.Lotro.ShortcutType.Skill + local creep = TravelInfo.creep + for i = 1, #creep.skills do + local map = creep.skills[i].map + local id = creep.skills[i].id + if map and #map > 0 then + self:AddSingleShortcut(map[1], Turbine.UI.Lotro.Shortcut(sType, id)) + end + end +end + +-- Add locations from a skill list +function TravelMapTab:AddLocations(skills) + local sType = Turbine.UI.Lotro.ShortcutType.Skill + for i = 1, #skills do + local skill = skills[i] + if skill.map ~= nil then + for r = 1, #skill.map do + local item = skill.map[r] + if item ~= nil and #item == 3 and self.currentRegion == item[1] then + local id = skill.id + -- Only add shortcut if it's enabled + if IsShortcutEnabled(id) then + self:AddSingleShortcut(item, Turbine.UI.Lotro.Shortcut(sType, id)) + end + end + end + end + end +end + +-- Add a single shortcut to the map +function TravelMapTab:AddSingleShortcut(location, shortcut) + local index = #self.quickslots + 1 + self.quickslots[index] = Turbine.UI.Lotro.Quickslot() + + self.quickslots[index]:SetShortcut(shortcut) + self.quickslots[index]:SetOpacity(1) + self.quickslots[index]:SetParent(self.mapLabel) + self.quickslots[index]:SetMouseVisible(true) + self.quickslots[index]:SetUseOnRightClick(false) + self.quickslots[index]:SetAllowDrop(false) + self.quickslots[index]:SetStretchMode(1) + self.quickslots[index]:SetSize(32, 32) + self.quickslots[index]:SetPosition(location[2], location[3]) + self.quickslots[index]:SetZOrder(98) + self.quickslots[index]:SetVisible(true) + + self.quickslots[index].MouseClick = function(sender, args) + if (args.Button == Turbine.UI.MouseButton.Right) then + Menu:ShowMenu() + else + if (Settings.hideOnTravel == 1) then + self.parent:SetVisible(false) + end + end + end +end + +-- Add milestone/housing skills with no map location to navigation panel +function TravelMapTab:AddPanelQuickslots() + if self.navPanelHeight == 0 then + return -- No panel for monster players + end + + -- Clear existing panel quickslots + for i = 1, #self.panelQuickslots do + self.panelQuickslots[i]:SetParent(nil) + end + self.panelQuickslots = {} + + -- Collect skills with MapType.NONE + local skills = {} + for i = 1, #TravelInfo.gen.skills do + local skill = TravelInfo.gen.skills[i] + if skill.map and #skill.map > 0 then + local mapEntry = skill.map[1] + if mapEntry[1] == MapType.NONE then + local id = skill.id + -- Check if skill is trained and enabled + for j = 1, #TravelShortcuts do + local shortcut = TravelShortcuts[j] + if shortcut:GetData() == id then + if shortcut.found and shortcut:IsEnabled() then + table.insert(skills, {id = id}) + end + break + end + end + end + end + end + + if #skills == 0 then + return -- No skills to display + end + + -- Calculate centered layout + local quickslotSize = 32 + local spacing = 5 + local totalWidth = (#skills * quickslotSize) + ((#skills - 1) * spacing) + local startX = ((self.mapWidth - (self.mapBorder * 2)) - totalWidth) / 2 + local startY = 31 -- Below region buttons (25px tall) + 1px gap, ends at y=63 with 2px bottom padding + + -- Create quickslots + local sType = Turbine.UI.Lotro.ShortcutType.Skill + for i = 1, #skills do + local index = #self.panelQuickslots + 1 + self.panelQuickslots[index] = Turbine.UI.Lotro.Quickslot() + + local shortcut = Turbine.UI.Lotro.Shortcut(sType, skills[i].id) + self.panelQuickslots[index]:SetShortcut(shortcut) + self.panelQuickslots[index]:SetOpacity(1) + self.panelQuickslots[index]:SetParent(self.navPanel) + self.panelQuickslots[index]:SetMouseVisible(true) + self.panelQuickslots[index]:SetUseOnRightClick(false) + self.panelQuickslots[index]:SetAllowDrop(false) + self.panelQuickslots[index]:SetStretchMode(1) + self.panelQuickslots[index]:SetSize(quickslotSize, quickslotSize) + + local posX = startX + ((i - 1) * (quickslotSize + spacing)) + self.panelQuickslots[index]:SetPosition(posX, startY) + self.panelQuickslots[index]:SetZOrder(98) + self.panelQuickslots[index]:SetVisible(true) + + self.panelQuickslots[index].MouseClick = function(sender, args) + if (args.Button == Turbine.UI.MouseButton.Right) then + Menu:ShowMenu() + else + if (Settings.hideOnTravel == 1) then + self.parent:SetVisible(false) + end + end + end + end +end + +-- Handle tab size changes +function TravelMapTab:SetSize(width, height) + Turbine.UI.Control.SetSize(self, width, height) +end + +-- Get pixel size for this tab +function TravelMapTab:GetPixelSize() + local width = self.mapWidth + self.parent.wPadding + (self.mapBorder * 2) + local height = self.mapHeight + self.parent.hPadding + self.navPanelHeight + (self.mapBorder * 2) + return width, height +end + +function TravelMapTab:SetOpacityItems(value) + -- quickslots in stretch mode do not get updated opacity from + -- the parent; update them here + for i = 1, #self.quickslots do + self.quickslots[i]:SetOpacity(value) + end + -- Also update panel quickslots + for i = 1, #self.panelQuickslots do + self.panelQuickslots[i]:SetOpacity(value) + end +end diff --git a/src/TravelPulldownTab.lua b/src/TravelPulldownTab.lua index d2514644..a15a26c9 100644 --- a/src/TravelPulldownTab.lua +++ b/src/TravelPulldownTab.lua @@ -2,7 +2,6 @@ import "Turbine.Gameplay"; import "Turbine.UI"; import "Turbine.UI.Lotro"; import "TravelWindowII.src.extensions"; -import "TravelWindowII.src.SettingsMenu"; import "TravelWindowII.src.utils.BitOps"; import "TravelWindowII.src.OrendarUIMods.ComboBox" diff --git a/src/TravelWindow.lua b/src/TravelWindow.lua index c2b78225..4ef4ed4e 100644 --- a/src/TravelWindow.lua +++ b/src/TravelWindow.lua @@ -1,7 +1,6 @@ import "Turbine.Gameplay"; import "Turbine.UI"; import "Turbine.UI.Lotro"; -import "TravelWindowII.src.MapWindow" import "TravelWindowII.src.extensions"; import "TravelWindowII.src.utils.BitOps"; import "TravelWindowII.src.VindarPatch"; @@ -21,6 +20,14 @@ function TravelWindow:Constructor() Turbine.UI.Lotro.Window.Constructor(self); end + TabId = { + LIST = 1, + GRID = 2, + CARO = 3, + PULL = 4, + MAP = 5, + } + self.fadeOut = false self.levelUpdate = false self.reloadGVMap = false; @@ -53,10 +60,6 @@ function TravelWindow:Constructor() AddCallback(ChatLog, "Received", ChatLogHandler); -- configure the main window - local screenW, screenH = Turbine.UI.Display.GetSize() - local positionX = screenW * Settings.positionRelativeX - local positionY = screenH * Settings.positionRelativeY - self:SetPosition(positionX, positionY) self:SetText(LC.mainTitle); self:SetBackColor(self.backColor); if (Settings.hideOnStart == 1) then @@ -85,16 +88,19 @@ function TravelWindow:Constructor() self.GridTab = TravelGridTab(self); self.CaroTab = TravelCaroTab(self); self.PullTab = TravelPulldownTab(self); + self.MapTab = TravelMapTab(self); -- add the tabs to the panel self.MainPanel:AddTab(self.ListTab); self.MainPanel:AddTab(self.GridTab); self.MainPanel:AddTab(self.CaroTab); self.MainPanel:AddTab(self.PullTab); - self.ListTab.tabId = 1; - self.GridTab.tabId = 2; - self.CaroTab.tabId = 3; - self.PullTab.tabId = 4; + self.MainPanel:AddTab(self.MapTab); + self.ListTab.tabId = TabId.LIST; + self.GridTab.tabId = TabId.GRID; + self.CaroTab.tabId = TabId.CARO; + self.PullTab.tabId = TabId.PULL; + self.MapTab.tabId = TabId.MAP; self.GridTab.numOfCols = Settings.gridCols; self.GridTab.numOfRows = Settings.gridRows; self.ListTab.pixelWidth = Settings.listWidth; @@ -102,6 +108,7 @@ function TravelWindow:Constructor() self.PullTab.pixelWidth = Settings.pullWidth self.MainPanel:SetTab(Settings.mode); + self:SetInitialPosition() self.GridTab:SetAllowDrop(true) self:SetItems(); self:UpdateMinimum(); @@ -132,10 +139,12 @@ function TravelWindow:Constructor() -- check if our position has changed, and save the settings if so self.PositionChanged = function(sender, args) - local w, h = self:GetPosition() - local sw, sh = Turbine.UI.Display.GetSize() - Settings.positionRelativeX = w / sw - Settings.positionRelativeY = h / sh + if Settings.mode ~= TabId.MAP then + local w, h = self:GetPosition() + local sw, sh = Turbine.UI.Display.GetSize() + Settings.positionRelativeX = w / sw + Settings.positionRelativeY = h / sh + end self.PullTab:ClosePulldown() end @@ -146,7 +155,6 @@ function TravelWindow:Constructor() self:SetVisible(false); end OptionsWindow:SetVisible(false); - self:CloseMapWindow(); if (self.hidden == true) then self.hidden = false; self:SetVisible(self.currentVisState); @@ -159,16 +167,10 @@ function TravelWindow:Constructor() self:SetVisible(false); OptionsWindow:SetVisible(false); ToggleButton:SetVisible(false); - if self.mapWindow ~= nil then - self.mapWindow:SetVisible(false); - end else self.hidden = false; self:SetVisible(self.currentVisState); ToggleButton:SetVisible(Settings.showButton == 1); - if self.mapWindow ~= nil then - self.mapWindow:SetVisible(true); - end end end end @@ -279,7 +281,7 @@ function TravelWindow:Constructor() Menu:ShowMenu(); end - if Settings.mode == 4 then + if Settings.mode == TabId.PULL then self.PullTab:ClosePulldown(); end end @@ -308,7 +310,9 @@ function TravelWindow:Constructor() self.isMouseDown = true; if (args.Button == Turbine.UI.MouseButton.Left) then self.dragStartX, self.dragStartY = self:GetMousePosition(); - if Settings.mode == 1 or Settings.mode == 2 or Settings.mode == 4 then + if Settings.mode == TabId.LIST or + Settings.mode == TabId.GRID or + Settings.mode == TabId.PULL then local mX, mY = self:GetMousePosition(); self.resizeStartX, self.resizeStartY = self:GetSize(); if self.resizeStartX - mX < self.resizeLabelSize + 1 and @@ -334,11 +338,11 @@ function TravelWindow:Constructor() local mX, mY = self:GetMousePosition(); sX = self.resizeStartX + (mX - self.dragStartX); sY = self.resizeStartY + (mY - self.dragStartY); - if Settings.mode == 1 then + if Settings.mode == TabId.LIST then sX, sY = self.ListTab:FitToPixels(sX, sY); - elseif Settings.mode == 2 then + elseif Settings.mode == TabId.GRID then sX, sY = self.GridTab:FitToPixels(sX, sY); - elseif Settings.mode == 4 then + elseif Settings.mode == TabId.PULL then sY = self:GetHeight(); self.PullTab.pixelWidth = sX end @@ -374,13 +378,13 @@ function TravelWindow:Constructor() end self.SizeChanged = function(sender, args) - if Settings.mode == 1 then + if Settings.mode == TabId.LIST then Settings.listWidth = self.ListTab.pixelWidth; Settings.listRows = self.ListTab.numOfRows; - elseif Settings.mode == 2 then + elseif Settings.mode == TabId.GRID then Settings.gridCols = self.GridTab.numOfCols; Settings.gridRows = self.GridTab.numOfRows; - elseif Settings.mode == 4 then + elseif Settings.mode == TabId.PULL then Settings.pullWidth = self.PullTab.pixelWidth end self.MainPanel:SetSize(self:GetWidth() - self.wPadding, self:GetHeight() - self.hPadding); @@ -403,11 +407,11 @@ function TravelWindow:Constructor() end end self:SizeChanged(); -- explicitly call to ensure correct positioning - if Settings.mode == 1 then + if Settings.mode == TabId.LIST then self:SetSize(self.ListTab:FitToPixels(self:GetSize())); - elseif Settings.mode == 2 then + elseif Settings.mode == TabId.GRID then self:SetSize(self.GridTab:FitToPixels(self:GetSize())); - elseif Settings.mode == 4 then + elseif Settings.mode == TabId.PULL then self.PullTab.pixelWidth = self:GetWidth() end end @@ -426,28 +430,31 @@ function TravelWindow:FadeOut() end function TravelWindow:SetItems() - if Settings.mode == 1 then + if Settings.mode == TabId.LIST then self:SetSize(self.ListTab:GetPixelSize()); self.ListTab:SetItems(); self:SetSize(self.ListTab:FitToPixels(self:GetSize())); - elseif Settings.mode == 2 then + elseif Settings.mode == TabId.GRID then self:SetSize(self.GridTab:GetPixelSize()); self.GridTab:SetItems(); self:SetSize(self.GridTab:FitToPixels(self:GetSize())); - elseif Settings.mode == 3 then + elseif Settings.mode == TabId.CARO then self.CaroTab:SetItems(); - elseif Settings.mode == 4 then + elseif Settings.mode == TabId.PULL then self.PullTab:SetItems(); self.PullTab.pixelWidth = self:GetWidth() + elseif Settings.mode == TabId.MAP then + self:SetSize(self.MapTab:GetPixelSize()); + self.MapTab:SetItems(); end end function TravelWindow:UpdateMinimum() -- update the page that is showing - if Settings.mode == 1 then + if Settings.mode == TabId.LIST then self.minWidth = self.ListTab.minWidth; self.minHeight = self.ListTab.minHeight; - elseif Settings.mode == 3 then + elseif Settings.mode == TabId.CARO then if self.isMinWindow then self.minWidth = 150; self.minHeight = 75; @@ -455,7 +462,7 @@ function TravelWindow:UpdateMinimum() self.minWidth = 200; self.minHeight = 110; end - elseif Settings.mode == 4 then + elseif Settings.mode == TabId.PULL then if self.isMinWindow then self.minWidth = 360; self.minHeight = 65; @@ -463,6 +470,9 @@ function TravelWindow:UpdateMinimum() self.minWidth = 360; self.minHeight = 105; end + elseif Settings.mode == TabId.MAP then + -- Map view fixed at 1024x768 + padding (nav panel below map) + self.minWidth, self.minHeight = self.MapTab:GetPixelSize() else self.minWidth = 40; self.minHeight = 40; @@ -470,12 +480,27 @@ function TravelWindow:UpdateMinimum() self:SetMinimumSize(self.minWidth, self.minHeight); - if Settings.mode == 3 then + if Settings.mode == TabId.CARO then self:SetSize(self.minWidth, self.minHeight); end - if Settings.mode == 4 then + if Settings.mode == TabId.PULL then self:SetSize(self.PullTab.pixelWidth, self.minHeight) end + if Settings.mode == TabId.MAP then + self:SetSize(self.minWidth, self.minHeight); + end +end + +function TravelWindow:SetInitialPosition() + local screenW, screenH = Turbine.UI.Display.GetSize() + local positionX = screenW * Settings.positionRelativeX + local positionY = screenH * Settings.positionRelativeY + if Settings.mode == TabId.MAP then + local w, h = self.MapTab:GetPixelSize() + positionX = (screenW - w) / 2 + positionY = (screenH - h) / 2 + end + self:SetPosition(positionX, positionY) end function TravelWindow:ReloadLabels() @@ -488,30 +513,16 @@ function TravelWindow:ReloadLabels() end end -function TravelWindow:OpenMapWindow(map) - self:CloseMapWindow(); - self.mapWindow = TravelWindowII.src.MapWindow(map); - self.mapWindow:SetVisible(true); -end - --- function to close the current map window -function TravelWindow:CloseMapWindow() - if (self.mapWindow ~= nil) then - self.mapWindow:SetVisible(false); - self.mapWindow:Close(); - end - self.mapWindow = nil; -end - function TravelWindow:UpdateOpacity() self:SetOpacity(Settings.mainMinOpacity); ToggleButton:UpdateOpacity(); end function TravelWindow:SetOpacity(value) - Turbine.UI.Window.SetOpacity(self, value); - self.CaroTab:SetOpacityItems(value); - self.PullTab:SetOpacity(value); + Turbine.UI.Window.SetOpacity(self, value) + self.CaroTab:SetOpacityItems(value) + self.PullTab:SetOpacity(value) + self.MapTab:SetOpacityItems(value) end function TravelWindow:UpdateSettings() @@ -526,6 +537,7 @@ function TravelWindow:UpdateSettings() -- set which page of the tab panel to show self.MainPanel:SetTab(Settings.mode); self:UpdateMinimum(); + self:SetInitialPosition() self:SetItems(); self.MainPanel:SetSize(self:GetWidth() - self.wPadding, self:GetHeight() - self.hPadding); @@ -552,9 +564,7 @@ function SyncUIFromSettings() OptionsWindow.Panel:EnableFromSettings() OptionsWindow.Panel:AddSortList() Menu:SetSettings(Settings.mode, Settings.filters) - local positionX = screenW * Settings.positionRelativeX - local positionY = screenH * Settings.positionRelativeY - _G.travel:SetPosition(positionX, positionY) + _G.travel:SetInitialPosition() _G.travel.dirty = true _G.travel:UpdateSettings() end diff --git a/src/UpdateNotificationWindow.lua b/src/UpdateNotificationWindow.lua new file mode 100644 index 00000000..81084298 --- /dev/null +++ b/src/UpdateNotificationWindow.lua @@ -0,0 +1,98 @@ +import "Turbine.UI" +import "Turbine.UI.Lotro" +import "TravelWindowII.src.ChangelogData" -- For changelog data + +UpdateNotificationWindow = class(Turbine.UI.Lotro.Window) + +-- Filter and format changelog data for display +function UpdateNotificationWindow:FormatChangelog(lastVersion, currentVersion) + if not ChangelogData or #ChangelogData == 0 then + return LC.updateDefaultMessage .. " " .. currentVersion + end + + local lastVersionNum = GetVersionNumber(lastVersion) + local currentVersionNum = GetVersionNumber(currentVersion) + + local relevantSections = {} + + -- Iterate through changelog entries + for _, entry in ipairs(ChangelogData) do + local versionNum = GetVersionNumber(entry.version) + + -- Include if version is between lastVersion (exclusive) and currentVersion (inclusive) + if versionNum > lastVersionNum and versionNum <= currentVersionNum then + -- Format this version section + local section = "== " .. entry.version .. " ==\n" + for _, change in ipairs(entry.changes) do + section = section .. "- " .. change .. "\n" + end + table.insert(relevantSections, section) + end + end + + -- Combine relevant sections + if #relevantSections > 0 then + return table.concat(relevantSections, "\n") + else + return LC.updateDefaultMessage .. " " .. currentVersion + end +end + +function UpdateNotificationWindow:Constructor(currentVersion, lastVersion, onClose, onRemindLater) + Turbine.UI.Lotro.Window.Constructor(self) + + -- Window properties + self.width = 500 + self.height = 400 + local screenW, screenH = Turbine.UI.Display:GetSize() + + self:SetPosition(screenW / 2 - self.width / 2, screenH / 2 - self.height / 2) + self:SetSize(self.width, self.height) + self:SetText(LC.updateTitle .. " " .. currentVersion) + self:SetZOrder(1000) -- High z-order to appear on top + + -- Format changelog from data table + local changelogText = self:FormatChangelog(lastVersion, currentVersion) + + -- Create scrollable text area for changelog + self.textBox = Turbine.UI.Lotro.TextBox() + self.textBox:SetParent(self) + self.textBox:SetPosition(10, 45) + self.textBox:SetSize(self.width - 30, self.height - 100) + self.textBox:SetMultiline(true) + self.textBox:SetReadOnly(true) + self.textBox:SetText(changelogText) + self.textBox:SetFont(Turbine.UI.Lotro.Font.TrajanPro14) + + -- Create vertical scrollbar for the text area + self.scrollBar = Turbine.UI.Lotro.ScrollBar() + self.scrollBar:SetOrientation(Turbine.UI.Orientation.Vertical) + self.scrollBar:SetParent(self) + self.scrollBar:SetPosition(self.width - 20, 45) + self.scrollBar:SetSize(10, self.height - 100) + self.textBox:SetVerticalScrollBar(self.scrollBar) + + -- Create "Show Again Later" button (doesn't save version) - far left + self.remindButton = Turbine.UI.Lotro.Button() + self.remindButton:SetParent(self) + self.remindButton:SetPosition(10, self.height - 45) + self.remindButton:SetSize(130, 30) + self.remindButton:SetText(LC.updateRemindLater) + self.remindButton.Click = function() + self:SetVisible(false) + if onRemindLater then onRemindLater() end + end + + -- Create "Close" button (saves version) - far right + self.closeButton = Turbine.UI.Lotro.Button() + self.closeButton:SetParent(self) + self.closeButton:SetPosition(self.width - 120, self.height - 45) + self.closeButton:SetSize(110, 30) + self.closeButton:SetText(LC.updateClose) + self.closeButton.Click = function() + self:SetVisible(false) + if onClose then onClose() end + end + + self:SetVisible(true) +end diff --git a/src/__init__.lua b/src/__init__.lua index e3d15552..501d48f6 100644 --- a/src/__init__.lua +++ b/src/__init__.lua @@ -4,6 +4,7 @@ import "TravelWindowII.src.TravelListTab"; import "TravelWindowII.src.TravelGridTab"; import "TravelWindowII.src.TravelCaroTab"; import "TravelWindowII.src.TravelPulldownTab" +import "TravelWindowII.src.TravelMapTab" import "TravelWindowII.src.IndexedDictionary" import "TravelWindowII.src.TravelDictionary" import "TravelWindowII.src.SkillData" @@ -13,5 +14,7 @@ import "TravelWindowII.src.TravelShortcut"; import "TravelWindowII.src.OptionsWindow"; import "TravelWindowII.src.TravelButton"; -- import "TravelWindowII.src.TravelTests"; -import "TravelWindowII.src.MapWindow"; +import "TravelWindowII.src.SettingsMenu"; import "TravelWindowII.src.OptionsPanel"; +import "TravelWindowII.src.ChangelogData"; +import "TravelWindowII.src.UpdateNotificationWindow";