Category: News

0

ExpenseReport (1.0)

Tracks all gold spent on wayshrine travel during an event. Start tracking with /eventstart and stop with /eventstop to generate a neatly formatted expense report in chat for guild reimbursement.

0

Slash Finder (1.0.0)

What it doesLists every slash command registered by your active addons in a searchable window.Libraries that use SLASH_COMMANDS as a key‑value store are filtered out.Commands/slashfinder open the window (optional pre‑fill)/sf alias for /slashfinder

0

BG3 Shadowheart Dark Justiciar Build – Trickery Cleric

Welcome to the best Shadowheart Trickery Domain Build Guide for BG3. This build is perfect for players who want to fully embrace the Shar-aligned path in Shadowheart’s storyline after the Gauntlet of Shar. The Dark Justiciar Build works especially well in stealth-focused parties. But it is also has excellent melee damage potential. We also have […]
The post BG3 Shadowheart Dark Justiciar Build – Trickery Cleric appeared first on AlcastHQ.

0

Darker Tamriel Tomes for PerfectPixel (DarkTamrielTomesUI) (20260718)

EnglishDescriptionThese are alternative textures for the Tamriel Tomes user interface. It works flawlessly with both keyboard/mouse and gamepad modes.Darker Tamriel Tomes for PerfectPixel (DarkTamrielTomesUI)” is a standalone addon and does not require PerfectPixel to function.No settings/options menuNo dependenciesOptionalPerfectPixelCredits & Special ThanksMasteroshi430 Author of the original Darker Tamriel Tomes addon.⚠️ Attention / Please NoteIf you are currently using the original Darker Tamriel Tomes, please disable or uninstall it before installing this addon to avoid conflicts.==================================================German/DeutschBeschreibungDies sind alternative Texturen fr die Benutzeroberflche von Tamriel Folianten. Sie funktionieren einwandfrei sowohl mit Tastatur/Maus als auch mit Gamepad.Darker Tamriel Tomes fr PerfectPixel (DarkTamrielTomesUI) ist ein eigenstndiges Add-on und bentigt PerfectPixel nicht, um zu funktionieren.Kein Einstellungs- oder OptionsmenKeine AbhngigkeitenOptionalPerfectPixelCredits & Besonderer DankMasteroshi430 Autor des ursprnglichen Add-ons Darker Tamriel Tomes.⚠️ Achtung / Bitte beachtenFalls du derzeit das ursprngliche Darker Tamriel Tomes verwendest, deaktiviere oder deinstalliere es bitte, bevor du dieses Add-on installierst, um Konflikte zu vermeiden.

0

LibZoneTemp (2.3.11)

