From db764a66e70ccfa7fbca4caea805991826761d00 Mon Sep 17 00:00:00 2001 From: hbock Date: Wed, 31 Dec 2025 09:02:45 +0000 Subject: [PATCH] Dateien nach "/" hochladen --- MoanS.lua | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ MoanS.toc | 8 ++ 2 files changed, 261 insertions(+) create mode 100644 MoanS.lua create mode 100644 MoanS.toc diff --git a/MoanS.lua b/MoanS.lua new file mode 100644 index 0000000..6a63505 --- /dev/null +++ b/MoanS.lua @@ -0,0 +1,253 @@ +local addonName = "MoanS" + +local defaults = { + active = true, + chat = true, + petEnabled = true, + healEnabled = true, + color = "|cffFF69B4", + totalMoans = 0, + showCounter = true, + framePos = nil, + soundBaseName = "moan", + comboTimeout = 4.0, + locked = false, -- Neue Einstellung für die Verankerung +} + +local frame = CreateFrame("Frame") +frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") +frame:RegisterEvent("ADDON_LOADED") + +local lastSoundTime = 0 +local comboCount = 0 +local MAX_SOUNDS = 9 + +-- Hilfsfunktion: Zahlen kürzen +local function FormatNumber(amount) +if not amount or type(amount) ~= "number" then return amount or "0" end + if amount >= 1000000 then return string.format("%.1fM", amount / 1000000) + elseif amount >= 1000 then return string.format("%.1fK", amount / 1000) + else return tostring(amount) end + end + + -- 1. GRAFISCHER COUNTER + local CounterFrame = CreateFrame("Frame", "MoanSCounterFrame", UIParent, "BackdropTemplate") + CounterFrame:SetSize(130, 40) + CounterFrame:SetPoint("CENTER", 0, 0) + CounterFrame:SetMovable(true) + CounterFrame:EnableMouse(true) + CounterFrame:RegisterForDrag("LeftButton") + CounterFrame:SetClampedToScreen(true) + + CounterFrame.bg = CounterFrame:CreateTexture(nil, "BACKGROUND") + CounterFrame.bg:SetAllPoints() + CounterFrame.bg:SetColorTexture(0, 0, 0, 0.6) + + CounterFrame.Cooldown = CreateFrame("Cooldown", nil, CounterFrame, "CooldownFrameTemplate") + CounterFrame.Cooldown:SetAllPoints() + CounterFrame.Cooldown:SetDrawEdge(false) + CounterFrame.Cooldown:SetSwipeColor(1, 0.41, 0.7, 0.5) + + CounterFrame.text = CounterFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge") + CounterFrame.text:SetPoint("CENTER") + CounterFrame.text:SetText("Moans: 0") + + -- 2. FEUERWERK ANIMATION + local function ShowCritText(amount) + local f = CreateFrame("Frame", nil, CounterFrame) + f:SetSize(200, 30) + f:SetPoint("CENTER", CounterFrame, "CENTER", 0, 0) + + local text = f:CreateFontString(nil, "OVERLAY", "NumberFont_Outline_Huge") + text:SetPoint("CENTER") + text:SetText(FormatNumber(amount)) + text:SetTextColor(1, 0.41, 0.7) + + local ag = f:CreateAnimationGroup() + + -- Zufällige Richtung für das Feuerwerk + local targetX = math.random(-120, 120) + local targetY = math.random(80, 150) + + -- 1. Pop & Scale + local scale = ag:CreateAnimation("Scale") + scale:SetScale(1.5, 1.5) + scale:SetDuration(0.15) + scale:SetOrder(1) + + -- 2. Flugbahn (Explosionseffekt) + local translation = ag:CreateAnimation("Translation") + translation:SetOffset(targetX, targetY) + translation:SetDuration(1.4) + translation:SetSmoothing("OUT") + translation:SetOrder(2) + + -- 3. Rotation (leichtes Trudeln) + local rotation = ag:CreateAnimation("Rotation") + rotation:SetDegrees(math.random(-20, 20)) + rotation:SetDuration(1.4) + rotation:SetOrder(2) + + -- 4. Verzögertes Ausfaden + local alpha = ag:CreateAnimation("Alpha") + alpha:SetFromAlpha(1) + alpha:SetToAlpha(0) + alpha:SetStartDelay(0.7) + alpha:SetDuration(0.7) + alpha:SetOrder(2) + + ag:SetScript("OnFinished", function() f:Hide() end) + ag:Play() + end + + -- Verankerungs-Logik + local function UpdateLockState() + if not MoanSDB then return end + if MoanSDB.locked then + CounterFrame:EnableMouse(false) + else + CounterFrame:EnableMouse(true) + end + end + + CounterFrame:SetScript("OnDragStart", CounterFrame.StartMoving) + CounterFrame:SetScript("OnDragStop", function(self) + self:StopMovingOrSizing() + local point, _, relativePoint, x, y = self:GetPoint() + if MoanSDB then MoanSDB.framePos = { point, relativePoint, x, y } end + end) + + local function UpdateCounterDisplay() + if not MoanSDB then return end + CounterFrame.text:SetText("Moans: " .. (MoanSDB.totalMoans or 0)) + if MoanSDB.showCounter and MoanSDB.active then CounterFrame:Show() else CounterFrame:Hide() end + UpdateLockState() + end + + local function TriggerCombo() + local currentTime = GetTime() + local timeout = MoanSDB and MoanSDB.comboTimeout or 4.0 + local soundFile = "" + + if (currentTime - lastSoundTime) > timeout or comboCount >= MAX_SOUNDS then + comboCount = 1 + else + comboCount = comboCount + 1 + end + + lastSoundTime = currentTime + CounterFrame.Cooldown:SetCooldown(currentTime, timeout) + + if comboCount == MAX_SOUNDS then + soundFile = "Interface\\AddOns\\MoanS\\moan10.ogg" + else + soundFile = "Interface\\AddOns\\MoanS\\" .. (MoanSDB.soundBaseName or "moan") .. comboCount .. ".ogg" + end + return soundFile + end + + -- 3. OPTIONS PANEL + local MoanSPanel = CreateFrame("Frame", "MoanSConfigPanel", UIParent) + MoanSPanel.name = addonName + local category + + local function CreateCB(parent, label, x, y, dbKey) + local cb = CreateFrame("CheckButton", nil, parent, "InterfaceOptionsCheckButtonTemplate") + cb:SetPoint("TOPLEFT", x, y) + cb.Text:SetText(label) + cb:SetScript("OnShow", function(self) if MoanSDB then self:SetChecked(MoanSDB[dbKey]) end end) + cb:SetScript("OnClick", function(self) + MoanSDB[dbKey] = self:GetChecked() + UpdateCounterDisplay() + end) + return cb + end + + -- 4. EVENT HANDLER + frame:SetScript("OnEvent", function(self, event, arg1) + if event == "ADDON_LOADED" and arg1 == addonName then + if not MoanSDB then MoanSDB = CopyTable(defaults) end + for k, v in pairs(defaults) do if MoanSDB[k] == nil then MoanSDB[k] = v end end + + category = Settings.RegisterCanvasLayoutCategory(MoanSPanel, addonName) + Settings.RegisterAddOnCategory(category) + + local title = MoanSPanel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge") + title:SetPoint("TOPLEFT", 16, -16) + title:SetText("|cffFF69B4MoanS|r - Retail Edition") + + CreateCB(MoanSPanel, "Addon Aktiviert", 16, -50, "active") + CreateCB(MoanSPanel, "Fenster anzeigen", 16, -80, "showCounter") + CreateCB(MoanSPanel, "Fenster fixieren (Lock)", 16, -110, "locked") + CreateCB(MoanSPanel, "Chat Nachrichten", 16, -140, "chat") + + local slider = CreateFrame("Slider", "MoanSTimeoutSlider", MoanSPanel, "OptionsSliderTemplate") + slider:SetPoint("TOPLEFT", 20, -190) + slider:SetMinMaxValues(0.5, 10.0) + slider:SetValueStep(0.5) + slider:SetWidth(180) + _G[slider:GetName().."Low"]:SetText("0.5s") + _G[slider:GetName().."High"]:SetText("10s") + + local sliderVal = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlight") + sliderVal:SetPoint("BOTTOM", slider, "TOP", 0, 5) + slider:SetScript("OnValueChanged", function(s, val) + val = math.floor(val * 2 + 0.5) / 2 + MoanSDB.comboTimeout = val + sliderVal:SetText("Combo-Zeit: "..val.."s") + end) + slider:SetValue(MoanSDB.comboTimeout) + + local btnTest = CreateFrame("Button", nil, MoanSPanel, "UIPanelButtonTemplate") + btnTest:SetPoint("TOPLEFT", 16, -240) + btnTest:SetSize(160, 25) + btnTest:SetText("Feuerwerk Testen") + btnTest:SetScript("OnClick", function() + PlaySoundFile(TriggerCombo(), "Master") + ShowCritText(math.random(10000, 2000000)) + end) + + local btnReset = CreateFrame("Button", nil, MoanSPanel, "UIPanelButtonTemplate") + btnReset:SetPoint("TOPLEFT", 16, -275) + btnReset:SetSize(160, 25) + btnReset:SetText("Counter Reset") + btnReset:SetScript("OnClick", function() MoanSDB.totalMoans = 0; UpdateCounterDisplay() end) + + if MoanSDB.framePos then + CounterFrame:ClearAllPoints() + CounterFrame:SetPoint(MoanSDB.framePos[1], UIParent, MoanSDB.framePos[2], MoanSDB.framePos[3], MoanSDB.framePos[4]) + end + UpdateCounterDisplay() + + elseif event == "COMBAT_LOG_EVENT_UNFILTERED" then + if not MoanSDB or not MoanSDB.active then return end + + local info = {CombatLogGetCurrentEventInfo()} + local subevent, sourceGUID = info[2], info[4] + + if sourceGUID == UnitGUID("player") or (sourceGUID == UnitGUID("pet") and MoanSDB.petEnabled) then + local critDetected, amount = false, 0 + + if subevent == "SWING_DAMAGE" then + amount, critDetected = info[12], info[18] + elseif subevent:find("_DAMAGE") then + amount, critDetected = info[15], info[21] + elseif subevent == "SPELL_HEAL" and MoanSDB.healEnabled then + amount, critDetected = info[15], info[18] + end + + if critDetected then + PlaySoundFile(TriggerCombo(), "Master") + ShowCritText(amount) + MoanSDB.totalMoans = MoanSDB.totalMoans + 1 + UpdateCounterDisplay() + if MoanSDB.chat then print("|cffFF69B4MoanS!|r Combo: "..comboCount.."/9 ("..FormatNumber(amount)..")") end + end + end + end + end) + + SLASH_MOANS1 = "/moans" + SlashCmdList["MOANS"] = function() + if category then Settings.OpenToCategory(category:GetID()) end + end diff --git a/MoanS.toc b/MoanS.toc new file mode 100644 index 0000000..4d534ea --- /dev/null +++ b/MoanS.toc @@ -0,0 +1,8 @@ +## Interface: 110007 +## Title: |cffFF69B4MoanS|r (Retail) +## Notes: Spielt Combo-Sounds bei kritischen Treffern. +## Author: DeinName +## Version: 1.5 +## SavedVariables: MoanSDB + +MoanS.lua