Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Frostforge/Core/Core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local addonName, J = ...
-- Keep the addon folder and saved-variable keys stable for existing installs.
J.Brand = { name="Jiberish's Frostforge", shortName="Frostforge", website="https://theigloo.io" }
local Core = {
version = "1.0.0",
version = "1.0.1",
modules = {}, clients = {}, owned = {}, notices = {},
order = { "minimap", "playerFrame", "targetFrame", "focusFrame", "actionHub" },
settingsOrder = { "minimap", "playerFrame", "targetFrame", "focusFrame", "targetTargetFrame", "partyFrames", "actionHub" },
Expand Down
33 changes: 31 additions & 2 deletions Frostforge/Core/Portraits.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ J.Portraits = P
J.Core.properties.portraitMode = {CLASS=true,RACE=true,FACTION=true,FIXED=true}
J.Core.properties.portrait = {}
for id in pairs(J.PortraitCatalog.entries) do J.Core.properties.portrait[id] = true end
J.Core.properties.npcArtwork = {boolean=true}
J.Core.propertyOrder[#J.Core.propertyOrder+1] = "npcArtwork"

function P:IsUnitKey(key)
return key == "playerFrame" or key == "targetFrame" or key == "focusFrame"
Expand Down Expand Up @@ -106,16 +108,43 @@ function P:NPCCity(unit)
return id
end

function P:CreatureArtwork(unit)
if publicCall(UnitPlayerControlled,unit)~=false or type(UnitCreatureType)~="function" then return end
local ok,name,typeID=pcall(UnitCreatureType,unit)
if not ok then return end
-- The numeric ID is independent of client language. Never use restricted
-- values as table keys, or infer identity from names/health/reaction.
if not J.Core:IsSafe(typeID) or not J.Core:IsSafe(name) then return end
if J.Core:IsNumber(typeID) then return J.PortraitCatalog.creatures[typeID] end
if type(name)~="string" then return end
-- Older clients may return only the localized label. Resolve exact client
-- names when available, with English labels as a conservative fallback.
if not self.creatureNames then
self.creatureNames={}
for id,artwork in pairs(J.PortraitCatalog.creatures) do
local entry=J.PortraitCatalog.entries[artwork]
self.creatureNames[entry.label]=artwork
local info=publicCall(field(C_CreatureInfo,"GetCreatureTypeInfo"),id)
local localized=field(info,"name")
if type(localized)=="string" then self.creatureNames[localized]=artwork end
end
end
return self.creatureNames[name]
end

function P:Resolve(config)
local id
if config.portraitMode == "FIXED" then
id = config.portrait
else
local player=publicCall(UnitIsPlayer,config.unit)
if player==false then id=self:NPCCity(config.unit) end
if player==false then
id=self:NPCCity(config.unit)
if not id and config.npcArtwork~=false then id=self:CreatureArtwork(config.unit) end
end
if not id and config.portraitMode == "CLASS" then
-- NPC UnitClass commonly returns WARRIOR regardless of appearance.
-- Unrecognized NPC affiliations keep the neutral fallback.
-- Unknown creature types keep the neutral fallback.
if player == true then
local value = token(UnitClass,config.unit,2)
if value then id = J.PortraitCatalog.classes[value] end
Expand Down
1 change: 1 addition & 0 deletions Frostforge/Core/ProfileManager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ end
local function supported(key,property)
if J.SmallFrames:IsKey(key) then return J.SmallFrames:Supports(property) end
if J.SmallFrames.properties[property] then return false end
if property=="npcArtwork" then return J.Portraits:IsUnitKey(key) end
if J.BlizzardUnits.placementProperties[property] then return key=="targetFrame" or key=="focusFrame" end
if J.BlizzardUnits.textProperties[property] then return J.Portraits:IsUnitKey(key) end
if J.BlizzardUnits.styleProperties[property] then return J.Portraits:IsUnitKey(key) end
Expand Down
18 changes: 15 additions & 3 deletions Frostforge/Core/Settings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,12 @@ function S:CreateCollection(kind)
backdrop(p,"outer");text(p,spec.title,24,-22,650,"GameFontNormalLarge")
button(p,"X",714,-18,28,function() p:Hide() end)
self[spec.groups]={}
for i,entry in ipairs({{"CLASS","Classes"},{"RACE","Races"},{"FACTION","Factions"}}) do
local groups={{"CLASS","Classes"},{"RACE","Races"},{"FACTION","Factions"}}
if kind=="portrait" or kind=="unit" then groups[#groups+1]={"CREATURE","Creatures"} end
local groupWidth=732/#groups
for i,entry in ipairs(groups) do
local group=entry[1]
self[spec.groups][group]=button(p,entry[2],24+(i-1)*244,-64,232,function() self:ShowCollection(kind,group) end)
self[spec.groups][group]=button(p,entry[2],24+(i-1)*groupWidth,-64,groupWidth-12,function() self:ShowCollection(kind,group) end)
end
text(p,"Find artwork",24,-115,90,"GameFontNormalSmall")
p.search=CreateFrame("EditBox",nil,p,"BackdropTemplate")
Expand All @@ -223,6 +226,7 @@ function S:CreateCollection(kind)
p.empty=text(p,"No matching artwork in this collection. Try another name or category.",24,-170,716)
self[spec.buttons]={}
for id,entry in pairs(J[spec.catalog].entries) do
if entry.group~="CREATURE" or kind=="portrait" or kind=="unit" then
local choice=id
local b=button(p,"",0,0,168,function()
p:Hide();self:Set(spec.property,choice);if spec.mode then self:Set(spec.mode,"FIXED") end
Expand All @@ -235,6 +239,7 @@ function S:CreateCollection(kind)
if kind=="portrait" then b.image:SetTexCoord(0,.5,0,1) end
local caption=text(b,entry.label,6,-86,156);caption:SetJustifyH("CENTER")
self[spec.buttons][id]=b
end
end
p.hint=text(p,"",24,-536,716)
p.previous=button(p,"Previous",24,-566,144,function() self:ShowCollection(kind,self[spec.group],self[spec.page]-1) end)
Expand Down Expand Up @@ -820,6 +825,10 @@ function S:Create()
self.minimapCaption=text(a,"Artwork collection",414,-102,236,"GameFontNormal")
self.minimapButton=button(a,"Browse artwork",414,-124,236,function() self:HideMenus();self:ShowMinimapGroup(self.minimapGroup or "CLASS",self.minimapPage);self.minimapPicker:Show() end)
self.modeHelp=text(a,"",154,-166,496)
self.npcArtworkToggle=toggle(a,"Match NPC creature types",346,-220,318,function()
self:Set("npcArtwork",not J.ThemeManager:Resolve(self.selected).npcArtwork)
end)
self.npcArtworkHelp=text(a,"City art and fixed choices take priority.",376,-258,288,"GameFontNormalSmall")
self:Dropdown("portraitSource","Portrait provider",portraitSources,0,-282,a)
self:Dropdown("smallPortraitSource","Portrait provider",hubSources,0,-282,a)
self:Dropdown("hubSource","Action bar provider",hubSources,0,-236,a)
Expand Down Expand Up @@ -983,6 +992,9 @@ function S:Refresh()
self.hubCaption:SetShown(hub);self.hubButton:SetShown(hub)
self.controls.portraitMode.button:SetShown(unit);self.controls.portraitMode.label:SetShown(unit)
self.portraitCaption:SetShown(unit);self.portraitButton:SetShown(unit)
local creatureOptions=self.selected=="targetFrame" or self.selected=="focusFrame"
self.npcArtworkToggle:SetShown(creatureOptions);self.npcArtworkToggle:SetChecked(config.npcArtwork)
self.npcArtworkHelp:SetShown(creatureOptions);self.modeHelp:SetShown(not creatureOptions)
self.genericPreviewPanel:SetShown(not unit);self.genericChoicePanel:SetShown(not unit)
self.portraitCard:SetShown(unit);self.unitCard:SetShown(unit)
self.unitPreview:SetShown(unit);self.unitCaption:SetShown(unit);self.unitBrowse:SetShown(unit)
Expand All @@ -1004,7 +1016,7 @@ function S:Refresh()
self.sourceStatus:SetText("|cff9edfffPortrait:|r "..portrait.."\n|cff9edfffUnit frame:|r "..frame)
self.providerHelp:SetText("Full shells fit Blizzard, ElvUI and Ellesmere: horizontal health with full-width power below. No power keeps a dark empty opening.")
self.placementHelp:SetText("Offsets move only the decoration. Use your UI addon's settings to move the portrait or health bars themselves.")
self.guideHelp:SetText("|cff9edfffArtwork missing?|r Target a unit, check its artwork toggle and provider, and enable portraits in that provider.\n|cff9edfffWrong NPC theme?|r Browse for a fixed design to override automatic matching.")
self.guideHelp:SetText("|cff9edfffArtwork missing?|r Target a unit, check its artwork toggle and provider, and enable portraits in that provider.\n|cff9edfffWrong NPC theme?|r Creature matching follows the NPC type. City affiliations take priority. Browse Creatures for a fixed design.")
if small then
local group=J.SmallFrames.groups[self.selected]
local borderID=config.smallFrameArt=="MATCH" and id or config.smallFrameArt
Expand Down
2 changes: 1 addition & 1 deletion Frostforge/Core/SmallFrames.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ for _,property in ipairs({"smallFrameArt","smallFrameWeight","smallFramePadding"
J.Core.propertyOrder[#J.Core.propertyOrder+1]=property
end
local supported={width=true,height=true,x=true,y=true,scale=true,opacity=true,shown=true,
strata=true,level=true,layer=true,portraitMode=true,portrait=true,portraitSource=true,
strata=true,level=true,layer=true,portraitMode=true,portrait=true,portraitSource=true,npcArtwork=true,
unitFrameShown=true,unitFrameSource=true,unitFrameWidth=true,unitFrameHeight=true,
unitFrameX=true,unitFrameY=true,unitFrameStrata=true}
function S:IsKey(key) return key=="targetTargetFrame" or key=="partyFrames" end
Expand Down
2 changes: 1 addition & 1 deletion Frostforge/Core/ThemeManager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function Themes:Register(id, theme)
end
end
for property in pairs(J.Core.properties) do
local portrait = J.BlizzardUnits.styleProperties[property] or J.BlizzardUnits.textProperties[property] or property == "portraitMode" or property == "unitFrameStrata" or property == "castBarLevel" or property == "castBarStrata" or property == "blizzardPortraitFrameHidden" or property == "blizzardPortraitHidden" or property == "blizzardNameEnabled" or property == "blizzardNameX" or property == "blizzardNameY" or property == "blizzardNameSize" or property == "blizzardNameAlign" or property == "blizzardNameOutline" or property == "castBarShown" or property == "castBarSource" or property == "castBarStyle" or property == "castBarArt" or property == "castBarWeight" or property == "castBarPadding" or property == "castBarWidth" or property == "castBarHeight" or property == "portrait" or property == "unitStyle" or property == "unitFrameShown" or property == "unitFrameFill" or property == "unitFrameWidth" or property == "unitFrameHeight" or property == "unitFrameX" or property == "unitFrameY" or property == "unitFrameInset" or property == "unitFrameSource" or property == "portraitSource"
local portrait = property=="npcArtwork" or J.BlizzardUnits.styleProperties[property] or J.BlizzardUnits.textProperties[property] or property == "portraitMode" or property == "unitFrameStrata" or property == "castBarLevel" or property == "castBarStrata" or property == "blizzardPortraitFrameHidden" or property == "blizzardPortraitHidden" or property == "blizzardNameEnabled" or property == "blizzardNameX" or property == "blizzardNameY" or property == "blizzardNameSize" or property == "blizzardNameAlign" or property == "blizzardNameOutline" or property == "castBarShown" or property == "castBarSource" or property == "castBarStyle" or property == "castBarArt" or property == "castBarWeight" or property == "castBarPadding" or property == "castBarWidth" or property == "castBarHeight" or property == "portrait" or property == "unitStyle" or property == "unitFrameShown" or property == "unitFrameFill" or property == "unitFrameWidth" or property == "unitFrameHeight" or property == "unitFrameX" or property == "unitFrameY" or property == "unitFrameInset" or property == "unitFrameSource" or property == "portraitSource"
local hub = property == "hubMode" or property == "hub" or property == "hubSource"
local minimap = property == "minimapMode" or property == "minimap" or property=="minimapRound"
local small=J.SmallFrames:IsKey(key)
Expand Down
2 changes: 1 addition & 1 deletion Frostforge/Frostforge.toc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
## X-Website: https://theigloo.io
## Notes: Optional sculpted unit-frame skins and fantasy portrait surrounds with Blinkii, mMediaTag, ElvUI and EllesmereUI support, matching cast-bar borders, action hubs and minimap artwork.
## Author: Jiberish
## Version: 1.0.0
## Version: 1.0.1
## SavedVariables: JiberishUIDB
## SavedVariablesPerCharacter: JiberishUICharacterDB
## OptionalDeps: LibSharedMedia-3.0, Blizzard_UnitFrame, Blizzard_ActionBar, Blizzard_Minimap, Blizzard_GameMenu, Blinkiis_Portraits, ElvUI, ElvUI_mMediaTag, EllesmereUI, EllesmereUIUnitFrames, EllesmereUIRaidFrames, EllesmereUIResourceBars, EllesmereUIActionBars, EllesmereUIMinimap
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Frostforge/Media/Portraits/creature_beast.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Frostforge/Media/Portraits/creature_critter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Frostforge/Media/Portraits/creature_demon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Frostforge/Media/Portraits/creature_giant.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Frostforge/Media/Portraits/creature_humanoid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Frostforge/Media/Portraits/creature_undead.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Frostforge/Media/UnitFrames/creature_beast.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Frostforge/Media/UnitFrames/creature_critter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Frostforge/Media/UnitFrames/creature_demon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Frostforge/Media/UnitFrames/creature_giant.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Frostforge/Media/UnitFrames/creature_undead.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion Frostforge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ Use the package for your client. Updates replace the addon folder; keep your `WT

[Website](https://theigloo.io) · [Credits](CREDITS.md)

Version 1.0.0 has separate packages for Retail 12.1.0 and Forever 1.60.1. Choose the package matching your client.
Version 1.0.1 has separate packages for Retail 12.1.0 and Forever 1.60.1. Choose the package matching your client.
5 changes: 5 additions & 0 deletions Frostforge/Themes/CastBorders.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,8 @@ for id, inset in pairs(insets) do
J.CastBorderFitLimits[1] = math.max(J.CastBorderFitLimits[1],inset[1]+inset[3])
J.CastBorderFitLimits[2] = math.max(J.CastBorderFitLimits[2],inset[2]+inset[4])
end

-- Creature portraits/shells reuse an existing matching cast trim and its fit.
for _,entry in pairs(J.UnitSkinCatalog.entries) do
if entry.castTheme then entry.castInsets=J.UnitSkinCatalog.entries[entry.castTheme].castInsets end
end
1 change: 1 addition & 0 deletions Frostforge/Themes/Paladin/Retribution.lua
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,5 @@ for _,key in ipairs(J.SmallFrames.keys) do
smallFrameArt="MATCH",smallFrameWeight=.7,smallFramePadding=1,smallFrameLevel=1,
}
end
for _,key in ipairs({"playerFrame","targetFrame","focusFrame","targetTargetFrame","partyFrames"}) do theme[key].npcArtwork=true end
J.ThemeManager:Register("paladin_ret",theme)
24 changes: 23 additions & 1 deletion Frostforge/Themes/Portraits.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local _, J = ...
-- Data only. Individual hand-painted portrait textures share the same fit template.
J.PortraitCatalog = { entries = {}, classes = {}, races = {}, factions = {} }
J.PortraitCatalog = { entries = {}, classes = {}, races = {}, factions = {}, creatures = {} }
local C = J.PortraitCatalog
C.entries.CLASS_WARRIOR = {label="Warrior",group="CLASS",texture="Interface\\AddOns\\Frostforge\\Media\\Portraits\\class_warrior.png"}
C.classes["WARRIOR"] = "CLASS_WARRIOR"
Expand Down Expand Up @@ -89,3 +89,25 @@ C.factions["Neutral"] = "FACTION_NEUTRAL"
C.races.Undead = C.races.Scourge
C.races.Earthen = C.races.EarthenDwarf
C.races.Maghar = C.races.MagharOrc

-- Dedicated creature artwork for public NPC type IDs.
C.entries.CREATURE_BEAST = {label="Beast",group="CREATURE",texture="Interface\\AddOns\\Frostforge\\Media\\Portraits\\creature_beast.png"}
C.creatures[1] = "CREATURE_BEAST"
C.entries.CREATURE_DRAGONKIN = {label="Dragonkin",group="CREATURE",texture="Interface\\AddOns\\Frostforge\\Media\\Portraits\\creature_dragonkin.png"}
C.creatures[2] = "CREATURE_DRAGONKIN"
C.entries.CREATURE_DEMON = {label="Demon",group="CREATURE",texture="Interface\\AddOns\\Frostforge\\Media\\Portraits\\creature_demon.png"}
C.creatures[3] = "CREATURE_DEMON"
C.entries.CREATURE_ELEMENTAL = {label="Elemental",group="CREATURE",texture="Interface\\AddOns\\Frostforge\\Media\\Portraits\\creature_elemental.png"}
C.creatures[4] = "CREATURE_ELEMENTAL"
C.entries.CREATURE_GIANT = {label="Giant",group="CREATURE",texture="Interface\\AddOns\\Frostforge\\Media\\Portraits\\creature_giant.png"}
C.creatures[5] = "CREATURE_GIANT"
C.entries.CREATURE_UNDEAD = {label="Undead",group="CREATURE",texture="Interface\\AddOns\\Frostforge\\Media\\Portraits\\creature_undead.png"}
C.creatures[6] = "CREATURE_UNDEAD"
C.entries.CREATURE_HUMANOID = {label="Humanoid",group="CREATURE",texture="Interface\\AddOns\\Frostforge\\Media\\Portraits\\creature_humanoid.png"}
C.creatures[7] = "CREATURE_HUMANOID"
C.entries.CREATURE_CRITTER = {label="Critter",group="CREATURE",texture="Interface\\AddOns\\Frostforge\\Media\\Portraits\\creature_critter.png"}
C.creatures[8] = "CREATURE_CRITTER"
C.entries.CREATURE_MECHANICAL = {label="Mechanical",group="CREATURE",texture="Interface\\AddOns\\Frostforge\\Media\\Portraits\\creature_mechanical.png"}
C.creatures[9] = "CREATURE_MECHANICAL"
C.entries.CREATURE_ABERRATION = {label="Aberration",group="CREATURE",texture="Interface\\AddOns\\Frostforge\\Media\\Portraits\\creature_aberration.png"}
C.creatures[14] = "CREATURE_ABERRATION"
Loading
Loading