diff --git a/data/cdata/ui_scripts/achievements/__init__.lua b/data/cdata/ui_scripts/achievements/__init__.lua index 15df206b..3e0ad2bd 100644 --- a/data/cdata/ui_scripts/achievements/__init__.lua +++ b/data/cdata/ui_scripts/achievements/__init__.lua @@ -1,196 +1,2 @@ -if (Engine.InFrontend()) then - return -end - -local hud = LUI.UIElement.new({ - topAnchor = true, - leftAnchor = true, - width = 500, - height = 500, - left = 0 -}) - -local hidetimer = LUI.UITimer.new(5000, "hide_toast") -local finishtimer = LUI.UITimer.new(6000, "notification_finished") -local animtime = 250 - -hud:setPriority(1000) - -local isshowingachievement = false -local notificationqueue = {} -local shownotificationinternal = nil - -local shownextnotification = function() - isshowingachievement = false - local data = notificationqueue[1] - if (data == nil) then - return - end - - table.remove(notificationqueue, 1) - shownotificationinternal(data) -end - -local createtoast = function() - local height = 80 - local width = 400 - local padding = 10 - local leftoffset = 10 - - local titlefont = CoD.TextSettings.Font27 - local descfont = CoD.TextSettings.Font21 - - local imagesize = height - padding * 2 - local textoffset = padding * 2 + imagesize - local textyoffset = height / 2 - (titlefont.Height + descfont.Height) / 2 - local text2yoffset = 5 - - local container = LUI.UIElement.new({ - topAnchor = true, - leftAnchor = true, - top = 100, - left = 0, - width = width, - height = height - }) - - container:registerAnimationState("hide", { - topAnchor = true, - leftAnchor = true, - top = 100, - left = -1000, - width = width, - height = height - }) - - container:registerAnimationState("show", { - topAnchor = true, - leftAnchor = true, - top = 100, - left = 0, - width = width, - height = height - }) - - container:registerAnimationState("show_right", { - topAnchor = true, - leftAnchor = true, - top = 100, - left = 40, - width = width, - height = height - }) - - local bg = LUI.UIImage.new({ - topAnchor = true, - leftAnchor = true, - rightAnchor = true, - bottomAnchor = true, - color = { - r = 0.1, - g = 0.1, - b = 0.1, - }, - alpha = 0.55 - }) - - local image = LUI.UIImage.new({ - topAnchor = true, - leftAnchor = true, - top = padding, - left = padding + leftoffset, - width = imagesize, - height = imagesize, - }) - - local title = LUI.UIText.new({ - topAnchor = true, - leftAnchor = true, - top = textyoffset, - left = textoffset + leftoffset, - font = titlefont.Font, - height = titlefont.Height - }) - - local desc = LUI.UIText.new({ - topAnchor = true, - leftAnchor = true, - width = width - textoffset - leftoffset - padding, - alignment = LUI.Alignment.Left, - top = textyoffset + titlefont.Height + text2yoffset, - left = textoffset + leftoffset, - font = descfont.Font, - height = descfont.Height - }) - - container:addElement(bg) - container:addElement(image) - container:addElement(title) - container:addElement(desc) - container:addElement(LUI.DecoFrame.new(nil, LUI.DecoFrame.Grey)) - - container:animateToState("hide") - - container:addElement(hidetimer) - container:addElement(finishtimer) - - container:registerEventHandler("hide_toast", function() - LUI.UITimer.Stop(hidetimer) - container:animateToState("hide", animtime) - end) - - container:registerEventHandler("notification_finished", function() - LUI.UITimer.Stop(finishtimer) - shownextnotification() - end) - - hud:addElement(container) - - container.image = image - container.title = title - container.desc = desc - - return container -end - -local toast = createtoast() - -shownotificationinternal = function(data) - isshowingachievement = true - - LUI.UITimer.Reset(hidetimer) - LUI.UITimer.Reset(finishtimer) - - toast:animateToState("hide") - toast:animateToState("show", animtime) - - toast.title:setText(data.title) - toast.desc:setText(data.description) - toast.image:setImage(data.image) - - if (data.sound) then - Engine.PlaySound(data.sound) - end -end - -function addnotification(data) - table.insert(notificationqueue, data) - if (not isshowingachievement) then - shownextnotification() - end -end - -local addachievementnotification = function(id) - addnotification({ - title = Engine.Localize("ACHIEVEMENT_EARNED"), - description = Engine.ToUpperCase(Engine.Localize("ACHIEVEMENT_NAME_" .. id)), - image = RegisterMaterial("trophy_" .. id), - sound = "ui_achievement_unlocked" - }) -end - -hud:registerEventHandler("earned_achievement", function(element, event) - addachievementnotification(event.id) -end) - -LUI.roots.UIRoot0:addElement(hud) \ No newline at end of file +require("toast") +require("menu") diff --git a/data/cdata/ui_scripts/achievements/menu.lua b/data/cdata/ui_scripts/achievements/menu.lua new file mode 100644 index 00000000..35b07940 --- /dev/null +++ b/data/cdata/ui_scripts/achievements/menu.lua @@ -0,0 +1,319 @@ +local maincampaign = LUI.MenuBuilder.m_types_build["main_campaign"] +LUI.MenuBuilder.m_types_build["main_campaign"] = function(...) + local initlist = LUI.Options.InitScrollingList + LUI.Options.InitScrollingList = function(list) + initlist(list, nil ,{ + rows = 10 + }) + end + + local menu = maincampaign(...) + LUI.Options.InitScrollingList = initlist + return menu +end + +LUI.MenuBuilder.registerType("achievements_menu", function(root, controller) + local menuwidth = 1129 + local menu = LUI.MenuTemplate.new(root, { + menu_title = "@LUA_MENU_ACHIEVEMENTS", + exclusiveController = 0, + menu_width = menuwidth, + menu_top_indent = LUI.MenuTemplate.spMenuOffset, + showTopRightSmallBar = true, + uppercase_title = true + }) + + local itemwidth = 80 + local itemspacing = 10 + local maxrowelements = 1 + + local rowelements = 0 + local newrow = function() + local currentrow = LUI.UIElement.new({ + topAnchor = true, + leftAnchor = true, + width = itemwidth * maxrowelements, + height = itemwidth, + }) + + menu.list.currentrow = currentrow + menu.list:addElement(currentrow) + menu.list.currentrow:makeFocusable() + + end + + newrow() + + local addelement = function(element) + local container = LUI.UIElement.new({ + topAnchor = true, + leftAnchor = true, + width = itemwidth, + height = itemwidth, + left = rowelements * (itemwidth + itemspacing) + }) + container:addElement(element) + container:makeFocusable() + menu.list.currentrow:addElement(container) + rowelements = rowelements + 1 + if (rowelements == maxrowelements) then + newrow() + rowelements = 0 + end + end + + local achievementtable = achievements.table() + local unlockcount = 0 + for i = 0, #achievementtable do + if (achievementtable[i]) then + unlockcount = unlockcount + 1 + end + end + + for i = 0, achievements.count() - 1 do + local trophyimage = LUI.UIImage.new({ + topAnchor = true, + leftAnchor = true, + width = menuwidth, + height = itemwidth, + material = RegisterMaterial("h2_btn_unfocused") + }) + + trophyimage:setup9SliceImage() + + trophyimage:registerAnimationState("locked", { + material = RegisterMaterial("h2_btn_unfocused_locked") + }) + + local stroke = LUI.UIImage.new({ + topAnchor = true, + leftAnchor = true, + width = menuwidth, + height = itemwidth, + material = RegisterMaterial("h2_btn_focused_stroke") + }) + + stroke:registerAnimationState("hide", { + alpha = 0 + }) + + stroke:registerAnimationState("show", { + alpha = 1 + }) + + stroke:setup9SliceImage() + + local glow = LUI.UIImage.new({ + topAnchor = true, + leftAnchor = true, + left = -20, + top = -20, + width = menuwidth + 40, + height = itemwidth + 40, + material = RegisterMaterial("h2_btn_focused_outerglow") + }) + + glow:registerAnimationState("hide", { + alpha = 0 + }) + + glow:registerAnimationState("show", { + alpha = 1 + }) + + glow:setup9SliceImage() + + local pattern = LUI.UIImage.new({ + topAnchor = true, + leftAnchor = true, + width = menuwidth, + height = itemwidth, + material = RegisterMaterial("h2_btn_dot_pattern") + }) + + pattern:registerAnimationState("hide", { + alpha = 0 + }) + + pattern:registerAnimationState("show", { + alpha = 1 + }) + + stroke:animateToState("hide") + pattern:animateToState("hide") + glow:animateToState("hide") + + local achievementcontainer = LUI.UIElement.new({ + topAnchor = true, + leftAnchor = true, + width = menuwidth, + height = itemwidth, + }) + + local image = LUI.UIImage.new({ + topAnchor = true, + leftAnchor = true, + top = itemspacing / 2, + left = itemspacing / 2, + width = itemwidth - itemspacing, + height = itemwidth - itemspacing, + material = RegisterMaterial("trophy_" .. i) + }) + + image:registerAnimationState("locked", { + topAnchor = true, + leftAnchor = true, + top = itemspacing / 2 + 15, + left = itemspacing / 2 + 15, + width = itemwidth - itemspacing - 30, + height = itemwidth - itemspacing - 30, + material = RegisterMaterial("icon_lock_mini") + }) + + local textwidth = menuwidth - itemwidth - itemspacing * 2 + local title = LUI.UIText.new({ + topAnchor = true, + leftAnchor = true, + top = itemspacing + 5, + left = itemwidth + 5, + color = { + r = 0.7, + g = 0.7, + b = 0.7, + }, + width = textwidth, + font = CoD.TextSettings.Font23.Font, + height = CoD.TextSettings.Font23.Height + }) + + local desc = LUI.UIText.new({ + topAnchor = true, + leftAnchor = true, + top = itemspacing + CoD.TextSettings.Font23.Height + 10, + left = itemwidth + 5, + width = textwidth, + alignment = LUI.Alignment.Left, + color = { + r = 0.7, + g = 0.7, + b = 0.7, + }, + font = CoD.TextSettings.Font21.Font, + height = CoD.TextSettings.Font21.Height + }) + + local focusedtext = { + color = {r = 1, g = 1, b = 1} + } + desc:registerAnimationState("focused", focusedtext) + title:registerAnimationState("focused", focusedtext) + + title:setText(Engine.ToUpperCase(Engine.Localize(achievements.getname(i)))) + desc:setText(Engine.Localize(achievements.getdetails(i))) + + achievementcontainer:setHandleMouse(true) + local locked = not achievementtable[i] + + achievementcontainer:registerEventHandler("mouseenter", function() + Engine.PlaySound(CoD.SFX.MouseOver) + + if (locked) then + trophyimage:setImage(RegisterMaterial("h2_btn_focused_locked")) + else + stroke:animateToState("show") + pattern:animateToState("show") + title:animateToState("focused") + desc:animateToState("focused") + glow:animateToState("show") + end + end) + achievementcontainer:registerEventHandler("mouseleave", function() + if (locked) then + trophyimage:setImage(RegisterMaterial("h2_btn_unfocused_locked")) + else + stroke:animateToState("hide") + pattern:animateToState("hide") + title:animateToState("default") + desc:animateToState("default") + glow:animateToState("hide") + end + end) + + achievementcontainer:addElement(trophyimage) + achievementcontainer:addElement(pattern) + achievementcontainer:addElement(glow) + achievementcontainer:addElement(stroke) + achievementcontainer:addElement(image) + achievementcontainer:addElement(title) + achievementcontainer:addElement(desc) + + if (locked) then + trophyimage:animateToState("locked") + image:animateToState("locked") + title:setText(Engine.Localize("@LUA_MENU_UNKNOWN_ACHIEVEMENT")) + desc:setText("") + end + + addelement(achievementcontainer) + end + + if (rowelements == 0) then + menu.list.currentrow:close() + end + + LUI.Options.InitScrollingList(menu.list, nil, { + rows = 5 + }) + + local createprogressbar = function() + local barwidth = menuwidth + 17 + local progressbar = LUI.UIElement.new({ + bottomAnchor = true, + leftAnchor = true, + width = barwidth, + bottom = -90, + height = 15 + }) + + local bg = LUI.UIImage.new({ + topAnchor = true, + leftAnchor = true, + rightAnchor = true, + bottomAnchor = true, + alpha = 0.55, + color = Colors.grey_14, + }) + + local bar = LUI.UIImage.new({ + topAnchor = true, + leftAnchor = true, + bottomAnchor = true, + width = 0, + material = RegisterMaterial("h1_ui_progressbar_green") + }) + + progressbar.setprogress = function(fraction) + bar:registerAnimationState("progress", { + topAnchor = true, + leftAnchor = true, + bottomAnchor = true, + width = fraction * (barwidth), + }) + + bar:animateToState("progress", 300) + end + + progressbar.setprogress(unlockcount / achievements.count()) + + progressbar:addElement(bg) + progressbar:addElement(bar) + progressbar:addElement(LUI.DecoFrame.new(nil, LUI.DecoFrame.Grey)) + + return progressbar + end + + menu:addElement(createprogressbar()) + menu:AddBackButton() + + return menu +end) diff --git a/data/cdata/ui_scripts/achievements/toast.lua b/data/cdata/ui_scripts/achievements/toast.lua new file mode 100644 index 00000000..b6a919aa --- /dev/null +++ b/data/cdata/ui_scripts/achievements/toast.lua @@ -0,0 +1,203 @@ +if (Engine.InFrontend()) then + return +end + +local hud = LUI.UIElement.new({ + topAnchor = true, + leftAnchor = true, + width = 500, + height = 500, + left = 0 +}) + +local hidetimer = LUI.UITimer.new(5000, "hide_toast") +local finishtimer = LUI.UITimer.new(6000, "notification_finished") +local animtime = 250 + +hud:setPriority(1000) + +local isshowingachievement = false +local notificationqueue = {} +local shownotificationinternal = nil + +local shownextnotification = function() + isshowingachievement = false + local data = notificationqueue[1] + if (data == nil) then + return + end + + table.remove(notificationqueue, 1) + shownotificationinternal(data) +end + +local createtoast = function() + local height = 80 + local width = 400 + local padding = 10 + local leftoffset = 10 + + local titlefont = CoD.TextSettings.Font27 + local descfont = CoD.TextSettings.Font21 + + local imagesize = height - padding * 2 + local textoffset = padding * 2 + imagesize + local textyoffset = height / 2 - (titlefont.Height + descfont.Height) / 2 + local text2yoffset = 5 + + local container = LUI.UIElement.new({ + topAnchor = true, + leftAnchor = true, + top = 100, + left = 0, + width = width, + height = height + }) + + container:registerAnimationState("hide", { + topAnchor = true, + leftAnchor = true, + top = 100, + left = -1000, + width = width, + height = height + }) + + container:registerAnimationState("show", { + topAnchor = true, + leftAnchor = true, + top = 100, + left = 0, + width = width, + height = height + }) + + container:registerAnimationState("show_right", { + topAnchor = true, + leftAnchor = true, + top = 100, + left = 40, + width = width, + height = height + }) + + local bg = LUI.UIImage.new({ + topAnchor = true, + leftAnchor = true, + rightAnchor = true, + bottomAnchor = true, + alpha = 0.55, + color = Colors.grey_14, + }) + + local imagebg = LUI.UIImage.new({ + topAnchor = true, + leftAnchor = true, + top = padding, + left = padding + leftoffset, + width = imagesize, + height = imagesize, + material = RegisterMaterial("trophy_border") + }) + + local image = LUI.UIImage.new({ + topAnchor = true, + leftAnchor = true, + top = padding, + left = padding + leftoffset, + width = imagesize, + height = imagesize, + }) + + local title = LUI.UIText.new({ + topAnchor = true, + leftAnchor = true, + top = textyoffset, + left = textoffset + leftoffset, + font = titlefont.Font, + height = titlefont.Height + }) + + local desc = LUI.UIText.new({ + topAnchor = true, + leftAnchor = true, + width = width - textoffset - leftoffset - padding, + alignment = LUI.Alignment.Left, + top = textyoffset + titlefont.Height + text2yoffset, + left = textoffset + leftoffset, + font = descfont.Font, + height = descfont.Height + }) + + container:addElement(bg) + container:addElement(imagebg) + container:addElement(image) + container:addElement(title) + container:addElement(desc) + container:addElement(LUI.DecoFrame.new(nil, LUI.DecoFrame.Grey)) + + container:animateToState("hide") + + container:addElement(hidetimer) + container:addElement(finishtimer) + + container:registerEventHandler("hide_toast", function() + LUI.UITimer.Stop(hidetimer) + container:animateToState("hide", animtime) + end) + + container:registerEventHandler("notification_finished", function() + LUI.UITimer.Stop(finishtimer) + shownextnotification() + end) + + hud:addElement(container) + + container.image = image + container.title = title + container.desc = desc + + return container +end + +local toast = createtoast() + +shownotificationinternal = function(data) + isshowingachievement = true + + LUI.UITimer.Reset(hidetimer) + LUI.UITimer.Reset(finishtimer) + + toast:animateToState("hide") + toast:animateToState("show", animtime) + + toast.title:setText(data.title) + toast.desc:setText(data.description) + toast.image:setImage(data.image) + + if (data.sound) then + Engine.PlaySound(data.sound) + end +end + +function addnotification(data) + table.insert(notificationqueue, data) + if (not isshowingachievement) then + shownextnotification() + end +end + +local addachievementnotification = function(id) + addnotification({ + title = Engine.Localize("ACHIEVEMENT_EARNED"), + description = Engine.ToUpperCase(Engine.Localize("ACHIEVEMENT_NAME_" .. id)), + image = RegisterMaterial("trophy_" .. id), + sound = "ui_achievement_unlocked" + }) +end + +hud:registerEventHandler("earned_achievement", function(element, event) + addachievementnotification(event.id) +end) + +LUI.roots.UIRoot0:addElement(hud) \ No newline at end of file diff --git a/data/cdata/ui_scripts/mods/loading.lua b/data/cdata/ui_scripts/mods/loading.lua index dff0c811..e940e52d 100644 --- a/data/cdata/ui_scripts/mods/loading.lua +++ b/data/cdata/ui_scripts/mods/loading.lua @@ -29,6 +29,15 @@ function string:truncate(length) return self:sub(1, length - 3) .. "..." end +LUI.addmenubutton("main_campaign", { + index = 6, + text = "@LUA_MENU_ACHIEVEMENTS", + description = Engine.Localize("@LUA_MENU_ACHIEVEMENTS_DESC"), + callback = function() + LUI.FlowManager.RequestAddMenu(nil, "achievements_menu") + end +}) + LUI.addmenubutton("main_campaign", { index = 6, text = "@MENU_MODS", diff --git a/data/zonetool/h2_mod_ui/images/trophy_0.dds b/data/zonetool/h2_mod_ui/images/trophy_0.dds index f2c794da..2f223e61 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_0.dds and b/data/zonetool/h2_mod_ui/images/trophy_0.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_1.dds b/data/zonetool/h2_mod_ui/images/trophy_1.dds index f1337327..0bfdc771 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_1.dds and b/data/zonetool/h2_mod_ui/images/trophy_1.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_10.dds b/data/zonetool/h2_mod_ui/images/trophy_10.dds index 937c3e68..9ccacd8a 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_10.dds and b/data/zonetool/h2_mod_ui/images/trophy_10.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_11.dds b/data/zonetool/h2_mod_ui/images/trophy_11.dds index ac758314..1bd4d3c7 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_11.dds and b/data/zonetool/h2_mod_ui/images/trophy_11.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_12.dds b/data/zonetool/h2_mod_ui/images/trophy_12.dds index 522cc3cf..ea4f219f 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_12.dds and b/data/zonetool/h2_mod_ui/images/trophy_12.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_13.dds b/data/zonetool/h2_mod_ui/images/trophy_13.dds index dcfe720a..ce3c260a 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_13.dds and b/data/zonetool/h2_mod_ui/images/trophy_13.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_14.dds b/data/zonetool/h2_mod_ui/images/trophy_14.dds index 71297720..74f2aa19 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_14.dds and b/data/zonetool/h2_mod_ui/images/trophy_14.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_15.dds b/data/zonetool/h2_mod_ui/images/trophy_15.dds index eb89330c..7e132b2a 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_15.dds and b/data/zonetool/h2_mod_ui/images/trophy_15.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_16.dds b/data/zonetool/h2_mod_ui/images/trophy_16.dds index ee4d782e..b58b4089 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_16.dds and b/data/zonetool/h2_mod_ui/images/trophy_16.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_17.dds b/data/zonetool/h2_mod_ui/images/trophy_17.dds index 4235463c..5b66a8f9 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_17.dds and b/data/zonetool/h2_mod_ui/images/trophy_17.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_18.dds b/data/zonetool/h2_mod_ui/images/trophy_18.dds index e07130d9..362b5893 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_18.dds and b/data/zonetool/h2_mod_ui/images/trophy_18.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_19.dds b/data/zonetool/h2_mod_ui/images/trophy_19.dds index 205c012c..aed97df1 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_19.dds and b/data/zonetool/h2_mod_ui/images/trophy_19.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_2.dds b/data/zonetool/h2_mod_ui/images/trophy_2.dds index b1d53864..b7a2acae 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_2.dds and b/data/zonetool/h2_mod_ui/images/trophy_2.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_20.dds b/data/zonetool/h2_mod_ui/images/trophy_20.dds index 4197056f..f229d041 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_20.dds and b/data/zonetool/h2_mod_ui/images/trophy_20.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_21.dds b/data/zonetool/h2_mod_ui/images/trophy_21.dds index 478a878e..da207c20 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_21.dds and b/data/zonetool/h2_mod_ui/images/trophy_21.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_22.dds b/data/zonetool/h2_mod_ui/images/trophy_22.dds index 979292a3..7f0d11c5 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_22.dds and b/data/zonetool/h2_mod_ui/images/trophy_22.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_23.dds b/data/zonetool/h2_mod_ui/images/trophy_23.dds index 059ccd72..ffb5cb9d 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_23.dds and b/data/zonetool/h2_mod_ui/images/trophy_23.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_24.dds b/data/zonetool/h2_mod_ui/images/trophy_24.dds index a88b1ee3..49b76a93 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_24.dds and b/data/zonetool/h2_mod_ui/images/trophy_24.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_25.dds b/data/zonetool/h2_mod_ui/images/trophy_25.dds index 9fda4441..97270e16 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_25.dds and b/data/zonetool/h2_mod_ui/images/trophy_25.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_26.dds b/data/zonetool/h2_mod_ui/images/trophy_26.dds index bf113a4f..f3cd36ea 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_26.dds and b/data/zonetool/h2_mod_ui/images/trophy_26.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_27.dds b/data/zonetool/h2_mod_ui/images/trophy_27.dds index 1a1bf0b0..c9d9ecf3 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_27.dds and b/data/zonetool/h2_mod_ui/images/trophy_27.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_28.dds b/data/zonetool/h2_mod_ui/images/trophy_28.dds index 2d576f86..86771651 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_28.dds and b/data/zonetool/h2_mod_ui/images/trophy_28.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_29.dds b/data/zonetool/h2_mod_ui/images/trophy_29.dds index 256e2ac6..121300bb 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_29.dds and b/data/zonetool/h2_mod_ui/images/trophy_29.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_3.dds b/data/zonetool/h2_mod_ui/images/trophy_3.dds index e9674a01..312eba3b 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_3.dds and b/data/zonetool/h2_mod_ui/images/trophy_3.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_30.dds b/data/zonetool/h2_mod_ui/images/trophy_30.dds index 9f801ac2..d09f1ff1 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_30.dds and b/data/zonetool/h2_mod_ui/images/trophy_30.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_31.dds b/data/zonetool/h2_mod_ui/images/trophy_31.dds index 907b14f9..b786c305 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_31.dds and b/data/zonetool/h2_mod_ui/images/trophy_31.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_32.dds b/data/zonetool/h2_mod_ui/images/trophy_32.dds index ec9e3db7..e454de31 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_32.dds and b/data/zonetool/h2_mod_ui/images/trophy_32.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_33.dds b/data/zonetool/h2_mod_ui/images/trophy_33.dds index f3c50064..79d7aed1 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_33.dds and b/data/zonetool/h2_mod_ui/images/trophy_33.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_34.dds b/data/zonetool/h2_mod_ui/images/trophy_34.dds index 23b989a2..8632404a 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_34.dds and b/data/zonetool/h2_mod_ui/images/trophy_34.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_35.dds b/data/zonetool/h2_mod_ui/images/trophy_35.dds index 55b66065..c9bfb76b 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_35.dds and b/data/zonetool/h2_mod_ui/images/trophy_35.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_36.dds b/data/zonetool/h2_mod_ui/images/trophy_36.dds index 9bd03f2e..09761390 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_36.dds and b/data/zonetool/h2_mod_ui/images/trophy_36.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_37.dds b/data/zonetool/h2_mod_ui/images/trophy_37.dds index b0283485..238f18aa 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_37.dds and b/data/zonetool/h2_mod_ui/images/trophy_37.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_38.dds b/data/zonetool/h2_mod_ui/images/trophy_38.dds index 78f12244..97534e23 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_38.dds and b/data/zonetool/h2_mod_ui/images/trophy_38.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_39.dds b/data/zonetool/h2_mod_ui/images/trophy_39.dds index 61cd8e27..07d91323 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_39.dds and b/data/zonetool/h2_mod_ui/images/trophy_39.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_4.dds b/data/zonetool/h2_mod_ui/images/trophy_4.dds index e90bb449..593b4009 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_4.dds and b/data/zonetool/h2_mod_ui/images/trophy_4.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_40.dds b/data/zonetool/h2_mod_ui/images/trophy_40.dds index b9ec29ab..6309ce6f 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_40.dds and b/data/zonetool/h2_mod_ui/images/trophy_40.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_41.dds b/data/zonetool/h2_mod_ui/images/trophy_41.dds index 0d32c621..fddfd0d4 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_41.dds and b/data/zonetool/h2_mod_ui/images/trophy_41.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_42.dds b/data/zonetool/h2_mod_ui/images/trophy_42.dds index 40055e81..14a4b1e1 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_42.dds and b/data/zonetool/h2_mod_ui/images/trophy_42.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_43.dds b/data/zonetool/h2_mod_ui/images/trophy_43.dds index a25d9bd5..541c0701 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_43.dds and b/data/zonetool/h2_mod_ui/images/trophy_43.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_44.dds b/data/zonetool/h2_mod_ui/images/trophy_44.dds index b84aa579..219d280c 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_44.dds and b/data/zonetool/h2_mod_ui/images/trophy_44.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_45.dds b/data/zonetool/h2_mod_ui/images/trophy_45.dds index 1d7acfb1..3957fdb0 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_45.dds and b/data/zonetool/h2_mod_ui/images/trophy_45.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_46.dds b/data/zonetool/h2_mod_ui/images/trophy_46.dds index 605164e6..d6dc6b56 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_46.dds and b/data/zonetool/h2_mod_ui/images/trophy_46.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_47.dds b/data/zonetool/h2_mod_ui/images/trophy_47.dds index 2ff93b51..d4731772 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_47.dds and b/data/zonetool/h2_mod_ui/images/trophy_47.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_48.dds b/data/zonetool/h2_mod_ui/images/trophy_48.dds index 8d4cf1cf..a1f666e8 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_48.dds and b/data/zonetool/h2_mod_ui/images/trophy_48.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_49.dds b/data/zonetool/h2_mod_ui/images/trophy_49.dds index 498a9336..a919e5c2 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_49.dds and b/data/zonetool/h2_mod_ui/images/trophy_49.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_5.dds b/data/zonetool/h2_mod_ui/images/trophy_5.dds index 39a96656..67b12653 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_5.dds and b/data/zonetool/h2_mod_ui/images/trophy_5.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_50.dds b/data/zonetool/h2_mod_ui/images/trophy_50.dds index 3913bd93..67940071 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_50.dds and b/data/zonetool/h2_mod_ui/images/trophy_50.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_6.dds b/data/zonetool/h2_mod_ui/images/trophy_6.dds index 01714ee2..277dfa2a 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_6.dds and b/data/zonetool/h2_mod_ui/images/trophy_6.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_7.dds b/data/zonetool/h2_mod_ui/images/trophy_7.dds index 194435fc..ca44e124 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_7.dds and b/data/zonetool/h2_mod_ui/images/trophy_7.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_8.dds b/data/zonetool/h2_mod_ui/images/trophy_8.dds index 8420b3cb..fad6ccdf 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_8.dds and b/data/zonetool/h2_mod_ui/images/trophy_8.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_9.dds b/data/zonetool/h2_mod_ui/images/trophy_9.dds index d8005d28..f20a8812 100644 Binary files a/data/zonetool/h2_mod_ui/images/trophy_9.dds and b/data/zonetool/h2_mod_ui/images/trophy_9.dds differ diff --git a/data/zonetool/h2_mod_ui/images/trophy_border.dds b/data/zonetool/h2_mod_ui/images/trophy_border.dds new file mode 100644 index 00000000..8b5bec55 Binary files /dev/null and b/data/zonetool/h2_mod_ui/images/trophy_border.dds differ diff --git a/data/zonetool/h2_mod_ui/materials/trophy_border.json b/data/zonetool/h2_mod_ui/materials/trophy_border.json new file mode 100644 index 00000000..a306a105 --- /dev/null +++ b/data/zonetool/h2_mod_ui/materials/trophy_border.json @@ -0,0 +1,26 @@ +{ + "name": "trophy_border", + "techniqueSet->name": "2d", + "gameFlags": 0, + "sortKey": 60, + "renderFlags": 0, + "textureAtlasRowCount": 1, + "textureAtlasColumnCount": 1, + "textureAtlasFrameBlend": 0, + "textureAtlasAsArray": 0, + "surfaceTypeBits": 0, + "cameraRegion": 12, + "materialType": 0, + "assetFlags": 0, + "constantTable": null, + "textureTable": [ + { + "image": "trophy_border", + "semantic": 0, + "samplerState": 226, + "lastCharacter": 112, + "firstCharacter": 99, + "typeHash": 2695565377 + } + ] +} \ No newline at end of file diff --git a/data/zonetool/localizedstrings/english.json b/data/zonetool/localizedstrings/english.json index da4bbe4a..43d13612 100644 --- a/data/zonetool/localizedstrings/english.json +++ b/data/zonetool/localizedstrings/english.json @@ -121,6 +121,10 @@ "DEPOT_GO_TO_THE_DEPOT": "Open link", "MENU_OPEN_MOTD": "Open Message of the Day", + "LUA_MENU_ACHIEVEMENTS": "ACHIEVEMENTS", + "LUA_MENU_ACHIEVEMENTS_DESC": "View achievements.", + "LUA_MENU_UNKNOWN_ACHIEVEMENT": "???", + "ACHIEVEMENT_EARNED": "Achievement Unlocked!", "ACHIEVEMENT_NAME_0": "Is That All You Got?", "ACHIEVEMENT_DETAIL_0": "Earn all available trophies for Call of Duty®: Modern Warfare® 2 Campaign Remastered.", diff --git a/src/client/component/achievements.cpp b/src/client/component/achievements.cpp index becc11f3..168981c1 100644 --- a/src/client/component/achievements.cpp +++ b/src/client/component/achievements.cpp @@ -78,40 +78,12 @@ namespace achievements achievement_t(ACHIEVEMENT_50, "HEADBANGER", ACHIEVEMENT_RARITY_0), }; - struct achievement_file_t - { - std::uint32_t signature; - std::uint8_t version; - bool achievements[ACHIEVEMENT_COUNT]; - }; - std::filesystem::path get_achievements_path() { return utils::properties::get_appdata_path() / "player/achievements.bin"; } - void get_achievements(achievement_file_t* file) - { - std::lock_guard _0(file_mutex); - const auto path = get_achievements_path().generic_string(); - if (!utils::io::file_exists(path)) - { - return; - } - - const auto data = utils::io::read_file(path); - if (data.size() < sizeof(achievement_file_t)) - { - return; - } - - std::memcpy(file, data.data(), sizeof(achievement_file_t)); - if (file->signature != ACHIEVEMENT_FILE_SIGNATURE) - { - std::memset(file, 0, sizeof(achievement_file_t)); - } - } void write_achievements(achievement_file_t* data) { @@ -177,7 +149,7 @@ namespace achievements void give_achievement_id_internal(achievement_file_t* file, int id) { - get_achievements(file); + achievements::get_achievements(file); if (has_achievement(file, id)) { return; @@ -216,6 +188,29 @@ namespace achievements } } + void get_achievements(achievement_file_t* file) + { + std::lock_guard _0(file_mutex); + const auto path = get_achievements_path().generic_string(); + + if (!utils::io::file_exists(path)) + { + return; + } + + const auto data = utils::io::read_file(path); + if (data.size() < sizeof(achievement_file_t)) + { + return; + } + + std::memcpy(file, data.data(), sizeof(achievement_file_t)); + if (file->signature != ACHIEVEMENT_FILE_SIGNATURE) + { + std::memset(file, 0, sizeof(achievement_file_t)); + } + } + int get_count() { return ACHIEVEMENT_COUNT; diff --git a/src/client/component/achievements.hpp b/src/client/component/achievements.hpp index e2f7490e..61202c63 100644 --- a/src/client/component/achievements.hpp +++ b/src/client/component/achievements.hpp @@ -76,6 +76,15 @@ namespace achievements achievement_rarity rarity; }; + struct achievement_file_t + { + std::uint32_t signature; + std::uint8_t version; + bool achievements[ACHIEVEMENT_COUNT]; + }; + + void get_achievements(achievement_file_t* file); + int get_count(); bool has_achievement(int id); std::string get_name(int id); diff --git a/src/client/component/ui_scripting.cpp b/src/client/component/ui_scripting.cpp index 7053b72a..d81ba954 100644 --- a/src/client/component/ui_scripting.cpp +++ b/src/client/component/ui_scripting.cpp @@ -682,6 +682,21 @@ namespace ui_scripting achievements_table["getname"] = achievements::get_name; achievements_table["getdetails"] = achievements::get_details; achievements_table["count"] = achievements::get_count; + + achievements_table["table"] = []() + { + table table{}; + + achievements::achievement_file_t file{}; + achievements::get_achievements(&file); + + for (auto i = 0; i < achievements::ACHIEVEMENT_COUNT; i++) + { + table[i] = file.achievements[i]; + } + + return table; + }; } void start()