From 3eb87180a3a55f756adb249cdd21e3f623f57c14 Mon Sep 17 00:00:00 2001 From: shaga Date: Sun, 28 Jun 2026 21:34:44 -0700 Subject: [PATCH] Fork of RavenOfSeven/LifeSafer_LowHealthWarning for OctoWoW Only change vs upstream: lowercase the toc Title color escapes (|C... / |R -> |c... / |r) so the OctoLauncher addon browser renders the gradient name instead of the raw escape codes. Addon code unchanged. Co-Authored-By: Claude Opus 4.8 --- LifeSafer_LowHealthWarning.toc | 11 + LowHealth.lua | 285 ++++++++++++++++ LowHealth.xml | 49 +++ LowHealthSettings.lua | 161 +++++++++ LowHealthSettings.xml | 416 +++++++++++++++++++++++ Nightfall.lua | 97 ++++++ Nightfall.xml | 48 +++ NightfallSettings.lua | 75 ++++ NightfallSettings.xml | 182 ++++++++++ README.md | 8 + Sounds/00 - Sounds - HeartbeatLoud.mp3 | Bin 0 -> 25218 bytes Sounds/00 - Sounds - HeartbeatNormal.mp3 | Bin 0 -> 16756 bytes Sounds/00 - Sounds - HeartbeatQuiet.mp3 | Bin 0 -> 16125 bytes Sounds/00 - Sounds - PanicLoud.mp3 | Bin 0 -> 14179 bytes Sounds/00 - Sounds - PanicNormal.mp3 | Bin 0 -> 11018 bytes Sounds/CriticalDamage.mp3 | Bin 0 -> 33437 bytes Sounds/EnslaveDemonEnd-En.mp3 | Bin 0 -> 44348 bytes Sounds/EnslaveDemonEnd-Fr.mp3 | Bin 0 -> 53289 bytes Sounds/Fear-En.mp3 | Bin 0 -> 38912 bytes Sounds/Fear-Fr.mp3 | Bin 0 -> 83382 bytes Sounds/LifeSafer_LifeAlert.wav | Bin 0 -> 14446 bytes Sounds/LifeSafer_LifeAlert_Low.mp3 | Bin 0 -> 14592 bytes Sounds/Pig01.mp3 | Bin 0 -> 13586 bytes Sounds/Pig02.mp3 | Bin 0 -> 12546 bytes Sounds/ShadowTrance-En.mp3 | Bin 0 -> 36407 bytes Sounds/ShadowTrance-Fr.mp3 | Bin 0 -> 58305 bytes Sounds/Sheep01.mp3 | Bin 0 -> 12543 bytes Sounds/Sheep02.mp3 | Bin 0 -> 17769 bytes Sounds/SoulstoneEnd-En.mp3 | Bin 0 -> 55589 bytes Sounds/SoulstoneEnd-Fr.mp3 | Bin 0 -> 74605 bytes Sounds/Sounds_Alarm.mp3 | Bin 0 -> 23644 bytes Sounds/Sounds_Alert.mp3 | Bin 0 -> 47675 bytes Sounds/critical.mp3 | Bin 0 -> 33437 bytes Textures/flash1.tga | Bin 0 -> 607914 bytes Textures/flash2.tga | Bin 0 -> 220192 bytes Textures/lowhealth1.tga | Bin 0 -> 556676 bytes Textures/lowhealth2.tga | Bin 0 -> 475023 bytes localization.lua | 307 +++++++++++++++++ readme.txt | 122 +++++++ 39 files changed, 1761 insertions(+) create mode 100644 LifeSafer_LowHealthWarning.toc create mode 100644 LowHealth.lua create mode 100644 LowHealth.xml create mode 100644 LowHealthSettings.lua create mode 100644 LowHealthSettings.xml create mode 100644 Nightfall.lua create mode 100644 Nightfall.xml create mode 100644 NightfallSettings.lua create mode 100644 NightfallSettings.xml create mode 100644 README.md create mode 100644 Sounds/00 - Sounds - HeartbeatLoud.mp3 create mode 100644 Sounds/00 - Sounds - HeartbeatNormal.mp3 create mode 100644 Sounds/00 - Sounds - HeartbeatQuiet.mp3 create mode 100644 Sounds/00 - Sounds - PanicLoud.mp3 create mode 100644 Sounds/00 - Sounds - PanicNormal.mp3 create mode 100644 Sounds/CriticalDamage.mp3 create mode 100644 Sounds/EnslaveDemonEnd-En.mp3 create mode 100644 Sounds/EnslaveDemonEnd-Fr.mp3 create mode 100644 Sounds/Fear-En.mp3 create mode 100644 Sounds/Fear-Fr.mp3 create mode 100644 Sounds/LifeSafer_LifeAlert.wav create mode 100644 Sounds/LifeSafer_LifeAlert_Low.mp3 create mode 100644 Sounds/Pig01.mp3 create mode 100644 Sounds/Pig02.mp3 create mode 100644 Sounds/ShadowTrance-En.mp3 create mode 100644 Sounds/ShadowTrance-Fr.mp3 create mode 100644 Sounds/Sheep01.mp3 create mode 100644 Sounds/Sheep02.mp3 create mode 100644 Sounds/SoulstoneEnd-En.mp3 create mode 100644 Sounds/SoulstoneEnd-Fr.mp3 create mode 100644 Sounds/Sounds_Alarm.mp3 create mode 100644 Sounds/Sounds_Alert.mp3 create mode 100644 Sounds/critical.mp3 create mode 100644 Textures/flash1.tga create mode 100644 Textures/flash2.tga create mode 100644 Textures/lowhealth1.tga create mode 100644 Textures/lowhealth2.tga create mode 100644 localization.lua create mode 100644 readme.txt diff --git a/LifeSafer_LowHealthWarning.toc b/LifeSafer_LowHealthWarning.toc new file mode 100644 index 0000000..50a37ef --- /dev/null +++ b/LifeSafer_LowHealthWarning.toc @@ -0,0 +1,11 @@ +## Interface: 11200 +## Title: |cFFB700B7Li|cFFFF00FFfe|cFFFF50FFSa|cFFFF99FFf|cFFFFC4FFe|cFFFFFFFFr|cFFFFC4FFLO|cFFFF99FFw|cFFFF50FFHea|cFFFF00FFlth |cFFB700B7Wa|cFFFFFFFFrn|cFF7FFF7Fing|r πŸ¦‡πŸ¦‡ +## Author: |cFF9482C9Silent|r ported and merged by tamara09πŸ¦‡πŸ¦‡ +## Version: 0.7a +## Notes: Enables a flashing red effect when you are low on life, and a flasing blue effect when you're low on mana. This warning system was implemented by Blizzard but is not in use.|r +## SavedVariablesPerCharacter: LifeSafer_LowHealth_Thresholds, LifeSafer_LowHealth_Enabled, LifeSafer_LowHealth_SoundCombatOnly, LifeSafer_LowHealth_HealthCombatOnly, LifeSafer_LowHealth_ManaCombatOnly, LifeSafer_LowHealth_SoundEnabled, LifeSafer_LowHealth_HealthEnabled, LifeSafer_LowHealth_ManaEnabled, LifeSafer_LowHealth_HealthSync, LifeSafer_LowHealth_ManaSync, LifeSafer_LowHealth_HealthEmote, LifeSafer_LowHealth_ManaEmote, LifeSafer_LowHealth_UseAltTextures, LifeSafer_Nightfall_Enabled, LifeSafer_Nightfall_ShardEnabled, LifeSafer_Nightfall_UseLargeEffect, +LowHealth.xml +LowHealthSettings.xml +LifeSafer_Nightfall_SoundEffects +Nightfall.xml +NightfallSettings.xml diff --git a/LowHealth.lua b/LowHealth.lua new file mode 100644 index 0000000..abe4f3b --- /dev/null +++ b/LowHealth.lua @@ -0,0 +1,285 @@ +function LifeSafer_LowHealth_OnLoad() + + local health, mana, sound = "UNIT_HEALTH", "UNIT_MANA", "SOUND" + + LifeSafer_LowHealth_Version = "2.2.2" + + -- these are the default values + LifeSafer_LowHealth_Default_Enabled = true + LifeSafer_LowHealth_Default_SoundEnabled = true + LifeSafer_LowHealth_Default_HealthEnabled = true + LifeSafer_LowHealth_Default_ManaEnabled = true + LifeSafer_LowHealth_Default_SoundCombatOnly = false + LifeSafer_LowHealth_Default_HealthCombatOnly = false + LifeSafer_LowHealth_Default_ManaCombatOnly = false + LifeSafer_LowHealth_Default_HealthSync = false + LifeSafer_LowHealth_Default_ManaSync = false + LifeSafer_LowHealth_Default_HealthEmote = false + LifeSafer_LowHealth_Default_ManaEmote = false + LifeSafer_LowHealth_Default_UseAltTextures = false + LifeSafer_LowHealth_Default_Thresholds = { + [health] = { [1] = 40, [2] = 20 }, -- regular and critical, in percent + [mana] = { [1] = 40, [2] = 20 }, + [sound] = { [1] = 50 }, + } + + -- set variables to their default values. these will be overriden when variables are loaded + LifeSafer_LowHealth_Enabled = LifeSafer_LowHealth_Default_Enabled + LifeSafer_LowHealth_SoundEnabled = LifeSafer_LowHealth_Default_SoundEnabled + LifeSafer_LowHealth_HealthEnabled = LifeSafer_LowHealth_Default_HealthEnabled + LifeSafer_LowHealth_ManaEnabled = LifeSafer_LowHealth_Default_ManaEnabled + LifeSafer_LowHealth_SoundCombatOnly = LifeSafer_LowHealth_Default_SoundCombatOnly + LifeSafer_LowHealth_HealthCombatOnly = LifeSafer_LowHealth_Default_HealthCombatOnly + LifeSafer_LowHealth_ManaCombatOnly = LifeSafer_LowHealth_Default_ManaCombatOnly + LifeSafer_LowHealth_HealthSync = LifeSafer_LowHealth_Default_HealthSync + LifeSafer_LowHealth_ManaSync = LifeSafer_LowHealth_Default_ManaSync + LifeSafer_LowHealth_HealthEmote = LifeSafer_LowHealth_Default_HealthEmote + LifeSafer_LowHealth_ManaEmote = LifeSafer_LowHealth_Default_ManaEmote + LifeSafer_LowHealth_Thresholds = LifeSafer_LowHealth_Default_Thresholds + LifeSafer_LowHealth_UseAltTextures = LifeSafer_LowHealth_Default_UseAltTextures + + LifeSafer_LowHealth_HealthFrame = LowHealthFrame + LifeSafer_LowHealth_ManaFrame = OutOfControlFrame + + -- these values keep track of animation + this.states = { [health] = 0, [mana] = 0 } + + -- change the blue frame to act as the red one + OutOfControlFrame:ClearAllPoints() + OutOfControlFrame:SetParent("WorldFrame") + OutOfControlFrame:SetAllPoints("WorldFrame") + + -- set both frames transparent to avoid onload flashing + LowHealthFrame:SetAlpha(0) + OutOfControlFrame:SetAlpha(0) + + -- command line + SlashCmdList["LOWHEALTHWARNINGCMD"] = LifeSafer_LowHealth_CMD + SLASH_LOWHEALTHWARNINGCMD1 = "/lowhealthwarning" + SLASH_LOWHEALTHWARNINGCMD2 = "/lowhealth" + SLASH_LOWHEALTHWARNINGCMD3 = "/lhw" + +end + + +function LifeSafer_LowHealth_ApplySettings() + + -- for compatibility with older versions of saved variables + if (not LifeSafer_LowHealth_Thresholds["SOUND"]) then + LifeSafer_LowHealth_Thresholds["SOUND"] = { [1] = 30 } + end + + local frame = getglobal("LowHealthWarningFrame") + + LifeSafer_LowHealth_FlashFrameStop(LifeSafer_LowHealth_HealthFrame, "UNIT_HEALTH") + LifeSafer_LowHealth_FlashFrameStop(LifeSafer_LowHealth_ManaFrame, "UNIT_MANA") + + -- register or unregister events + if (LifeSafer_LowHealth_Enabled) then + LifeSafer_LowHealth_HealthFrame = LifeSafer_LowHealth_UseAltTextures and LowHealthWarningFrameAltTexture1 or LowHealthFrame + frame:RegisterEvent("UNIT_DISPLAYPOWER") + if (LifeSafer_LowHealth_HealthEnabled or LifeSafer_LowHealth_SoundEnabled) then + frame:RegisterEvent("UNIT_HEALTH") + end + LifeSafer_LowHealth_ManaCheck() + LifeSafer_LowHealth_ManaFrame = LifeSafer_LowHealth_UseAltTextures and LowHealthWarningFrameAltTexture2 or OutOfControlFrame + else + frame:UnregisterEvent("UNIT_HEALTH") + frame:UnregisterEvent("UNIT_MANA") + frame:UnregisterEvent("UNIT_DISPLAYPOWER") + end + +end + + +function LifeSafer_LowHealth_FlashFrame(value, regular, critical, frame, state) + + local REGULAR_FLASH, CRITICAL_FLASH = 1, 2 + + -- disable + if (value > regular or LifeSafer_LowHealth_CombatCheck(state) or UnitIsDeadOrGhost("player")) then + if (UIFrameIsFlashing(frame) or UIFrameIsFading(frame)) then + LifeSafer_LowHealth_FlashFrameStop(frame, state) + end + -- regular flash + elseif (value > critical) then + if (not (LowHealthWarningFrame.states[state] == REGULAR_FLASH)) then + if (UIFrameIsFlashing(frame)) then + --frame.flashDuration = frame.flashDuration + 10 + frame.fadeInTime = 0.4 + frame.fadeOutTime = 0.6 + frame.flashInHoldTime = 1 + else + UIFrameFlash(frame, 0.4, 0.6, -1, nil, 1, 0) + end + LowHealthWarningFrame.states[state] = REGULAR_FLASH + end + -- critical flash + else + if (not (LowHealthWarningFrame.states[state] == CRITICAL_FLASH)) then + if (LifeSafer_LowHealth_HealthEmote and state == "UNIT_HEALTH") then DoEmote("healme") end + if (LifeSafer_LowHealth_ManaEmote and state == "UNIT_MANA") then DoEmote("oom") end + if (UIFrameIsFlashing(frame)) then + --frame.flashDuration = frame.flashDuration + 10 + frame.fadeInTime = 0.2 + frame.fadeOutTime = 0.8 + frame.flashInHoldTime = 0 + else + UIFrameFlash(frame, 0.2, 0.8, -1, nil, 0, 0) + end + LowHealthWarningFrame.states[state] = CRITICAL_FLASH + end + end + +end + +function LifeSafer_LowHealth_SmoothFlashFrame(value, threshold, frame, state) + + -- disable + if (value > threshold or LifeSafer_LowHealth_CombatCheck(state) or UnitIsDeadOrGhost("player")) then + LifeSafer_LowHealth_FlashFrameStop(frame, state) + -- smooth flash + else + local rate = LifeSafer_LowHealth_GetHeartRate(state) + local flashIn, flashOut = rate * 0.1, rate * 0.4 + if (UIFrameIsFlashing(frame)) then + frame.flashDuration = frame.flashDuration + rate + 1 + if (rate < 1) then + frame.fadeInTime = rate * 0.15 + frame.fadeOutTime = rate * 0.85 + frame.flashInHoldTime = 0 + else + frame.fadeInTime = 0.2 + frame.fadeOutTime = 0.8 + frame.flashInHoldTime = rate - 1 + end + else + UIFrameFlash(frame, 0.2, 0.8, 10, nil, rate -1, 0) + end + end + +end + + +function LifeSafer_LowHealth_FlashFrameStop(frame, state) + + UIFrameFlashRemoveFrame(frame) + UIFrameFadeRemoveFrame(frame) + UIFrameFadeOut(frame, 0.5, frame:GetAlpha(), 0) + LowHealthWarningFrame.states[state] = 0 + +end + + +function LifeSafer_LowHealth_OnEvent() + + if (event == "UNIT_DISPLAYPOWER") then + LifeSafer_LowHealth_ManaCheck() + return + end + + -- unpacks regular threshold, critical threshold, nil, nil, nil + local t1, t2, value, frame, smooth = unpack(LifeSafer_LowHealth_Thresholds[event]) + + -- pick frame based on event + if (event == "UNIT_HEALTH") then + value = UnitHealth("player") / UnitHealthMax("player") + LifeSafer_LowHealth_SoundCheck(this, value * 100, unpack(LifeSafer_LowHealth_Thresholds["SOUND"])) + if (not LifeSafer_LowHealth_HealthEnabled) then + return -- this hack is because both sound and health flash need this event + end + frame = LifeSafer_LowHealth_HealthFrame + smooth = LifeSafer_LowHealth_HealthSync + elseif (event == "UNIT_MANA") then + value = UnitMana("player") / UnitManaMax("player") + frame = LifeSafer_LowHealth_ManaFrame + smooth = LifeSafer_LowHealth_ManaSync + end + + if (smooth) then -- flash differently depending on settings + LifeSafer_LowHealth_SmoothFlashFrame(value * 100, t1, frame, event) + else + LifeSafer_LowHealth_FlashFrame(value * 100, t1, t2, frame, event) + end + +end + + +function LifeSafer_LowHealth_CombatCheck(state) + + local combat = UnitAffectingCombat("player") + if (not state or state == "UNIT_HEALTH") then + return LifeSafer_LowHealth_HealthCombatOnly and not combat + elseif (state == "UNIT_MANA") then + return LifeSafer_LowHealth_ManaCombatOnly and not combat + else + return LifeSafer_LowHealth_SoundCombatOnly and not combat + end + +end + + +function LifeSafer_LowHealth_SoundCheck(frame, value, threshold) + + -- disable + if (value > threshold or not LifeSafer_LowHealth_SoundEnabled or LifeSafer_LowHealth_CombatCheck("SOUND") or UnitIsDeadOrGhost("player")) then + if (frame.heartRate) then + frame:SetScript("OnUpdate", nil) + frame.heartRate = nil + end + -- regular + elseif (not frame.heartRate) then + frame:SetScript("OnUpdate", LifeSafer_LowHealth_OnUpdate) + frame.timer = 1 + frame.heartRate = 0 + end +end + + +function LifeSafer_LowHealth_ManaCheck() + + local mana, frame = "UNIT_MANA", getglobal("LowHealthWarningFrame") + if (LifeSafer_LowHealth_ManaEnabled and UnitPowerType("player") == 0) then + -- player is using mana + frame:RegisterEvent(mana) + else + frame:UnregisterEvent(mana) + LifeSafer_LowHealth_FlashFrameStop(LifeSafer_LowHealth_ManaFrame, mana) + end +end + + +function LifeSafer_LowHealth_OnUpdate() + + if (this.timer > this.heartRate) then + PlaySoundFile("Interface\\AddOns\\LifeSafer_LowHealthWarning\\Sounds\\LifeSafer_LifeAlert_Low.mp3") + this.heartRate = LifeSafer_LowHealth_GetHeartRate() + this.timer = 0 + else + this.timer = this.timer + arg1 + end + +end + + +function LifeSafer_LowHealth_GetHeartRate(state) + if (state and state == "UNIT_MANA") then + return 0.5 + 2.0 * UnitMana("player") / UnitManaMax("player") + else + return 0.5 + 2.0 * UnitHealth("player") / UnitHealthMax("player") + end +end + + +function LifeSafer_LowHealth_CMD(arg1) + + if (not arg1) then + return + end + + if (string.find(arg1, "^settings$") or arg1 == "") then + ShowUIPanel(LowHealthSettingsFrame) + return + end + +end diff --git a/LowHealth.xml b/LowHealth.xml new file mode 100644 index 0000000..653923d --- /dev/null +++ b/LowHealth.xml @@ -0,0 +1,49 @@ + + + +