# LibZoneTemp**Version:** 2.3.11 | **API Version:** 101049 101050 | **Type:** Library*by @Kreksar5 and Claude.ai*> **AI-ASSISTED ADDON.** Written with Claude.ai and has not yet been> independently validated in-game for correctness or performance. This> notice will be removed once the library has seen real play-testing.A library for *The Elder Scrolls Online* that calculates ambient temperatures for all overland zones and hundreds of sub-zones (delves, dungeons, trials, starter zones, and Daedric realms) based on lore-accurate climate data, the current in-game time of day (via LibClockTST), weather probability, and whether the player is swimming.—## Table of Contents- (#overview)- (#whats-new-in-2311)- (#whats-new-in-2310)- (#whats-new-in-239)- (#whats-new-in-238)- (#whats-new-in-237)- (#whats-new-in-236)- (#whats-new-in-235)- (#whats-new-in-231)- (#whats-new-in-230)- (#whats-new-in-220)- (#whats-new-in-210)- (#whats-new-in-200)- (#features)- (#dependencies)- (#installation)- (#public-api)- (#slash-command)- (#settings-panel)- (#zone-coverage)- (#temperature-model)- (#design-notes)- (#for-addon-authors)- (#disclaimer)—## OverviewLibZoneTemp provides a single, consistent source for ambient temperature data across ESO zones. It is intended to be consumed by other addons that want to display, react to, or simulate temperature-driven gameplay such as weather mods, survival systems, immersion HUDs, or RP tools.All internal calculations are performed in **Celsius**. Fahrenheit conversion is available for display purposes via `lib.FormatTemperature()` and the user-facing settings panel.—## What’s New in 2.3.11- **Fixed the settings panel’s author field**, which was still the literal placeholder text `”YourName”` never actually updated even after the `## Author` manifest field itself was corrected. Also bumped the internal `LIB_VERSION` guard (previously stale at `12`) to match the manifest `## AddOnVersion`, since the panel’s displayed version reads directly from that constant.—## What’s New in 2.3.10- **Standardized the author credit** to `@Kreksar5 and Claude.ai` in the `## Author` manifest field and this README’s byline, and named Claude.ai specifically (rather than generic “AI assistance”) in the manifest description and the AI-assistance disclosure above, matching the crediting convention used across this addon’s companion libraries.—## What’s New in 2.3.9- **Fixed zone temperature overrides not applying to delves, dungeons, and trials.** Interior zones have no climate-table entry of their own and inherit their base temperature from their overland parent zone; the override lookup only ever checked the *parent’s* ID, so an override set on the interior zone itself (as offered in the settings dropdown) was saved but silently never read back. The override lookup now checks the player’s exact current zone first, before falling back to the climate zone used for the base-temperature table.- **Added a live “Currently Active Overrides” list** to the settings panel, showing every zone with an override currently set, in both C and F.- **Added a Celsius/Fahrenheit reference chart** to the override section’s description, with a short note on the kind of zone each range typically represents, to help you pick a sensible override value.—## What’s New in 2.3.8- **Corrected the `## Author` manifest field**, which was still the literal placeholder text “YourName” never actually filled in. Fixed to the real author.- **Added the required AI-assistance disclosure** to the manifest description and this README, per ESOUI’s addon release rules.- **Added a version floor (`>=1`) to the `LibClockTST` dependency**, which previously had none.—## What’s New in 2.3.7- **Full API audit against the official ESOUI API 101050 documentation.** Every function call, method call, and constant referenced across the library was cross-checked against the API doc and, where the doc didn’t cover it (third-party libraries), against the live ESOUI source. No invalid or deprecated API usage found the `LibZone`/`LibClockTST` calls (`GetAllZoneData`, `GetCurrentZoneIds`, `GetCurrentZoneAndGroupStatus`, `Instance`, `GetTime`, `RegisterForTime`) are all legitimate calls into those libraries and correctly used. No code changes required.—## What’s New in 2.3.6- **Corrected `LibAddonMenu-2.0` dependency floor**: was mistakenly bumped to `>=45` in 2.3.5, but LibAddonMenu’s own manifest documentation shows `43` as the latest available version, not `45`. Fixed to `>=43`. The 2.3.5 entry below has also been corrected to reflect the right number.—## What’s New in 2.3.5ESOUI release-rules compliance pass no zone-data changes.- **`## APIVersion` updated** from the stale `101040` to `101049 101050` (current Live/PTS).- **`LibAddonMenu-2.0` dependency floor bumped** from `>=30` to `>=43`, matching the version cited as current in LibAddonMenu’s own manifest documentation.- **Fixed a version-string mismatch**: this README’s header said `2.3.0` while the manifest’s `## Version` already said `2.3.4` now synced.- **Fixed a duplicate/mislabeled changelog section** (see below the second “What’s New in 2.3.0” entry has been relabeled `2.3.1`, since it describes a separate, later correction pass).- **Reviewed for global variable leaks** none found; the library already follows the single-global-table pattern (`LibZoneTemp = LibZoneTemp or {}` / `local lib = LibZoneTemp`).- **Reviewed against “what addons cannot do”** none found. This library only reads zone/time/weather state to compute a number; it doesn’t touch any restricted behavior.—## What’s New in 2.3.0Version 2.3.0 is the second UESP-verified correction pass, covering the remaining **405 zones** (rows 301705). **38 corrections** were applied.### Key Correction Themes**Solstice (tropical island) zones** all Solstice locations introduced in Seasons of the Worm Cult were assigned incorrect cold-zone temperatures. Solstice is a tropical island south of Murkmire (~32 C); affected zones corrected include Tarnur Mine (−8 C → 30 C), Li-Xal Pass (4 C → 28 C), Vosgah Shrine (4 C → 30 C), and Vale of Revelry (20 C → 28 C).**Nordic barrow/crypt zone mis-assignments** Shroud Hearth Barrow, Taarengrav Barrow, and Nimalten Barrow were all in **The Rift** (6 C), not the arctic; corrected from −8 C → 4 C each. Wittestadr Crypts and Trolhetta Cave are in **Eastmarch** (−2 C), not arctic.**Clockwork City** Slag Town Outlaws Refuge reassigned from 4 C → 22 C (mechanically regulated Brass Fortress environment).**Cyrodiil/Stormhaven/Deshaan** Underpall Cave (Cyrodiil, 14 C), Pariah Catacombs (Stormhaven, 10 C), Reservoir of Souls (Deshaan, 15 C) all corrected from −8 C.**Fargrave/Mirrormoor** Shattered Mirror Isle (20 C → 36 C) and Loom of the Untraveled Road (15 C → 32 C) correctly placed in Ithelia’s hot Oblivion realm.**Western Skyrim interior calibration** Proudspire Manor, Solitude Outlaws Refuge, Snowmelt Suite, and Tzinghalis’s Tower all adjusted downward to reflect WS = −10 C with appropriate interior insulation offsets.—## What’s New in 2.3.1Version 2.3.1 is the third UESP-verified correction pass (rows 301400). **16 zone entries** were corrected after cross-referencing confirmed locations against UESP.### Notable Fixes- **Kingscrest Cavern**: NE Cyrodiil cave (was 36C → 15C; not Bangkorai)- **Kushalit Sanctuary**: N Vvardenfell/Red Mountain slopes (note corrected to Vvardenfell)- **Lipsand Tarn**: Colovian Highlands Ayleid ruin in NW Cyrodiil (was 4C → 14C; not a mountain tarn)- **Lucky Cat Landing**: Senchal player house in S Elsweyr (was 22C → 28C)- **Nighthollow Keep**: Blackreach: Arkthzand Cavern deep interior (was 8C → −4C)- **Nikolvara’s Kennel**: Wrothgar cave SW of Orsinium (was 5C → −5C)- **Obsidian Scar**: Rivenspire volcanic cave (was 28C → 18C; geothermally warm but still Rivenspire)- **Odious Chapel**: Shadowfen (Stillrise Village chapel, was 12C → 28C)- **Old Coin Fort**: N tip of Amenos tropical island (was 16C → 24C)- **Maelstrom Arena**: Pocket realm of Fa-Nuit-Hen (was 10C → 20C; not cold Wrothgar)—## What’s New in 2.2.0Version 2.2.0 is a UESP-verified correction pass. **48 zone entries** from the v2.1.0 expansion have been corrected after cross-referencing each zone’s confirmed location against UESP wiki sources.### Corrections SummaryThe primary error pattern was zones assigned to the wrong parent region entirely, producing temperatures that were wildly off most commonly cold-zone values (−8 C) applied to locations in Bangkorai, Greenshade, Summerset, Southern Elsweyr, or Amenos, and vice versa. Notable individual fixes include:- **Coldrock Diggings**: Alik’r Desert mine (was −8 C → 36 C)- **Forsaken Citadel**: Southern Elsweyr (was 4 C → 28 C)- **Ghost Haven Bay**: Amenos tropical cove (was 8 C → 24 C)- **Halls of the Highmane**: Southern Elsweyr Khajiiti ruin (was 8 C → 26 C)- **Hildune’s Secret Refuge**: Rivenspire cave (was 32 C → 6 C)- **Istirus Outpost / Arena**: West Weald/Cyrodiil battleground, not Reaper’s March (was 35 C → 18 C)- **Destruction’s Solace**: Deadlands capital fortress (was 40 C → 50 C)- All 48 corrections include matching water temperature updates.—## What’s New in 2.1.0Version 2.1.0 is a UESP-verified data expansion. The zone database has grown from ~317 entries to over **1,000 named zones**, adding **705 new entries** sourced directly from the UESP wiki and covering the full breadth of ESO’s explorable areas.### New Coverage- **Delves, trials, arenas, and public dungeons** across all chapters and DLC- **Instanced interiors**: manors, Outlaws Refuges, city districts, crypts, and tombs- **Daedric and Oblivion sub-realms**: Colored Rooms, Spiral Skein, Hunting Grounds, and more- **Aquatic zones**: Abecean Sea and other ocean/coastal surfaces- **Player housing areas** with climate appropriate to their region- Air temperatures derived from lore-accurate UESP climate descriptions- Water temperatures for all new entriesAll new entries include a descriptive comment drawn from UESP source notes.—## What’s New in 2.0.0Version 2.0.0 is a major data expansion. The zone temperature tables now cover **all overland zones plus hundreds of named sub-zones**, including:### New Overland / Chapter Zones- **West Weald** (19 C) southwestern Cyrodiil woodlands and rolling hills- **Bleakrock Isle** (−8 C) frozen starter island in the Sea of Ghosts- **Bal Foyen** (20 C) warm coastal Morrowind delta- **Stros M’Kai** (34 C) arid sun-baked Hammerfell island- **Betnikh** (15 C) temperate Orc island off Glenumbra- **Khenarthi’s Roost** (30 C) warm tropical Khajiit island- **Blackreach: Arkthzand Cavern** (−5 C) cold underground Dwemer Blackreach beneath The Reach### Fire / Lava Sub-ZonesThese zones receive **explicit high temperatures** rather than inheriting from their parent, because they contain active lava, dragon fire, Oblivion portals, or extreme geothermal activity:| Zone | C | Notes ||—|—|—|| City of Ash II | 55 | Deepest Mehrunes Dagon Oblivion plane || The Path of Cinders | 53 | Lava-bordered Deadlands path || Tormented Spire Summit | 54 | Summit of most active Stonefalls volcanic vent || The Deadlands: Testing Grounds | 52 | Deadlands sub-region || Burning Gyre Keep | 52 | Deadlands fortification || City of Ash I | 50 | Mehrunes Dagon Oblivion plane || Bloodroot Forge | 48 | Hircine’s ancient forge; lava channels in The Reach || The Cauldron | 44 | Deep underground Blackwood forge dungeon || Blessed Crucible | 44 | Rift arena over a volcanic vent || Ashalmawia | 42 | Vvardenfell Daedric shrine on volcanic vent || Sunspire | 42 | Northern Elsweyr dragon trial; desert sun + dragon fire || Dragonhold | 46 | Southern Elsweyr dragon lair; volcanic peak || Khaj Rawlith | 30 | Ancient underground Anequine temple in hot Reaper’s March; warm, stuffy, dark-fire corruption |### Ice / Frozen Sub-ZonesThese zones receive **explicit low temperatures** below their parent zone:| Zone | C | Notes ||—|—|—|| Icereach | −16 | Frigid isle in the Sea of Ghosts; polar cold || Frostvault | −14 | Dwarven vault buried in a thawing glacier || Ice-Heart’s Lair | −14 | Frozen bandit cave in high Wrothgar peaks || Kyne’s Aegis | −12 | Offshore Norse sea fortress trial; freezing winds || Frostbreak Fortress | −12 | Frost-covered Orc fortress in Wrothgar || Frozen Coast | −12 | Western Skyrim coastal; sea ice and blizzards || Direfrost Keep | −10 | Ancient Nord ice fortress; permafrosted interior || The Frigid Grotto | −10 | Eastmarch; frost atronachs throughout || Stone Garden | −8 | Underground frozen lycanthrope lab under Skyrim || Bleakridge Barrow | −8 | Frozen Nord barrow in Western Skyrim || Icehammer’s Vault | −8 | Sealed ice vault in Eastmarch || Chillwind Depths | −8 | Underground frozen depths in Western Skyrim || Coldwind’s Den | −8 | High mountain den in Wrothgar; extreme cold || Greymoor Keep | −8 | Half-buried in Western Skyrim’s frozen earth || Scalecaller Peak | −6 | Icy Wrothgar mountain summit with dragon || Castle Thorn | −6 | Vampire stronghold in Western Skyrim || Labyrinthian | −6 | Ancient ruins; deeply cold || The Chill Hollow | −6 | Ice-filled Eastmarch hollow cave |### Underground / Dungeon CoverageHundreds of delves, public dungeons, group dungeons, and trials across all zones now have explicit entries rather than falling back to the overland default. Key examples:- **Fungal Grotto I & II** (24 C) warm, damp sea cavern in Stonefalls- **Darkshade Caverns I & II** (2022 C) geothermal kwama mine- **Ruins of Mazzatun** (28 C) hot, humid Hist-tree complex in Black Marsh- **Cloudrest** (14 C) Summerset trial near the summit of Eton Nir; cold at altitude- **Halls of Fabrication** (24 C) Vvardenfell trial; heat from fabricant manufacturing- **All Vvardenfell egg mines and Dwemer ruins** (3034 C) geothermal Morrowind underground- **All Clockwork City sub-zones** (2022 C) temperature-controlled mechanical realm### Water Temperature ExpansionAll newly added zones also include specific **water temperatures**, from −1 C (Frostvault glacier meltwater, Icereach polar water) to 60 C (Deadlands and City of Ash II).### Weather Profile ExpansionNewly added zones include weather profiles:- **Icereach**: 5% rain / 80% snow constant blizzard conditions- **Kyne’s Aegis**: 10% rain / 70% snow- **Bleakrock Isle**: 15% rain / 60% snow- **Scalecaller Peak**: 5% rain / 70% snow- **Frozen Coast**: 10% rain / 60% snow- All underground, Oblivion, and enclosed zones: 0% rain / 0% snow—## Features- **Lore-accurate base temperatures** for every overland zone and hundreds of sub-zones through West Weald (2024)- **Explicit overrides for fire/lava zones** City of Ash, Deadlands, Tormented Spire, Bloodroot Forge, The Cauldron, and more- **Explicit overrides for ice/frozen zones** Icereach, Frostvault, Direfrost Keep, Kyne’s Aegis, and more- **Time-of-day modifiers** using the in-game Tamriel clock (dawn, day, dusk, night)- **Climate/weather modifiers** derived from zone lore- **Water temperature** when the player is swimming (`IsUnitSwimming`)- **Interior/dungeon penalty** delves, group dungeons, public dungeons, and trials are shielded from weather; many now have their own explicit temperatures- **Parent zone inheritance** unlisted child zones fall back to their parent’s climate data- **Per-zone user overrides** via the LibAddonMenu-2.0 settings panel- **Celsius / Fahrenheit toggle** in settings- **Live updates** via LibClockTST subscription and `EVENT_PLAYER_ACTIVATED`- **Debug slash command** `/ztemp` for on-demand snapshots—## Dependencies| Library | Minimum Version | Purpose ||—|—|—|| (https://www.esoui.com/downloads/info1496-LibZone.html) | 077 | Resolves zone IDs and zone group status (delve/dungeon detection) || (https://www.esoui.com/downloads/info7-LibAddonMenu.html) | 30 | Settings panel UI || (https://www.esoui.com/downloads/info2360-LibClockTST.html) | | In-game lore time (hour/minute) for time-of-day modifiers |All three dependencies must be installed and loaded for full functionality. The library degrades gracefully if LibClockTST is unavailable (defaulting to noon), and will print a warning in the settings panel if LibZone data cannot be loaded.—## Installation1. Download and unzip `LibZoneTemp` into your addons folder: “` liveAddOnsLibZoneTemp “` The folder should contain: “` LibZoneTemp/ ├── LibZoneTemp.lua ├── LibZoneTemp.txt └── README.md “`2. Ensure all three (#dependencies) are also installed.3. Launch ESO. LibZoneTemp will initialise automatically on the `EVENT_ADD_ON_LOADED` event.4. Optionally access settings via the in-game **Settings → Addons → LibZoneTemp Settings** panel, or by typing `/libzonetemp` in chat.—## Public API“`lua– Returns the current ambient temperature for the player’s zone.– When the player is swimming, returns the zone’s water temperature.– formattedString respects the user’s unit preference (“23.4C” / “74.1F”).local tempC, zoneName, tempF, formatted = lib.GetCurrentTemperature()– Returns the base temperature for a given zone ID (before time/weather modifiers).local baseTemp = lib.GetBaseTemperatureForZone(zoneId, isInterior)– Returns the full temperature for arbitrary input values. Always Celsius.– Pass isSwimming = true to get the zone’s water temperature instead.local temp = lib.CalculateTemperature(zoneId, isInterior, loreHour, isSwimming)– Converts and formats a Celsius value using the user’s saved unit preference.– Safe to call before savedVars is loaded (falls back to Celsius).local str = lib.FormatTemperature(celsius)“`—## Slash CommandType `/ztemp` in chat to print a debug snapshot:“` Zone: City of Ash I Temperature : 50.0C (50.0C / 122.0F) Lore time : 14:30 Zone ID : 176 Swimming : false“`—## Settings PanelAccess via `/libzonetemp` or **Settings → Addons → LibZoneTemp Settings**:- **Display in Fahrenheit** toggle between C and F display- **Zone Temperature Overrides** pick any zone from a dropdown and set a custom base temperature (C). Set to 0 or blank to revert to the library default.—## Zone Coverage### Overland Zones (all factions + DLC/Chapter through West Weald)All 40+ overland zones have explicit base temperatures, weather profiles, and water temperatures.### Sub-Zones with Explicit TemperaturesOver 200 named sub-zones now have their own entries, overriding parent-zone inheritance where the environment is meaningfully different. These fall into three categories:**Fire / Lava / Volcanic** zones containing active lava rivers, Oblivion fire planes, volcanic vents, or draconic flame. Temperatures range from 30 C (warm underground ruins near volcanic activity) to 60 C (deep Deadlands and City of Ash II).**Ice / Frozen / Arctic** zones buried in glaciers, located on polar islands, or containing permafrost and frost atronachs. Temperatures range from −16 C (Icereach) to −2 C (March of Sacrifices).**Underground / Dungeons** most inherit from their parent zone via the existing fallback, but dungeons with notable microclimates (geothermal heat, deep cold, enclosed Daedric environments) have their own entry.### Fallback BehaviourAny zone not found in the tables falls back to `DEFAULT_TEMP` (20 C) for air and `DEFAULT_WATER_TEMP` (16 C) for water. Sub-zones will first try their specific `zoneId`, then fall back to their `parentZoneId`, before reaching the global default.—## Temperature Model“`finalTemp = baseTemp + interiorModifier (−3 C, reduced weather/time swing indoors) + timeOfDayModifier (−5 to +3 C based on lore hour) + weatherModifier (rain: up to −4 C; snow: up to −6 C)“`Water temperature bypasses all modifiers it returns the zone’s static water value directly.—## Design Notes**Why names and not integer IDs?** ESO zone IDs are large non-sequential integers that can change between API updates. The only stable, human-readable identifier is the English zone name. At initialisation, `BuildZoneIdMaps()` calls `LibZone:GetAllZoneData()` and inverts the name→ID mapping.**Why static weather and not live weather?** The ESO addon API does not expose a function to read the current client-side weather state. Weather is entirely client-side and visual only. LibZoneTemp therefore uses a static probability table derived from zone lore.**Why not cover every delve?** Most delves inherit cleanly from their parent overland zone. Only delves with a meaningfully different microclimate (volcanic heat, glacial cold, Daedric environment) receive their own entry. This keeps the table maintainable while covering all cases where inheritance would produce a wrong result.—## For Addon Authors“`lua– Minimal usage: get the current zone temperaturelocal temp, zoneName, tempF, formatted = LibZoneTemp.GetCurrentTemperature()if temp then d(“Current temperature in ” .. zoneName .. “: ” .. formatted)end– Check if the player is in a hot zone (e.g. for survival gameplay)local zoneId = LibZoneTemp._currentZoneIdlocal base = LibZoneTemp.GetBaseTemperatureForZone(zoneId, false)if base >= 40 then — Apply heat exhaustion debuffend“`—## DisclaimerThis Add-on is not created by, affiliated with, or sponsored by ZeniMax Media Inc. or its affiliates. The Elder Scrolls and related logos are registered trademarks or trademarks of ZeniMax Media Inc. in the United States and/or other countries. All rights reserved.

0

LibArmorInsulation (2.7.5)

# LibArmorInsulation**Version 2.7.5** ESO API 101049 101050 License: MIT*by @Kreksar5 and Claude.ai*> **AI-ASSISTED ADDON.** Large portions of this addon’s code (the costume/outfit> scanning commands, the resolver priority logic, and several data-table> structures) and its UESP-sourced costume/style insulation data were written> with Claude.ai, and **have not yet been independently validated in-game**> for correctness or performance. Material/insulation assignments carry an> explicit “ tag in `LibArmorInsulation_StyleData.lua`> where applicable `low`-confidence entries in particular are thematic> inferences, not verified facts, and are good candidates for manual> re-checking against UESP or in-game testing before being trusted as accurate.> This notice will be removed once the addon has seen real play-testing.A reusable ESO addon library that calculates a **staggered-tier thermal insulation score (-10 to 90, in steps of 10)** for the player based on their current visual appearance taking into account armor style, material composition, body-slot coverage, and flavor-text bonuses or penalties from the style database. The score mirrors ESO’s own visual-priority rules: polymorphs beat costumes, costumes beat outfits, outfits beat worn armor.—## Table of Contents1. (#installation)2. (#dependencies)3. (#insulation-model)4. (#visual-priority-cascade)5. (#public-api)6. (#slash-commands)7. (#settings-panel)8. (#adding–editing-style-data)9. (#eso-api-functions-used)10. (#design-notes–limitations)11. (#changelog)—## Installation1. Drop the `LibArmorInsulation` folder into `Elder Scrolls OnlineliveAddOns`.2. Ensure **LibAddonMenu-2.0 (v33+)** is also installed ((https://www.esoui.com/)).3. Enable the addon in the ESO Addon Manager.—## Dependencies| Library | Required | Notes ||—|—|—|| LibAddonMenu-2.0 ≥ 33 | **Yes** | Settings panel only. The calculation API works without LAM, but the settings panel will be unavailable. || LibStyleInfo | No | Not used. Its confirmed public API exposes style IDtoname lookups and light/medium/heavy weight flags, but not material composition, body-coverage percentage, or flavor text. || LibMotifCategories | No | Not used. Motif category data (crafted/overland/dungeon/etc.) does not map to thermal properties. |> **Why maintain an internal style database?**> Both evaluated libraries were ruled out because neither provides the material or coverage data needed for insulation math. LibArmorInsulation therefore ships its own hand-authored table keyed on `ITEM_STYLE_*` integer constants, which every ESO item carries natively.—## Insulation Model### ScaleAll values resolve to one of **eleven fixed tiers**, staggered in increments of 10 from **-10 to 90**:| Tier | Label | Meaning ||—|—|—|| -10 | Magically Cooled | Magically cooled equipment (e.g. refrigeration) || 0 | No Insulation | No insulation || 10 | Minimal | Underwear/swimwear || 20 | Light | Light silks, breathable thin fabrics, or minimal coverage || 30 | Coarse Light | Linens, coarser fabrics, or small amounts of leather with light coverage || 40 | Layered/Leather | Thick or many-layered fabrics, or majority-coverage leathers || 50 | Full Leather/Light Metal | Full coverage leathers, mild coverage metals, or full-coverage multi-layered thick fabrics || 60 | Heavy Leather/Fur | Full coverage heavy/thick leathers, mild coverage furs, or moderate coverage metals || 70 | Full Fur/Metal | Full coverage furs or full coverage metals || 80 | Heavy Fur/Metal | Full coverage heavy furs and/or metals || 90 | Magically Heated | Magically heated equipment |`-10` and `90` are reserved for entries explicitly flagged `magical = true` in the data tables (Flame Atronach, Ice Wraith, etc.). Every other entry is clamped to the mundane **080** range before being snapped to the nearest tier, so ordinary armor and clothing can never accidentally read as magically hot or cold.> **Why a tier ladder instead of a continuous score?** It’s a much better fit for anything that has to *display* insulation a UI can show one of 11 discrete states/icons instead of trying to render 101 shades of meaning. It’s also easier to reason about and balance by hand: every entry in the data tables is describable in one of eleven plain-English buckets rather than an arbitrary integer.### How an entry becomes a tierArmor styles and outfit style pieces keep their existing `baseMaterial` + `coverage` + `flavorBonus` authoring fields nothing in the data tables needed to be hand-rewritten for the tier system. The Calculator computes the same full-body reference score it always has, then **snaps** that score onto the nearest tier:“`raw = 0.90 styleCoverage materialCoeff SCALE_FACTOR + flavorBonustier = SnapToTier(raw, magical) — nearest of {-10,0,10,…,80,90} — clamped to first unless the entry has `magical = true““`SCALE_FACTOR = 55.556` anchors a full set of standard leather armor at coverage 1.0 to exactly tier 50.Costumes and polymorphs keep their existing hand-authored `totalInsulation` field, which is likewise snapped to the nearest tier at lookup time (again clamped to 080 unless `magical = true`).### Per-slot percentage adjustment (unless it’s a full costume)A style/outfit piece’s tier is its **full-body reference value**. Individual armor/outfit slots then contribute a **percentage** of that tier based on how much of the body they cover:“`slot_contribution = round(tier slotPercentage)total = sum(slot_contribution for every worn slot)“`Slot percentages now sum to exactly **1.00** across the 7 thermally-relevant slots (previously 0.90, compensated by `SCALE_FACTOR`), so a full matching set (every slot the same tier) reproduces that tier as the total. Missing slots count as bare skin (tier 0) for that percentage of the body small independent-rounding artifacts of a point or two are possible when summing per-slot contributions, but the total will never drift outside the -10..90 tier range.**Costumes and polymorphs are NOT slot-adjusted.** They represent the whole body at once, so their snapped tier *is* the total, unadjusted there’s no percentage to apply.### Slot coverage weights| Slot | Percentage ||—|—|| Chest | 33% || Legs | 28% || Head | 11% || Shoulders | 11% || Hands | 6% || Feet | 6% || Waist | 5% || Rings, Neck, Weapons | 0% |### Material coefficients| Material | Coefficient | Full-set reference (pre-snap) | Snapped tier ||—|—|—|—|| fur | 1.8 | 90 | 80 (mundane cap) || wool | 1.5 | 75 | 70 (tie rounds down) || heavy_leather | 1.3 | 65 | 60 (tie rounds down) || leather | 1.0 | 50 (baseline) | 50 || scale | 0.8 | 40 | 40 || runic | 0.8 | 40 | 40 || bone | 0.7 | 35 | 30 (tie rounds down) || cloth | 0.7 | 35 | 30 (tie rounds down) || chitin | 0.6 | 30 | 30 || hide | 0.6 | 30 | 30 || iron | 0.5 | 25 | 20 (tie rounds down) || steel | 0.5 | 25 | 20 (tie rounds down) || silk | 0.5 | 25 | 20 (tie rounds down) || linen | 0.4 | 20 | 20 || aetherial | 0.4 | 20 | 20 || daedric | 0.3 | 15 | 10 (tie rounds down) || crystal | 0.2 | 10 | 10 || none | 0.0 | 0 | 0 |Ties (raw score exactly halfway between two tiers, e.g. 75 between 70 and 80) round **down** to the lower tier `Calc.SnapToTier()` picks the first tier with the smallest difference while scanning the ladder ascending, so the lower of two equidistant tiers wins.”Full-set reference” assumes coverage 1.0 and no flavor bonus; per-style `coverage`/`flavorBonus` modifiers shift the raw score up or down before it’s snapped, so an individual style’s tier can land a step away from its base material’s own tier (e.g. Nord’s fur base plus its +8 flavor bonus and 1.1 coverage pushes it to the mundane ceiling of tier 80).### Costume & polymorph scoringCostumes and polymorphs bypass per-slot math entirely. They return a single snapped tier looked up from `CostumeInsulationById` (by collectible ID), then `CostumeInsulation` (by normalized lowercase name), then the appropriate default:| Fallback | Raw default | Snapped tier ||—|—|—|| `DEFAULT_COSTUME` | 50 | 50 || `DEFAULT_POLYMORPH` | 38 | 40 |**Costume lookup priority.** Order is: user override (already a tier used as-is) → `CostumeInsulationById` (by collectible ID) → `CostumeInsulation` (by name, manually curated see Changelog 2.5.0) → `sv.costumeCache` (populated by `/scancostumes`) → `DEFAULT_COSTUME`. Run `/scancostumes` to populate the cache with keyword-derived auto-ratings for anything not already in the manual tables.—## Visual Priority Cascade`GetTotalInsulation()` and `GetInsulationBreakdown()` mirror ESO’s own visual priority rules, evaluated top-to-bottom:1. **Polymorph** detected via `GetActiveCollectibleByType(COLLECTIBLE_CATEGORY_TYPE_COSTUME)` combined with keyword/ID matching against polymorph entries. Returns a flat body-wide score; slot math is skipped.2. **Costume** same detection mechanism. Returns a flat body-wide score; slot math is skipped.3. **Active Outfit** detected via `GetEquippedOutfitIndex()`. Slot insulation is calculated from the collectible ID on each `OUTFIT_SLOT_*` using `ZO_OUTFIT_MANAGER`. Only slots with a non-zero style override contribute; if *no* outfit slots are overridden, falls through to armor.4. **Worn Armor** calls `GetItemLink(BAG_WORN, equipSlot)` then `GetItemLinkItemStyle(itemLink)` for each thermally relevant `EQUIP_SLOT_*`. `GetItemLinkItemStyle` is used (not `GetItemStyle`) because it returns the correct visual style for all item origins crafted, dropped, set, and Crown Store items alike.5. **Naked** returns 0.—## Public API“`lua– Total insulation score, one of the 11 tiers for costume/polymorph;– a composite (-10..90) for armor/outfit made of per-slot tier contributionslocal total = LibArmorInsulation.GetTotalInsulation()– Full breakdown tablelocal info = LibArmorInsulation.GetInsulationBreakdown()– info.source : “polymorph” | “costume” | “outfit” | “armor” | “naked”– info.total : integer, -10..90– info.slots : table {– = {– styleId, — ITEM_STYLE_* (armor path) or nil– collectibleId, — collectible ID (outfit/costume path) or nil– insulation, — integer slot contribution (== tier for costume/polymorph)– tier, — the style/costume’s own full-body tier (-10..90)– slotPercentage, — 0-1 weight of this slot; nil for costume/polymorph– material, — string material key– flavorNote, — string human-readable note, or “”– armorFallback, — boolean: true if outfit slot fell back to worn armor– }– }– info.costumeId : number | nil (collectible ID of active costume/polymorph)– info.costumeName : string | nil (lower-cased collectible name)– Full-set reference tier for a given ITEM_STYLE_* id (respects overrides)– Returns one of {-10,0,10,20,30,40,50,60,70,80,90}local tier = LibArmorInsulation.GetInsulationForStyle(styleId)– Set a persisted insulation override one of the 11 tier values– idType : “style” → ITEM_STYLE_* integer (worn armor)– “outfit” → collectible ID (outfit slot piece)– “costume” → collectible ID (costume or polymorph)– value = nil removes the override. Non-tier numbers are snapped to the– nearest tier rather than rejected. In the Settings panel this is always a– dropdown, so it can’t drift off-tier.LibArmorInsulation.SetOverride(idType, id, value)– Remove all user overrides (does not clear the costume cache)LibArmorInsulation.ResetOverrides()“`### Constants“`luaLibArmorInsulation.VERSION — “2.7.0”LibArmorInsulation.ADDON_NAME — “LibArmorInsulation”“`### Saved variables schema (account-wide)“`luasv.overrides — { = tier integer (-10..90) }sv.costumeCache — { = { name, insulation, autoRated } } — Populated by /scancostumes; persists across sessions. — `insulation` here is a pre-snap raw value, snapped to the — nearest tier at lookup time.“`Override keys follow the pattern `_` (e.g. `style_42`, `outfit_1234567`, `costume_9876543`). This unified key space means a single `SetOverride` call handles all three entity types without ambiguity.—## Slash Commands### General| Command | Description ||—|—|| `/insulation` | Prints the current source, total score with its nearest tier label, and per-slot breakdown style/collectible ID, insulation contribution, tier, slot percentage, material to chat. || `/styleids` | Prints the `ITEM_STYLE_*` ID worn in each armor slot. Use this to find the ID to enter in the override editor when working with worn armor. |### Outfit commands| Command | Description ||—|—|| `/outfitids` | Prints the collectible ID and name applied to each slot of every styled outfit. Use this to find the collectible ID to enter as an `outfit_` override. || `/outfitactive` | Diagnostic probes free functions and `outfitManipulator` methods to determine whether each outfit is actively equipped versus merely stored. Run with an outfit equipped, then unequipped, and compare output. || `/scanoutfitstyles` | Walks every equipped slot across all unlocked outfits and, for any collectible ID not already in the hand-curated `OutfitStyles` table, keyword-rates it (by name, then description) and saves a guessed `{baseMaterial, coverage, flavorBonus}` to `sv.outfitStyleCache`. Run this after unlocking/equipping a new style page so it gets a value other than `OutfitStyles`. |### Costume & polymorph commands| Command | Description ||—|—|| `/costumeids` | Prints the collectible ID, display name, and current lookup method (user override / ID table / name table / DEFAULT_COSTUME) for the active costume or polymorph. Also prints the override key (`costume_`) to use in the settings panel. || `/scancostumes` | Walks every owned costume and polymorph in the Collections system and assigns a keyword-derived auto-rating to each (checking the name first, then the in-game description if the name has no match), saving the results in the costume cache (`sv.costumeCache`). Run this once and again after acquiring new costumes to ensure all owned costumes receive a meaningful score rather than the default. || `/clearcostumecache` | Removes all entries from `sv.costumeCache`. Re-run `/scancostumes` afterward to repopulate. |### Review commands| Command | Description ||—|—|| `/costumesneedreview` | Filters `sv.costumeCache` down to entries where the keyword scan found no match in either the name or description (sitting on the generic 50 default). Use this as a worklist for manual UESP-backed `CostumeInsulationById` entries instead of scrolling the full `/scancostumes` output. || `/outfitstylesneedreview` | Same as `/costumesneedreview`, but for `sv.outfitStyleCache` entries with no keyword match. Use as a worklist for manual `OutfitStyles` entries. |### Diagnostic commands| Command | Description ||—|—|| `/diagcollectibles` | Three-phase diagnostic that enumerates every collectible category and subcategory, identifies which one ESO marks as `COLLECTIBLE_CATEGORY_TYPE_COSTUME`, and reports the first reachable collectible per category. Run this and share the output if `/scancostumes` finds 0 costumes. |—## Settings PanelAccessible via **Addon Settings** in the ESO main menu.| Section | What it does ||—|—|| **Current Insulation** | Live breakdown of every slot’s contribution, tier, slot percentage, the source (outfit / armor / costume / polymorph), material, and any flavor note. Press **Refresh** to recalculate. || **Manual Overrides** | Pick a **Layer** (Costume/Polymorph, Outfit, or Armor) and, for Outfit/Armor, a **Slot** each selection does a fresh live lookup of that specific layer/slot (independent of what’s actually visually showing) and auto-fills Override Type/ID/Tier with it, or with a placeholder if nothing’s active there. Use **Refresh Preview** if you changed gear without touching the Layer/Slot dropdowns. Adjust the Tier if you like, then press **Apply Override**. Choosing “(no override)” removes an existing override. || **Active Overrides** | Lists all currently active overrides with their keys, tier values, and tier labels. || **Reset** | **Reset All Overrides** removes every override and reverts to database defaults. The costume cache is not affected. |> **Tip:** Use `/styleids` to find worn armor style IDs, `/outfitids` for outfit collectible IDs, and `/costumeids` for the active costume’s collectible ID before entering values in the override editor.—## Adding / Editing Style DataAll style data lives in `LibArmorInsulation_StyleData.lua`.### Armor styles (`LibArmorInsulationData.Styles`)Keys are `ITEM_STYLE_*` integer constants. Full list: “`lua = { baseMaterial = “leather”, — string key from MaterialCoefficient table coverage = 1.0, — style-level coverage modifier flavorBonus = 0, — flat integer bonus/penalty (can be negative) flavorNote = “”, — human-readable reason shown in settings & /insulation},“`Any style not in the table falls back to “ (leather, coverage 1.0, no bonus → score 50).### Outfit styles (`LibArmorInsulationData.OutfitStyles`)Keys are **collectible IDs** (Collections system integers), not `ITEM_STYLE_*` values. The two number spaces are unrelated. Use `/outfitids` to find collectible IDs.“`lua = { baseMaterial = “leather”, coverage = 1.0, flavorBonus = 0, flavorNote = “”,},“`Falls back to “ (leather, coverage 0.9).### Costume & polymorph entries (`LibArmorInsulationData.CostumeInsulationById` and `CostumeInsulation`)`CostumeInsulationById` is keyed by collectible ID (preferred); `CostumeInsulation` is keyed by lowercase display name (legacy fallback). Both use flat `totalInsulation` values.“`lua = { totalInsulation = 72, flavorNote = “Heavy bear-fur costume” },– or by name: = { totalInsulation = 30, flavorNote = “Thin ceremonial cloth” },“`Special keys “ (50) and “ (38) are the last-resort fallbacks.—## ESO API Functions Used| Function | Source | Purpose ||—|—|—|| `GetActiveCollectibleByType(type)` | ESO | Detect active costume / polymorph || `GetCollectibleName(id)` | ESO | Resolve collectible display name for data lookup || `GetCollectibleId(catIndex, subIndex, index)` | ESO | Iterate collectibles for costume scanning || `GetCollectibleInfo(id)` | ESO | Read unlock state during `/scancostumes` || `GetNumCollectibleCategories()` | ESO | Enumerate categories in `/diagcollectibles` || `GetCollectibleCategoryInfo(catIndex)` | ESO | Get category name in `/diagcollectibles` || `GetEquippedOutfitIndex()` | ESO | Detect whether an outfit is actively worn (confirmed in-game) || `GetNumUnlockedOutfits()` | ESO | Count unlocked outfits (takes **no** arguments) || `GetOutfitName(outfitIndex)` | ESO | Outfit display name for `/outfitids` || `ZO_OUTFIT_MANAGER:GetOutfitManipulator(actorCategory, outfitIndex)` | ESO | Access outfit slot data (actorCategory is required) || `outfitManipulator:GetSlotManipulator(OUTFIT_SLOT_*)` | ESO | Access individual outfit slots || `slotManipulator:GetCurrentCollectibleId()` | ESO | Collectible ID on a given outfit slot || `GetItemLink(bagId, slotIndex, linkStyle)` | ESO | Item link string for a worn equipment slot || `GetItemLinkItemStyle(itemLink)` | ESO | Visual style ID for any item regardless of origin || `BAG_WORN` | ESO | Constant the equipped item bag || `EQUIP_SLOT_*` | ESO | Equipment slot constants || `OUTFIT_SLOT_*` | ESO | Outfit slot constants || `COLLECTIBLE_CATEGORY_TYPE_COSTUME` | ESO | Collectible category constant || `ZO_SavedVars:NewAccountWide(…)` | ESO | Account-wide saved variables || `EVENT_MANAGER:RegisterForEvent(…)` | ESO | Addon load event || `CHAT_SYSTEM:AddMessage(…)` | ESO | Chat output || `SLASH_COMMANDS` | ESO | Slash command registration || `LibAddonMenu2:RegisterAddonPanel(…)` | LAM | Settings panel registration || `LibAddonMenu2:RegisterOptionControls(…)` | LAM | Settings controls |> **`GetItemLinkItemStyle` vs `GetItemStyle`:** `GetItemStyle()` only returns non-zero for player-crafted items; every dropped, set, or Crown Store piece returns `ITEM_STYLE_NONE` (0). `GetItemLinkItemStyle(itemLink)` returns the correct visual style for all item origins and is the correct choice here.>> **`GetNumUnlockedOutfits()`:** Takes no arguments. A `GameplayActorCategory` parameter does not exist on this function. `GetNumOutfits()` is not a real ESO API function and will crash with “function expected instead of nil”.>> **`GetEquippedOutfitIndex()`:** The correct gate for the outfit path. Confirmed working in-game; returns the 1-based index of the worn outfit, or nil if none.—## Design Notes & Limitations**No per-item flavor text scraping.** ESO does not provide a Lua API to read raw item flavor text at runtime (the tooltip system renders it as formatted strings, not structured data). The `flavorBonus` values in the style database are therefore authored by hand based on in-game style descriptions and motif book lore.**Item set names are ignored.** The library uses only the base `ITEM_STYLE_*` of each piece, not the set it belongs to. Set bonuses are mechanical gameplay systems unrelated to visual insulation.**Outfit “no override” slots fall through.** If a player has an outfit active but has not overridden every slot, only overridden slots contribute from the outfit source. If *no* outfit slots are overridden, the library falls through to worn armor styles entirely.**Costume vs. outfit visual conflict.** If a player has both a costume collectible active and an outfit applied, the costume wins visually in-game (costumes always take priority). LibArmorInsulation mirrors this by detecting costumes before outfits.**Polymorphs override costumes.** A polymorph replaces the entire character model. LibArmorInsulation checks for polymorphs before costumes, consistent with ESO’s in-game visual priority.**Outfit collectible IDs ≠ ITEM_STYLE_* IDs.** Outfit slots yield Collections-system collectible IDs, which are an entirely separate number space from `ITEM_STYLE_*` integers. The library maintains separate lookup tables (`OutfitStyles` and `Styles`) for this reason, and the override key prefix (`outfit_` vs `style_`) distinguishes them in saved variables.**Costume cache is opt-in.** The `sv.costumeCache` table is only populated when you run `/scancostumes`. Until then, unrecognized costumes fall back to `DEFAULT_COSTUME` (50). Cache entries persist across sessions.**Saved variables version 4.** The upgrade path from v3 preserves existing overrides and `costumeCache`, and adds the missing `outfitStyleCache` table. The upgrade path from v2 preserves overrides and adds both cache tables. Saves from v1 are reset to defaults to avoid schema conflicts.—## Changelog### 2.7.5- **Fixed the settings panel’s author/version fields**, which were still the literal placeholder text `”YourName”` and a hardcoded `”1.0.0″` never actually updated even after the `## Author` manifest field itself was corrected. The panel now reads `author = “@Kreksar5 and Claude.ai”` and `version = LibArmorInsulation.VERSION`, and the library’s internal `ADDON_VERSION` constant (previously stale at `”2.7.0″`) is kept in sync with the manifest `## Version` going forward.### 2.7.4- **Promoted 4 costumes and 11 outfit styles from verified player overrides** into the hard-coded data tables (`CostumeInsulationById` and `OutfitStyles`), so these no longer rely on a per-account manual override or auto-rated cache guess: – `CostumeInsulationById` gained 4 entries (collectible IDs 12717, 1101, 12719, 286) with their confirmed `totalInsulation` values, each superseding a previous auto-rated cache guess. – `OutfitStyles` gained 11 entries (collectible IDs 4804, 4798, 4800, 9746, 7195, 8786, 11819, 11818, 11820, 11851, 5309). The final tier for each is confirmed correct (set manually by a player after observing the outfit in-game), but since this table stores `baseMaterial`/`coverage`/ `flavorBonus` rather than a direct tier, those fields were chosen only as the minimal combination that reproduces the confirmed tier they are **not** an independent material assessment, and the collectibles’ actual names/appearances haven’t been looked up yet. Flagged accordingly in each entry’s `flavorNote`.### 2.7.3- **Standardized the author credit** to `@Kreksar5 and Claude.ai` in the `## Author` manifest field and this README’s byline, and named Claude.ai specifically (rather than generic “AI assistance”) in the manifest description and the AI-assistance disclosure above, matching the crediting convention used across this addon’s companion libraries.### 2.7.2- **Corrected the `## Author` manifest field**, which was still the literal placeholder text “YourName” left over from the manifest template never actually filled in. Fixed to the real author.### 2.7.1- **Full API audit against the official ESOUI API 101050 documentation.** Every function call, method call, and constant referenced across the library was cross-checked against the API doc and, where the doc didn’t cover it (manager singletons, third-party libraries), against the live ESOUI source. No invalid or deprecated API usage found `ZO_OUTFIT_MANAGER` and its `GetOutfitManipulator`/`GetSlotManipulator`/`GetCurrentCollectibleId` chain, and the `LibAddonMenu`/`LibSavedVars` calls, are all legitimate and correctly used. No code changes required.### 2.7.0- **Override editor redesigned around explicit Layer/Slot dropdowns.** Replaced the auto-detected “currently active item” list (and the 2.6.3 background poll that tried to keep it in sync) with two small, permanently static dropdowns: **Layer** (Costume/Polymorph, Outfit, Armor) and **Slot** (Head/Shoulders/Chest/Hands/Waist/Legs/Feet, disabled for Costume/Polymorph since that’s whole-body). Picking either does a FRESH live lookup at that exact moment via three new independent Calculator functions `Calc.ResolveCostumeOrPolymorph()`, `Calc.ResolveOutfitSlot()`, `Calc.ResolveArmorSlot()` each of which reads live game state directly and completely ignores ESO’s usual visual precedence. This means you can now inspect (and override) your Armor style on a slot even while a costume is actively displayed instead, or check what your Outfit has set for a slot regardless of what’s currently showing. If a layer/slot has nothing active (e.g. Costume picked while no costume is worn, or an empty armor slot), a placeholder tier and an explanatory note are shown instead of leaving the fields blank. A **Refresh Preview** button re-runs the same live lookup for whenever gear changes without touching either dropdown.- **Root-cause bug fix: Settings panel re-registration was silently a no-op.** The options table powering the whole Settings panel was declared as `local optionsTable = { …, func = function() … optionsTable … end, … }`. In Lua, a local variable’s scope begins only AFTER its declaration statement finishes, so any closure written INSIDE that table constructor which refers to `optionsTable` which is exactly what the Refresh/Apply Override/Reset buttons did to push a rebuilt panel back to LibAddonMenu actually resolved to a global of that name (`nil`), not the local table being built. Every one of those buttons had therefore been calling `LAM:RegisterOptionControls(Settings.panelId, nil)` this whole time. This is almost certainly the real reason the Settings panel never seemed to refresh, going back to before the tier-system rewrite. Fixed by forward-declaring `local optionsTable` on its own line before assigning the table to it, which is the standard Lua idiom for self-referencing structures; verified with a minimal isolated reproduction before and after the fix, and with an end-to-end test through the actual button handlers.### 2.6.3- **Background auto-refresh for the “currently active item” dropdown.** Previously the list only reflected equipped gear/costume/outfit at the moment the addon loaded, or whenever Refresh/Apply Override/Reset was pressed changing costume or outfit mid-session left it stale until one of those was clicked. Added a lightweight poll (`EVENT_MANAGER:RegisterForUpdate`, every 2 seconds) that compares a cheap fingerprint of “what’s currently resolving” (source + costume/polymorph ID + each slot’s collectible/style ID) against the last-seen one, and only pushes a rebuilt options table back to LibAddonMenu when something actually changed. This deliberately avoids hooking any specific ESO gear/costume-changed event, since there’s no single confirmed event that reliably fires for every costume/outfit/armor change alike and this addon’s data tables hold to a no-unverified-API-constants standard polling a signature built from data this file already computes gets the same result using only a bedrock-stable API. Updates land within ~2 seconds of a costume/outfit/armor change, whether or not the Settings panel happens to be open at the time.### 2.6.2- **Bug fix: costume/polymorph misclassification after applying an override.** Costumes and polymorphs share the same override key namespace (`costume_`) and the same detection path (`GetActiveCollectibleByType`), since ESO has no separate `COLLECTIBLE_CATEGORY_TYPE_POLYMORPH`. A prior fix that let polymorph overrides win over the data table accidentally checked `if polymorphOverride or polymorphEntry then` meaning applying an override to a *plain costume* made it get misclassified as a polymorph on the very next lookup (`result.source` flipped from `”costume”` to `”polymorph”`, and the breakdown slot key flipped from `””` to `””`). This is what caused the “Prefill from currently active item” dropdown in Settings to mislabel a costume as a “Polymorph” once you’d set an override on it. Classification now comes ONLY from table membership (`PolymorphInsulationById`/`PolymorphInsulation`), independent of whether an override exists; the override still applies to the resolved tier either way. The insulation *value* was never wrong only the source/label but the label feeds directly into the prefill dropdown and `/insulation`/`/costumeids` output, so this is worth updating for.### 2.6.1- **Override editor prefill.** Added a “Prefill from currently active item” dropdown above the Override Type/ID fields, listing whatever costume, polymorph, outfit piece, or armor style is *actually resolving right now* using the exact same precedence `GetInsulationBreakdown()` uses (polymorph/ costume beats outfit beats worn armor; an outfit slot with no style set falls back to the armor style showing through). Picking an entry auto-fills Override Type, the ID field, and the Insulation Tier dropdown with that item’s current resolved values, and shows the game’s own display name (`GetCollectibleName()` for outfits/costumes, the resolved English style name for armor) so there’s no need to cross-reference `/styleids`, `/outfitids`, or `/costumeids` by hand. “(manual entry)” remains available as the first choice for typing an arbitrary ID. The list refreshes whenever the panel opens, when **Refresh** is pressed, when an override is applied, or when overrides are reset.### 2.6.0- **Staggered tier system.** Replaced the free-floating 0100 continuous scale with eleven fixed tiers, staggered in increments of 10 from -10 to 90 (Magically Cooled, No Insulation, Minimal, Light, Coarse Light, Layered/Leather, Full Leather/Light Metal, Heavy Leather/Fur, Full Fur/Metal, Heavy Fur/Metal, Magically Heated). Every style, outfit piece, costume, and polymorph now resolves to one of these tiers via `Calc.SnapToTier()`. `-10`/`90` are reserved for entries flagged `magical = true` (Flame Atronach, Ice Wraith); everything else is clamped to the mundane 080 range before snapping.- **Per-slot percentage adjustment.** A style/outfit piece’s tier is now a full-body reference value; individual slots contribute a *percentage* of that tier based on body coverage (`slot_contribution = round(tier slotPercentage)`). `SlotCoverage`/`OutfitSlotCoverage` were rebalanced from summing to 0.90 up to exactly 1.00, so a full matching set reproduces its tier exactly as the total. Costumes and polymorphs are **not** slot-adjusted their snapped tier is the total, unadjusted, since they’re whole-body.- **Dropdown-based override editor.** The Settings panel’s “Insulation value” free-text editbox was replaced with an “Insulation tier” dropdown listing the eleven tiers by name, so an override can never drift off-tier. Programmatic `SetOverride()` calls snap any value passed in to the nearest tier instead of clamping 0100; `nil` (not `0`) now clears an override, since `0` is a legitimate tier (“No Insulation”).- **Saved-variable migration (v4 → v5).** Existing overrides from the old 0100 scale are snapped onto the nearest tier on first load rather than being discarded, preserving prior manual tuning as closely as the new scale allows.- **Bug fix:** `NearestMaterialForTarget()` (used by `/scanoutfitstyles` to guess a base material for unrecognized outfit pieces) was missing the 0.90 slot-weight-sum factor present in every other full-body reference calculation in this file, so its reference numbers (fur=100, leather=55.6, …) didn’t match the documented full-set reference table (fur=90, leather=50, …). Fixed to multiply by 0.90 like everywhere else.- `GetInsulationForStyle()` now simply delegates to the new `Calc.GetStyleTier()` instead of duplicating the formula.- Version bumped to 2.6.0 (`AddOnVersion: 8`), `SAVED_VARS_VERSION` to 5.### 2.5.3- **Corrected `LibAddonMenu-2.0` dependency floor**: was mistakenly bumped to `>=45` in 2.5.1, but LibAddonMenu’s own manifest documentation shows `43` as the latest available version, not `45`. Fixed to `>=43`. The 2.5.1 entry below has also been corrected to reflect the right number.### 2.5.2- **”What addons cannot do” compliance verified** against the actual ESOUI rules text (previously unverifiable due to a fetch issue with that specific thread see 2.5.1’s note). Checked all 24 prohibited-behavior items: this addon doesn’t touch the character-select/crown-store/scrying/Tribute UI, doesn’t read other players’ or NPCs’ positions, doesn’t change any visual effect/texture/sound/nameplate/camera/tooltip, doesn’t move/cast/interact with anything, doesn’t touch quickslot items, doesn’t write outside `SavedVariables`, doesn’t talk to external web services, and doesn’t share data between players. It’s a pure read-only calculator using documented API functions (the explicitly sanctioned “what addons could do” item #7), plus a settings panel and slash commands. **No code changes were required.** – Specifically confirmed: `CHAT_SYSTEM:AddMessage()`, used throughout this addon’s slash commands, is the standard local-only system-message print and is **not** the prohibited “send messages to chat directly” behavior (that rule targets auto-sending player-authored text into channels other players see, e.g. simulating Enter on `/say` or guild chat this addon never does that).### 2.5.1- **ESOUI release-rules compliance pass**, checked against the ESOUI “Please read: Before you release a new/update your addons” guidelines: – **AI-code disclosure added.** Per the rule requiring AI involvement to be named at the top of the addon description when the AI-written code/data hasn’t been independently validated, added a disclosure to both the manifest `## Description` and the top of this README. Most of this addon’s commands and data tables were built with AI assistance and are not yet confirmed working/performant in actual gameplay. – **Added the missing `## AddOnVersion` manifest tag.** Libraries need this so dependent addons can use `DependsOn: LibArmorInsulation>=N` version checks (the same mechanism this addon already uses for its own `LibAddonMenu-2.0` dependency). Starting value: `6` (one per tracked release so far); increment by 1 on every future release regardless of the semantic `## Version` string. – **`## APIVersion` updated** from the stale `101040` to `101049 101050` (current Live and PTS as of this pass), so the addon no longer shows as “Outdated” in-game. – **`LibAddonMenu-2.0` dependency floor bumped** from `>=33` to `>=43`, matching the version explicitly cited as current in the ESOUI rules thread at time of this pass. `>=` (rather than no version check) is required so the addon doesn’t silently load against a pre-Summerset LibStub-only build of LAM. – **Reviewed for global variable leaks** none found. The codebase already follows the recommended single-global-table pattern (`LibArmorInsulation`, `LibArmorInsulationData`, `LibArmorInsulationCalc`, `LibArmorInsulationSettings`), with all other identifiers declared `local`. – **Not independently verified this pass:** the “What AddOns must not do” rules thread (linked from the same guidelines post) could not be fetched to confirm compliance line-by-line at the time. **Resolved in 2.5.2** once the actual rules text was provided directly see that entry for the confirmed result.### 2.5.0- **152 manually-researched costume entries added to `CostumeInsulation`.** Sourced from UESP search-result snippets (direct page fetches are blocked by UESP’s bot detection, so coverage is best-effort rather than exhaustive roughly 134 of ~308 total ESO costumes were found with usable description text; the rest were left for `/scancostumes` to auto-rate). Each entry’s `flavorNote` carries a “ tag: – **high** the source text stated an explicit material (e.g. “studded leather doublet,” “Scaly Cloth Scraps,” “Fighters Guild Cool-Weather Gear”). – **medium** a strong contextual/regional inference (e.g. a scout outfit explicitly tied to a named cold-climate zone). – **low** a thematic guess with no explicit material cue in the source; these are reasonable starting points but are good candidates for manual re-verification, and `/scancostumes` will not override them since `CostumeInsulation` now outranks the scanner cache (see below). – One entry (**Old Orsinium Sentry**) corrects an earlier same-session guess after better source text was found later in the research pass.- **Costume resolver priority reordered.** `CostumeInsulation` (this manually-curated table) now outranks `sv.costumeCache` (the `/scancostumes` runtime cache) in `GetInsulationBreakdown()`. New priority order: user override → `CostumeInsulationById` → `CostumeInsulation` → `sv.costumeCache` → `DEFAULT_COSTUME`. Previously the scanner cache outranked this table, which meant a manually-verified entry could be silently shadowed by a coarser auto-rated guess.- **`OutfitStyles` gains a `Styles` fallback.** Most outfit-style collectibles are account-wide unlockable versions of existing crafting motifs, just reached through a different ID space. `GetOutfitStyleData()` now resolves an unrecognized collectible ID’s name via `GetCollectibleName()` (stripping a trailing `” Style”` suffix) and checks `Styles` before falling back to the `/scanoutfitstyles` cache so a style whose name matches an existing motif entry needs no new per-ID data at all. `/scanoutfitstyles` reports these as “ in its output.- **9 new motifs added to `Styles`** to close a coverage gap found while researching outfit styles: Swordthane, Dark Executioner, Necrom Armiger, Order of the Lamp, Ancient Mirrormoor, Companion Revelry, Fharun Moonlight, Chosen of Anu, Chosen of Padomay. These are Crown Crate/Collector’s Edition unlocks rather than world-found motif books, so they postdate the original “Motifs 1129” coverage. Material assignments are UESP-sourced where the style explicitly resembles an existing entry (e.g. Dark Executioner → resembles Dark Brotherhood armor); the rest are lower-confidence thematic inferences from cosmic-duality/regional lore with no explicit material description available.### 2.4.0- **`/scancostumes` now scans description text, not just name.** `AutoRate` checks the costume’s name against the keyword list first (names are usually more deliberately worded), then falls back to `GetCollectibleDescription()` flavor text if the name has no hit. Each cache entry now records a `matchSource` (`”name”`, `”description”`, or `”none”`) so genuinely unmatched entries sitting on the generic 50 fallback can be identified.- **New `/scanoutfitstyles` command.** Outfit style pages had no auto-detection path at all (`OutfitStyles` was a hand-only stub table). This walks every unlocked outfit’s 7 slots (same enumeration as `/outfitids`) and, for any collectible ID not already in `OutfitStyles`, keyword-rates it via name + description and writes a guessed `{baseMaterial, coverage, flavorBonus}` into the new `sv.outfitStyleCache`. `GetOutfitStyleData()` now checks this cache as a fallback before `OutfitStyles`.- **New `/costumesneedreview` and `/outfitstylesneedreview` commands.** Filter each respective cache down to entries where the keyword scan found no match in either name or description a short worklist for manual UESP-backed overrides instead of scrolling the full scan output.- **Shared keyword table.** `KEYWORD_RATINGS` and `AutoRate` were hoisted out of `/scancostumes` to file scope so `/scanoutfitstyles` draws from the same list a new pattern only needs adding once.- **Removed an unused dynamic costume-discovery path.** An earlier in-progress approach (`BuildCostumeKeywordMap()`, brute-force probing every collectible ID 1→N) was removed before release it would have silently outranked the better-designed `/scancostumes` + `sv.costumeCache` resolution order. Not shipped in any prior version; mentioned here for the record.- **Saved variables bumped to version 4;** v2/v3 saves are migrated automatically, preserving existing overrides and caches.### 2.3.0- **Name-keyed style table.** `LibArmorInsulationData.Styles` is now keyed by the English name returned by `GetItemStyleName()` (e.g. “, “) instead of raw `StyleItemIndex` integers. This mirrors the zone-ID lesson: style integers can be reassigned between ESO API updates, but the English name is stable.- **Runtime ID maps built at login.** `LibArmorInsulationCalc.BuildStyleIdMaps()` is called during `EVENT_ADD_ON_LOADED`. It iterates `GetItemStyleName(i)` for `i = 1, GetHighestItemStyleId()` and populates two tables: – `LibArmorInsulationData.StyleIdByName` `{ = 5, }` – `LibArmorInsulationData.StyleNameById` `{ = “Nord”, }` These maps are rebuilt every login from live game data, so any future ZOS reassignment of integer IDs is handled automatically without a data-table update.- **Lookup chain in Calculator.** All style lookups now follow: `styleId → StyleNameById → Styles → DEFAULT`. The integer from `GetItemLinkItemStyle()` is still accepted everywhere in the public API; it is resolved to a name internally and never stored as a persistent key.- **`styleName` added to breakdown results.** Each slot entry in `GetInsulationBreakdown().slots` now includes a `styleName` field (string or nil) alongside the existing `styleId`, so callers can display a human-readable name without performing their own lookup.- **Override keys unchanged.** Saved-variable override keys remain `”style_N”` (integer-based) because the player set them against a specific integer at a known point in time. They continue to work the integer is used only as a unique token for the saved-variable key, not for a data-table lookup.### 2.2.0- **Full style coverage:** `LibArmorInsulationData.Styles` now contains entries for all crafting-motif style IDs known as of ESO Update 49 (motifs 1129, IDs 1129). Previously only ~67 IDs were populated; ~62 motifs from the Thieves Guild, Dark Brotherhood, Morrowind, Summerset, Elsweyr, Greymoor, Blackwood, High Isle, Necrom, and Gold Road chapters were missing entirely.- **Corrected several ID-to-name mappings** that were shifted by one due to a miscount of the gap between the racial styles (110) and the first post-racial motifs: – Telvanni was “; corrected to “ (Motif 50). – Dragonscale was “; ID 36 is Dark Brotherhood (Motif 36). Dragonscale is not a craftable motif removed; dragon-scale aesthetics are covered by individual dungeon-set pieces with no motif ID. – Snowhawk “ was an invention with no confirmed ITEM_STYLE_* counterpart; Snowhawk is an **outfit-style collectible only** (not a motif). Entry removed from `Styles`; use the `OutfitStyles` collectible table instead. – IDs 8089 ancestral styles renumbered to match confirmed Motifs 8795. – IDs 90105 updated to match Greymoor / Blackwood / High Isle motif numbering.- **Zone ID statement evaluated:** The claim that “ESO zone IDs are large non-sequential integers the only stable identifier is the English zone name `BuildZoneIdMaps()` inverts the name→ID mapping” does **not apply to style IDs** and has **no relevance to this library**. Style IDs (`StyleItemIndex` / `ITEM_STYLE_*`) are small sequential integers starting at 1 and are stable across API updates the exact opposite of zone IDs. This library does not use `LibZone`, `BuildZoneIdMaps()`, or any zone-ID machinery. No changes were required.### 2.1.0- Outfit slots now look up insulation by **collectible ID** via `ZO_OUTFIT_MANAGER` rather than by `ITEM_STYLE_*` ID, matching how ESO actually stores outfit style data internally.- Added `LibArmorInsulationData.OutfitStyles` table (keyed by collectible ID) separate from `Styles` (keyed by `ITEM_STYLE_*`).- `SetOverride` now accepts an `idType` parameter (`”style”`, `”outfit”`, `”costume”`) to disambiguate the three ID spaces.- Added `sv.costumeCache` a persistent per-account cache populated by `/scancostumes`.- New slash commands: `/costumeids`, `/scancostumes`, `/clearcostumecache`, `/outfitids`, `/outfitactive`, `/diagcollectibles`.- Added `LibArmorInsulationData.CostumeInsulationById` (collectible ID keyed) alongside the existing name-keyed `CostumeInsulation` table.- Saved variables bumped to version 3; v2 saves are migrated automatically.- Detection of active outfit changed from `GetActiveOutfitIndex()` to `GetEquippedOutfitIndex()` (confirmed correct ESO API function).### 1.0.0- Initial release.—## LicenseMIT free to use, modify, and redistribute with attribution.

0

Frostfall (3.4.11)

# Frostfall Temperature System for ESO### Version 3.4.11 | Inspired by Frostfall (Skyrim)*by @Kreksar5 and Claude.ai*> Thematically inspired by *Frostfall*, the well-known Skyrim mod by> **Chesko** name and concept used as an homage, **not a port, and not> affiliated with or endorsed by Chesko or Frostfall’s other contributors.**> **AI-ASSISTED ADDON.** Written with Claude.ai. Core mechanics have been> iteratively refined and bug-fixed across many versions, but this should> still be treated as not fully independently validated in-game until> confirmed through extended play-testing.—## Credits- **Frostfall Hypothermia Camping Survival** (the Skyrim mod) by **Chesko**: the name and the general hypothermia/insulation concept are used as a direct homage. This addon is an original implementation built for ESO’s own API and mechanics no code, assets, or data from the Skyrim mod were used or could be (different engine, different game).- **RolePlayNeeds Tamriel Survival!** by **matheusbk2**: two implementation details were confirmed by inspecting its actual published source (checked directly against the official v0.7 BETA release) the `EVENT_LOOT_RECEIVED` argument signature (position 5, not 6, is the item-type integer), and the disease-overlay window construction pattern (`CreateTopLevelWindow` → `SetAnchorFill()` → `SetMouseEnabled(false)` → child `CT_TEXTURE` with its own `SetAnchorFill()`, alpha controlled on the parent window) that this addon’s hot/cold overlays follow. No code was copied; Frostfall is an original implementation. **Correction:** a third item a `RPN_REAGENT_TRAITS` static item-ID lookup table for alchemy traits was previously credited to RolePlayNeeds here and in the v3.3.0 notes below. That table does not exist in RolePlayNeeds’ published source; RolePlayNeeds has no reagent-trait handling at all. This addon’s `FV.SPELL_RESIST_REAGENT_IDS` table is an independent lookup this project built itself it was mistakenly attributed to RolePlayNeeds (likely confused with a local, personally- modified copy of RolePlayNeeds that was never published), and the credit has been removed.### Overlay art creditThe hot/cold screen-overlay images (`HOT_OVERLAY.dds`, `COLD_OVERLAY.dds`)were generated using AI text-to-image tools (https://perchance.org/ai-text-to-image-generator) and Google’sGemini Image Creator and edited/converted to the game’s `.dds` formatusing Paint.NET. They are not hand-drawn or sourced from ESO’s own artassets.—## OverviewFrostfall adds a fully-featured ambient temperature and survival system to Elder Scrolls Online. Every zone has an estimated ambient temperature based on its lore and biome. Your armor, costume, and outfit style all contribute **insulation**. Gear sets grant insulation bonuses (or penalties). Swimming affects your effective temperature. At temperature extremes, screen overlays and emotes bring the experience to life.**Insulation semantics:** High insulation traps body heat excellent in cold zones, but causes overheating in hot zones. Low insulation lets heat escape comfortable in heat, but leaves you exposed to cold.—## What’s New### v3.4.11 documentation accuracy passA full review of this README against the actual current code and againstLibZoneTemp/LibArmorInsulation’s real current data (the developer suppliedthe official RolePlayNeeds release for direct comparison). Found and fixed:- **RolePlayNeeds misattribution**: a `RPN_REAGENT_TRAITS` static item-ID lookup table was credited to RolePlayNeeds no such table exists in RolePlayNeeds’ published source (confirmed against the official v0.7 BETA release; RolePlayNeeds has no reagent-trait handling at all). This addon’s own `FV.SPELL_RESIST_REAGENT_IDS` table is an independent lookup this project built itself. The `EVENT_LOOT_RECEIVED` argument-signature and overlay-window-anchoring credits were checked too and are genuinely accurate kept as-is.- **Zone Temperature Reference table was completely wrong** every one of the 17 listed values was inaccurate, most by 3080C (e.g. Coldharbour listed as 2C, actually -8C; The Deadlands listed as 85C, actually 54C). Rebuilt from `LibZoneTemp.lua`’s actual `ZONE_BASE_TEMPS_BY_NAME` table. Also corrected the “80+ zones” / range claims in the Features overview (actually 1,000+ zones and sub-zones, -16C to 55C).- **Armor Insulation Reference table was from before the v2.6.0 staggered-tier rewrite** raw pre-snap scores that no longer correspond to any real output of the current formula, plus four listed styles/costumes (Voidsteel, Nightmare, Soul Shriven, Bear Raiment Costume) that don’t exist anywhere in the current data. Rebuilt with real entries and tiers computed through the actual current formula and `Calc.SnapToTier()`.- **Thermal direction was backwards for several Daedric-aligned pieces**: Daedric, Ancient Daedric, Dremora, and Waking Flame were all described as heat-generating with above-average insulation; the actual code has all four with a *negative* `flavorBonus` (explicitly cold-themed flavor text), landing them at or near the bottom of the range, not the top.- **Removed an entirely fictional “Set Insulation Bonuses” feature** a full section describing gear sets granting flat insulation bonuses, “detected via LibArmorInsulation” with its own config panel. No part of this exists in either addon: no set-detection code, no bonus data table, no such config panel. Also removed the matching “active set bonus” claim from the HUD Display section.- **Corrected the claimed cultural-origin insulation ordering** (“Nord > Orc > Breton > Imperial > Khajiit > Argonian”) the real computed order is Nord > Breton > Khajiit/Argonian/Orc (tied) > Imperial.### v3.4.10 settings-panel sync- **Fixed the settings panel’s author/version fields**, which were out of sync with the manifest and README: `author` incorrectly read “Frostfall” (the addon’s own title) instead of the actual author, and `version` was hardcoded to a stale `”3.4.2″` (the internal `FV.VERSION` constant was also stale, at `”3.4.4″`). The panel now reads `author = “@Kreksar5 and Claude.ai”` and `version = FV.VERSION`, and `FV.VERSION` itself is kept in sync with the manifest `## Version` going forward.### v3.4.9 overlay art credit- **Added an “Overlay art credit” note** to the Credits section, crediting the Perchance AI Text-to-Image Generator and Google’s Gemini Image Creator for generating `HOT_OVERLAY.dds` and `COLD_OVERLAY.dds`, and Paint.NET for editing/converting them to the game’s `.dds` format.### v3.4.8 author credit- **Standardized the author credit** to `@Kreksar5 and Claude.ai` in the `## Author` manifest field and this README’s byline, and named Claude.ai specifically (rather than generic “AI assistance”) in the manifest description and the AI-assistance disclosure above, matching the crediting convention used across this addon’s companion libraries.### v3.4.7 non-affiliation disclaimer- **Added an explicit “not a port, not affiliated with or endorsed by Chesko” disclaimer** for the Skyrim mod *Frostfall*, matching the disclaimer Realistic Needs and Diseases already carries for its own Skyrim namesake. This addon reuses Chesko’s mod name and general concept as a homage Chesko’s own permissions pages ask to be contacted before the mod’s name or work is reused elsewhere, so this addon now says plainly, in both the manifest description and this README, that it is an independent, unaffiliated ESO implementation with no shared code or assets (impossible between these two games’ engines regardless).- **Expanded the Credits section** to name Chesko and the Skyrim mod directly, rather than only crediting RolePlayNeeds for implementation details.### v3.4.6 ESOUI release-rules compliance pass- **Corrected the `## Author` manifest field**, which incorrectly read “Frostfall” (the addon’s own title) instead of the actual author.- **Added the required `## AddOnVersion` tag** (previously missing entirely this is the integer the ingame addon manager and Minion use to detect updates, separate from the informational `## Version` tag). Started at 6, comfortably above the `>=3` floor that Realistic Needs and Diseases’ `OptionalDependsOn` line already checks for.- **Added a version floor (`>=1`) to the `LibClockTST` dependency**, which previously had none.- **Added the required AI-assistance disclosure** to the manifest description and this README, per ESOUI’s addon release rules.- **Added a Credits section** naming RolePlayNeeds (matheusbk2) for the implementation details referenced during development.### v3.4.5 API compliance audit- **Full API audit against the official ESOUI API 101050 documentation.** Every function call, method call, and constant referenced across the addon was cross-checked against the API doc and, where the doc didn’t cover it (manager singletons, `ZO_` helpers, third-party libraries), against the live ESOUI source.- **Removed the entire weather feature** (`FV:UpdateWeatherState`, `FV:OnWeatherChanged`, the `EVENT_WEATHER_CHANGED` registration, and the precipitation-drag term in the temperature drift calculation). Neither `EVENT_WEATHER_CHANGED` nor any of the six `WEATHER_*` constants (`WEATHER_RAIN`, `WEATHER_SNOW`, `WEATHER_THUNDER`, `WEATHER_ASHCLOUD`, `WEATHER_FOG`, `WEATHER_CLOUDY`) exist anywhere in the ESO addon API ESO does not expose live weather state to addons at all, so this feature could never have worked. Worse, registering for a `nil` event code at load time risked erroring out of the whole `OnPlayerActivated` init sequence, breaking the drift-update timer and emote-loop registrations that ran after it. Removed the now-dead `isRaining`/`isSnowing`/`isStorming`/ `isSunny`/`weatherType` state fields and updated `/ff status`, the debug log line, and this README to match.- Everything else checked out: `EVENT_MANAGER`, `WINDOW_MANAGER`, `SCENE_MANAGER`, `PLAYER_EMOTE_MANAGER`, `ZO_Alert`, `ZO_PreHook`, and all LibAddonMenu/LibSavedVars/LibZone/LibClockTST calls are legitimate and correctly used.### v3.4.4 dependency version correction- **Corrected `LibAddonMenu-2.0` dependency floor**: was mistakenly bumped to `>=45` in 3.4.3, but LibAddonMenu’s own manifest documentation shows `43` as the latest available version, not `45`. Fixed to `>=43`. The 3.4.3 entry below has also been corrected to reflect the right number.- **`LibZoneTemp` dependency floor bumped** from `>=9` to `>=11`, following LibZoneTemp’s own version corrections in the same vein.### v3.4.3 ESOUI compliance pass- **Fixed a manifest bug: 5 separate `## DependsOn:` lines consolidated into 1.** Per the addon manifest spec, multiple non-optional dependencies must be space-separated on a single `## DependsOn:` line; repeating the directive across several lines risks the manifest parser only honoring the last occurrence, which would have silently dropped the `LibClockTST`, `LibAddonMenu-2.0`, `LibZone`, and `LibZoneTemp` checks (leaving only `LibArmorInsulation` actually enforced).- **Added missing version floors** (`>=`) for `LibAddonMenu-2.0` (`>=43`), `LibZoneTemp` (`>=9`), and `LibArmorInsulation` (`>=7`), matching their current `## AddOnVersion` values. `LibClockTST` still has no version floor its current `AddOnVersion` wasn’t available to check during this pass; recommend confirming and adding one.- **`## APIVersion` updated** from the stale `101043` to `101049 101050` (current Live/PTS), and the README’s compatibility section synced to match.- **Reviewed for global variable leaks and “what addons cannot do” compliance** none found. The reagent-consumption mechanic only *listens* for `EVENT_INVENTORY_SINGLE_SLOT_UPDATE` after the player manually eats/uses something; it never calls `UseItem` or any consume/cast/interact function itself, so it doesn’t touch the quickslot-automation restrictions.### v3.4.2- **Reagent consumption detection now ignores bank activity.** Withdrawing or depositing a reagent from the personal bank or guild bank fires the same `EVENT_INVENTORY_SINGLE_SLOT_UPDATE` as eating it, so the spell-resist buff trigger is now also gated off while either bank window is open (`EVENT_OPEN_BANK`/`EVENT_CLOSE_BANK`, `EVENT_OPEN_GUILD_BANK`/`EVENT_CLOSE_GUILD_BANK`), matching the existing merchant/crafting-station gating.### v3.4.1 (bugfix)- **Fixed: reagent consumption detection was completely broken.** `GetMedicinalUseRank()` (used to scale the spell-resist buff’s duration) called `GetCraftingSkillLineIndices()` and referenced a `SKILL_TYPE_CRAFTING` constant neither exists in the ESO UI API. The resulting Lua error aborted the whole consumption handler before it could ever apply the buff, so eating a qualifying reagent did nothing. Replaced with `GetNumSkillLines(SKILL_TYPE_TRADESKILL)` + `GetNumSkillAbilities()` + `GetSkillAbilityInfo()`, all verified directly against esoui/esoui’s `ESOUIDocumentation.txt`.### v3.4.0- **Spell-resist reagent buff completed** added the remaining two confirmed item IDs (Clam Gall `139020`, White Cap `30154`) to `FV.SPELL_RESIST_REAGENT_IDS`, alongside Bugloss and Mudcrab Chitin from 3.3.0. All four canonical “Increase Spell Resist” reagents (per UESP) now trigger the buff.### v3.3.0- **New: Spell-resist reagent temperature buff** consuming an alchemy reagent with the “Increase Spell Resist” trait (Bugloss, Clam Gall, Mudcrab Chitin, White Cap) steadies the player’s effective temperature toward neutral (22C, the midpoint of the comfortable band), capped at a 10C shift in either direction. – Lasts 30 real-world minutes, extended by 10%/20%/30% if the player has rank 1/2/3 of the Alchemy passive **Medicinal Use**. – Eating another qualifying reagent while the buff is active resets the timer instead of stacking. – Fires a fade warning once per minute during the last 5 minutes of the buff. – The steadying offset is **recalculated live** from the player’s current real temperature differential every time it’s applied it is not a fixed snapshot taken at the moment the reagent was eaten, so it keeps tracking the player’s true temperature as they move through zones/weather while the buff is up. – Uses a static item-ID lookup table (`FV.SPELL_RESIST_REAGENT_IDS`) built for this addon, since alchemy trait APIs only work at an open crafting station. *(Corrected: this was previously described as following the same pattern as RolePlayNeeds’ “`RPN_REAGENT_TRAITS`” no such table exists in RolePlayNeeds’ published source; see the correction in Credits above.)* – Internally, player temperature is now split into a “true” physical value (driven by ambient/weather/swim drift, unaffected by the buff) and an effective/displayed value (`FV:GetEffectiveTemp()`) that HUD, overlay, emotes, and band alerts all read from.### v3.2.0- **ConfigMenu synced with Frostfall.lua thresholds** the emote and threshold descriptions in the settings panel now reflect the correct v3.1.5 values (HOT 35C/95F, HEAT_DANGER 41C/105F) instead of the old stale values (27C/80F and 38C/100F).- **Slash command renamed: `/fv` → `/ff`** The short-form slash command is now `/ff` to avoid conflicts. `/frostfall` continues to work as before.- **ConfigMenu panel version updated** The LAM panel version string now correctly reads `3.2.0`.### v3.1.5 (included in this release)- Updated all temperature thresholds to more logical/reasonable values: – `COMFORTABLE_LO` raised from 16C → 20C (61F → 68F) – `COMFORTABLE_HI` raised from 26C → 24C (79F → 75F) *(reordered now correctly below WARM)* – `WARM` raised from 21C → 26C (70F → 79F) – `HOT` raised from 27C → 35C (80F → 95F) – `HEAT_DANGER` raised from 38C → 41C (100F → 105F)- Fixed band-transition comparison operators (`<` → `<=`) so boundary temperatures are correctly classified.- OverlayEffects: pre-computes both cold and hot alpha before applying either, eliminating a mutual-exclusion bug that could mask the hot overlay.- OverlayEffects: hot overlay comments and ramp references updated to match the new HOT (35C) and HEAT_DANGER (41C) thresholds.### v3.1.4- Fixed water loot handler was reading the 6th `EVENT_LOOT_RECEIVED` argument instead of the correct 5th (`itemType`). Now matches RolePlayNeeds exactly.—## Features### Zone Temperature System- **1,000+ zones and sub-zones** have carefully estimated base temperatures in C- Temperatures range from Icereach (-16C) to City of Ash II (55C) see the corrected reference table below for a curated selection of overland zones- Zone temperature provided by **LibZoneTemp**### Armor & Costume InsulationPriority order (first match wins):1. **Costume** Crown Store cosmetics; insulation based on material and coverage2. **Outfit Style** Outfit system style overrides; checks chest slot style3. **Base Armor Style** Your equipped armor’s crafting style**100+ styles** have insulation values calculated from the **style** alone (not the set name):- Skin coverage (how much of the body is covered)- Material (fur/hide > plate > leather > cloth > silks)- Cultural origin climate *(corrected: previously listed as “Nord > Orc > Breton > Imperial > Khajiit > Argonian”, but the real computed tier order is Nord (80) > Breton (50) > Khajiit/Argonian/Orc (30, tied) > Imperial (20) Orc and Imperial were both misplaced)*- Magical/special thermal properties (a small number of Daedric-aligned and undead-adjacent pieces are flavor-adjusted **colder**, not hotter see below)Certain unique pieces have **flavor-adjusted** insulation based on theirin-game descriptions. *(Corrected: this list previously claimed several ofthese were heat-generating and gave one nonexistent-style example; theactual code has the opposite thermal direction for the Daedric-alignedpieces, and three of the four “very low insulation” examples don’t existin the current data at all.)*- **Daedric / Ancient Daedric / Dremora / Xivkyn / Stalhrim Frostcaster** described in-code as radiating unnatural **cold**, not heat → these land at or near the bottom of the mundane range (tier 010), not the top- **Waking Flame** despite the fire theming, its actual flavor bonus is a small negative one (“carries a mild chill”) → mid-range tier (50), not especially warm- **Flame Atronach (costume)** living flame → clamped to the maximum tier (90, not 95 the raw 92 score is capped by `Calc.SnapToTier`)- **Frost Atronach (costume) / Ice Wraith (polymorph)** living ice/frost → clamped to the minimum tier (-10), the coldest a mundane or magical source can register- **Apostle** despite the “regulated temperature design” flavor text, its actual tier (30) is below the 50 midpoint, not neutral- *(Voidsteel, Nightmare, and Soul Shriven previously listed here as very-low-insulation examples do not exist anywhere in the current style/costume/polymorph data. The closest real match to “Soul Shriven” is the “Soul-Shriven” style, tier 10, no flavor bonus.)**(**Removed: “Set Insulation Bonuses” section.** This README previouslydescribed a whole feature here a table of specific gear sets each givinga flat additive insulation bonus/penalty, “detected via LibArmorInsulation”and configurable under a “Set Insulation Bonuses” panel in `/ff config`.No part of this exists: there’s no set-detection code (no`GetItemLinkSetInfo`/equivalent call) and no set-bonus data table anywherein either this addon or LibArmorInsulation, and no such panel in`ConfigMenu.lua`. The insulation sources that actually exist are exactlythe three listed under “Armor & Costume Insulation” above costume,outfit style, and base armor style with no separate set-based layer ontop. If a set-bonus feature gets built for real in the future, it belongsback here.)*### SwimmingSwimming in open water equilibrates your body temperature toward the water temperature, partially bypassing insulation. Cold-zone water (below 15C) is especially dangerous (2.5x drag rate). Thick armor provides some resistance but far less than on land.### Environmental Temperature Mechanics- **Water ingredient loot** Looting an alchemy water solvent cools you by 5C (only if you are already above `COMFORTABLE_HI`).- **Crafting station interaction** Opening a provisioning or smithing station warms you by 5C (only if below `COMFORTABLE_LO`). Rate-limited to once per minute.### Temperature Thresholds (all in C)| Threshold | C | F | Meaning ||———–|—-|—-|———|| FREEZE_DANGER | −10 | 14 | Hypothermia danger || VERY_COLD | 0 | 32 | Very cold shiver emote || COLD | 10 | 50 | Cold shiver emote || COMFORTABLE_LO | 20 | 68 | Lower edge of comfort zone || COMFORTABLE_HI | 24 | 75 | Upper edge of comfort zone || WARM | 26 | 79 | Warm (no effect) || HOT | 35 | 95 | Hot wipe-brow emote, heat overlay begins || HEAT_DANGER | 41 | 105 | Scorching breathless emote, full heat overlay |### HUD Display- Compact thermometer widget (draggable)- Color-coded temperature bar and value- Status label (COMFORTABLE, COLD, OVERHEATING, etc.)- Insulation value and source displayed (e.g. `80 (armor)`) *(corrected: previously also claimed an “active set bonus” was shown here; no such feature exists see the note on the removed “Set Insulation Bonuses” section above)*### Configuration MenuAccessible via `/ff config` or the ESO addon settings panel (LibAddonMenu-2.0):- Enable/disable the system entirely- Toggle HUD, overlay, emotes, and sounds- Scale and opacity controls for the HUD- Emote dropdowns for each temperature band, populated live from your installed emotes—## Installation1. Download and extract the `Frostfall` folder2. Place it in: `DocumentsElder Scrolls OnlineliveAddOnsFrostfall`3. Install all required dependencies (see below) Minion handles this automatically4. Launch ESO, enable the addon in the AddOns menu—## Slash Commands| Command | Description ||———|————-|| `/ff` or `/frostfall` | Show help || `/ff status` | Print current temperature state to chat || `/ff config` | Open configuration menu || `/ff debug` | Toggle debug logging || `/ff toggle` | Enable/disable Frostfall || `/ff findEmote ` | Search for an emote by name and print its stable emoteId |—## Zone Temperature Reference (Selected)*(Corrected every value in this table was previously wrong, by a widemargin in most cases (e.g. Coldharbour listed as a mild 2C when it’sactually -8C; The Deadlands listed as 85C when it’s actually 54C). Thetable below is pulled directly from `LibZoneTemp.lua`’s current`ZONE_BASE_TEMPS_BY_NAME` table.)*| Zone | Temperature | Climate ||——|————|———|| Western Skyrim | -10C | Very cold, snowy Nordic holds || Bleakrock Isle | -8C | Icy island cliffs, sparse forests || Coldharbour | -8C | Bleak grey sky, cold and lifeless || Wrothgar | -8C | Orsinium highlands, bitterly cold winters || Eastmarch | -2C | Frozen wastes, volcanic tundra || Rivenspire | 4C | Bleak, windswept moors || The Rift | 4C | Relatively temperate, rich autumnal forests || Cyrodiil | 17C | Temperate central forests and plains || Summerset | 18C | Mild, pleasant Mediterranean climate || Auridon | 20C | Temperate Mediterranean gardens and architecture || Gold Coast | 22C | Pleasant climate, warmed by the Abecean Sea || Murkmire | 34C | Deep tropical marshland jungle || Hew’s Bane | 36C | Barren, scorching desert peninsula || Vvardenfell | 38C | Volcanic island, arid ash wastes || Northern Elsweyr | 40C | Hot Anequine savanna and Scar desert || Alik’r Desert | 46C | Arid Hammerfell wasteland, scorching sandstorms || The Deadlands | 54C | Mehrunes Dagon’s hellfire Oblivion realm |—## Armor Insulation Reference (Selected)*(Corrected this table previously listed 18 entries with pre-tier-systemraw scores from before the v2.6.0 staggered-tier rewrite, four of whichVoidsteel, Nightmare, Soul Shriven, and Bear Raiment Costume don’t existanywhere in the current style/costume data at all. Several “flavor-adjusted”notes also had the thermal direction backwards: Daedric, Dremora, WakingFlame, and Ancient Daedric are all written in the code as **cold**-radiating(negative `flavorBonus`), not heat-generating. The table below is rebuiltfrom `LibArmorInsulation_StyleData.lua`’s actual current entries, with tierscomputed through the real formula and `Calc.SnapToTier()`.)*| Style | Insulation | Notes ||——-|———–|——-|| Flame Atronach (costume) | 90 ★ | Body of living fire extreme warmth || Nord | 80 | Fur construction, capped at the mundane ceiling (raw score ~107) || Werewolf (polymorph) | 80 | Dense fur pelt and elevated body temperature || Pyre Watch | 70 | Fire-tempered treatment provides insulating char layer || Silver Dawn | 70 | Heavy-leather motif, no flavor bonus || Waking Flame | 50 | Deadlands-tinged construction carries a **mild chill** (not heat, despite the fire theming) || Mercenary | 50 | Practical layered construction for road travel || Wood Elf | 30 | Light cloth racial armor, no flavor bonus || Khajiit | 30 | Light hide racial armor, no flavor bonus || Barbaric | 20 | Thin hide motif, low coverage || Fang Lair | 20 | Dragon bones carry the cold of death || Dremora | 10 | Emanates the consuming cold of Coldharbour || Storm Atronach (costume) | 10 | Elemental form provides no thermal protection || Daedric | 0 | Radiates unnatural cold into the wearer’s bones || Stalhrim Frostcaster | 0 | Stalhrim plates actively radiate cold || Frost Atronach (costume) | -10 ★ | Body of living frost actively leeches warmth || Ice Wraith (polymorph) | -10 ★ | Body of living ice aggressively cold |★ = `magical = true` clamped to the full -10..90 tier range instead of themundane 0..80 range reserved for ordinary materials.—## DependenciesAll are **required**. Minion (the standard ESO addon manager) will install them automatically.| Library | Source | Purpose ||———|——–|———|| LibAddonMenu-2.0 | (https://www.esoui.com/downloads/info7-LibAddonMenu.html) | Settings panel UI || LibZoneTemp | ESOUI | Zone ambient temperature data || LibArmorInsulation | ESOUI | Armor insulation breakdown |—## Compatibility- ESO API Version: 101049+- Works with all ESO chapters and DLC- Compatible with outfit system, costume system, and Crown Store collectibles—## Notes on Temperature CalculationsAll zone temperatures and armor insulation values are **estimates** based on lore descriptions, visual design, cultural origin, and material analysis. Insulation is calculated from the **visual style** of the armor, not the set name. Unique pieces with flavor text describing thermal properties have been individually adjusted. Use the override system to tune anything that doesn’t feel right for your playstyle.The temperature system is **purely cosmetic** it does not affect actual gameplay stats, damage, or character mechanics. It is an immersion and roleplay tool.