wuira 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +181 -0
- package/lib/Spells.d.ts +10 -0
- package/lib/Spells.lua +19 -0
- package/lib/datasources/AuraTimer.d.ts +21 -0
- package/lib/datasources/AuraTimer.lua +322 -0
- package/lib/datasources/CastTimer.d.ts +9 -0
- package/lib/datasources/CastTimer.lua +240 -0
- package/lib/datasources/DataSource.d.ts +4 -0
- package/lib/datasources/DataSource.lua +24 -0
- package/lib/datasources/ProgressSource.d.ts +6 -2
- package/lib/datasources/ProgressSource.lua +20 -2
- package/lib/datasources/Resources.d.ts +21 -2
- package/lib/datasources/Resources.lua +473 -0
- package/lib/datasources/SpellCooldown.d.ts +10 -0
- package/lib/datasources/SpellCooldown.lua +207 -0
- package/lib/datasources/SwingTimer.d.ts +31 -0
- package/lib/datasources/SwingTimer.lua +641 -0
- package/lib/datasources/TextureSource.d.ts +10 -0
- package/lib/datasources/TextureSource.lua +83 -0
- package/lib/datasources/TimerSource.d.ts +18 -0
- package/lib/datasources/TimerSource.lua +284 -0
- package/lib/datasources/index.d.ts +9 -1
- package/lib/datasources/index.lua +27 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.lua +13 -0
- package/lib/platform/BlizzardUI.d.ts +12 -0
- package/lib/platform/BlizzardUI.lua +352 -0
- package/lib/platform/forever.d.ts +40 -2
- package/lib/store/index.d.ts +37 -0
- package/lib/store/index.lua +921 -0
- package/lib/ui/Cell.d.ts +3 -1
- package/lib/ui/Icon.d.ts +8 -0
- package/lib/ui/Icon.lua +8 -0
- package/lib/ui/Label.d.ts +10 -0
- package/lib/ui/Label.lua +8 -0
- package/lib/ui/ProgressBar.d.ts +5 -1
- package/lib/ui/index.d.ts +4 -0
- package/lib/ui/index.lua +8 -0
- package/lib/ui/layout/measureLayout.lua +8 -1
- package/lib/ui/mount.lua +267 -45
- package/lib/ui/primitives/jsx.d.ts +7 -2
- package/package.json +8 -1
- package/tools/build-library.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,56 @@ with the release date and highlight breaking changes explicitly.
|
|
|
9
9
|
|
|
10
10
|
No changes yet.
|
|
11
11
|
|
|
12
|
+
## 0.1.5 — 2026-10-14
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Event-driven `.When(value => boolean)` source conditions. Inactive bindings
|
|
17
|
+
hide their visual and skip writes; secret inputs never reach callbacks.
|
|
18
|
+
Repeated conditions combine with AND, and fresh `.Value` reads remain unchanged.
|
|
19
|
+
- Opt-in `HP.UseHealPrediction()` and `HP.UseAbsorbPrediction()` channels,
|
|
20
|
+
with lazy allocation, capability checks, and optional event subscriptions.
|
|
21
|
+
- Independently styled healing and shield overlays on HP progress bars,
|
|
22
|
+
including direct native handling of secret amounts and clipping at bar bounds.
|
|
23
|
+
- Opt-in `BlizzardUI.Hide` for stock action bars and player/target/focus frames,
|
|
24
|
+
with combat deferral and a restore callback, preserving native event handlers.
|
|
25
|
+
- Cell visibility predicates and live label text, with cleanup on unmount.
|
|
26
|
+
- Timer activity flags and cast/channel spell names for conditional UI rows.
|
|
27
|
+
- Public `Spells` enum with named Paladin Seal spell IDs.
|
|
28
|
+
- Player swing countdown sources for main-hand, off-hand, and ranged attacks,
|
|
29
|
+
driven by Forever's native swing events and native StatusBar timer animation.
|
|
30
|
+
- Explicit unknown timing before the first readable event, secret-value guards,
|
|
31
|
+
weapon-change resets, and source disposal.
|
|
32
|
+
- Label and Icon primitives, with event-driven texture sources.
|
|
33
|
+
- Native duration sources for aura timers, spell/global cooldowns, and cast/channel
|
|
34
|
+
countdowns. Selected aura icons share the aura source's selection policy.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- Initialize native timer and swing bars with a normalized 0–1 range instead
|
|
39
|
+
of the default resource range.
|
|
40
|
+
- Mount lifecycle now runs datasource binding cleanup callbacks on unmount.
|
|
41
|
+
|
|
42
|
+
### Validation and limitations
|
|
43
|
+
|
|
44
|
+
- Lua tests cover conditional activation/reactivation, secret callback guards,
|
|
45
|
+
optional prediction reads/events, overlay placement, and unmount cleanup.
|
|
46
|
+
- Prediction amounts require the client's native unit APIs. Incoming healing
|
|
47
|
+
is raw (not reduced by heal-absorb debuffs); overheal is visually clipped.
|
|
48
|
+
HP overrides are incompatible with prediction overlays. In-game prediction
|
|
49
|
+
visuals still need validation in Forever.
|
|
50
|
+
|
|
51
|
+
## 0.1.4 — 2026-10-14
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- Class-based stores with optional stable tokens, one-time readonly snapshots,
|
|
56
|
+
transactional callback updates, and observer subscriptions.
|
|
57
|
+
- Memory-only stores when no token is declared; SavedVariables-backed records
|
|
58
|
+
when a token and registry persistence configuration are provided.
|
|
59
|
+
- SavedVariables initialization after the owning addon's `ADDON_LOADED` event,
|
|
60
|
+
default restoration, collision checks, and serializable data validation.
|
|
61
|
+
|
|
12
62
|
## 0.1.3 — 2026-10-14
|
|
13
63
|
|
|
14
64
|
### Added
|
package/README.md
CHANGED
|
@@ -94,6 +94,118 @@ function App() {
|
|
|
94
94
|
wuira.Mount(App);
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
### Conditional sources and health predictions
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import { UI } from "wuira";
|
|
101
|
+
import { ProgressBar } from "wuira/ui";
|
|
102
|
+
import { HP, Unit } from "wuira/datasources";
|
|
103
|
+
|
|
104
|
+
const hp = new HP(Unit.Player)
|
|
105
|
+
.UseHealPrediction()
|
|
106
|
+
.UseAbsorbPrediction()
|
|
107
|
+
.When(value => value >= 20); // Current health points, not a percentage.
|
|
108
|
+
|
|
109
|
+
const view = (
|
|
110
|
+
<ProgressBar width={220} height={24} source={hp}
|
|
111
|
+
healPrediction={{ texture: "blizzard", color: { r: 0.4, g: 1, b: 0.5, a: 0.5 } }}
|
|
112
|
+
absorbPrediction={{ texture: "solid", color: { r: 0.8, g: 0.9, b: 1, a: 0.55 } }} />
|
|
113
|
+
);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Configure sources before mounting. `.When()` filters native binding updates using
|
|
117
|
+
the source's own value; repeated calls combine with AND. A false condition hides
|
|
118
|
+
the bound bar and suppresses writes until a relevant event makes it true again.
|
|
119
|
+
The basic health events remain subscribed so the source can reactivate; there is
|
|
120
|
+
no health polling. Predicates should depend on this source's event-driven state,
|
|
121
|
+
not unrelated mutable values. `.Value` remains a fresh, checked snapshot rather
|
|
122
|
+
than a filtered subscription. Secret values never reach condition callbacks:
|
|
123
|
+
a conditional binding becomes inactive until readable data returns. Without a
|
|
124
|
+
condition, opaque values continue directly to native widgets.
|
|
125
|
+
|
|
126
|
+
Each prediction channel is allocated and its event registered only when explicitly
|
|
127
|
+
enabled and supported. No prediction snapshots are cached. Access
|
|
128
|
+
`hp.HealPrediction?.Value` and `hp.AbsorbPrediction?.Value` when readable, or check
|
|
129
|
+
the channel's `IsAvailable` flag. Direct reads retain the usual secret-value guard.
|
|
130
|
+
The APIs provide incoming healing and existing damage-absorb shields, not a
|
|
131
|
+
forecast of future damage. The adapter uses
|
|
132
|
+
[Blizzard's unit prediction APIs](https://github.com/Gethe/wow-ui-source/blob/live/Interface/AddOns/Blizzard_APIDocumentationGenerated/UnitDocumentation.lua).
|
|
133
|
+
|
|
134
|
+
Enabled channels draw by default; `healPrediction={false}` or
|
|
135
|
+
`absorbPrediction={false}` suppresses an individual overlay. Incoming healing starts
|
|
136
|
+
at the native health-fill edge and clips at the bar boundary. Shields overlay
|
|
137
|
+
inward from the opposite edge, remaining visible even at full health. Both accept
|
|
138
|
+
independent textures/colors and support horizontal, vertical, and reversed bars.
|
|
139
|
+
There is no arithmetic on secret health or prediction amounts. Raw incoming heals
|
|
140
|
+
are not reduced by heal-absorb debuffs; overheal is visually clipped. Prediction
|
|
141
|
+
overlays require the native health scale, so min/max/current overrides are rejected.
|
|
142
|
+
Prediction reads pause while the parent HP condition is inactive. The renderer
|
|
143
|
+
cleans up the overlays and resource subscriptions on unmount.
|
|
144
|
+
|
|
145
|
+
### Native aura, cooldown, and cast timers
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
import { UI, Spells } from "wuira";
|
|
149
|
+
import { FlowLayout, ProgressBar, Icon, Label } from "wuira/ui";
|
|
150
|
+
import { AuraTimer, GlobalCooldown, CastTimer, Unit } from "wuira/datasources";
|
|
151
|
+
|
|
152
|
+
const aura = new AuraTimer(Unit.Player, { spellIds: [Spells.SealOfRighteousness], filter: "HELPFUL" });
|
|
153
|
+
const gcd = new GlobalCooldown();
|
|
154
|
+
const cast = new CastTimer(Unit.Player);
|
|
155
|
+
|
|
156
|
+
function Timers() {
|
|
157
|
+
return (
|
|
158
|
+
<FlowLayout width={200} height={94} direction="vertical" gap={2}>
|
|
159
|
+
<Icon width={24} height={24} textureSource={aura.Texture} />
|
|
160
|
+
<ProgressBar height={24} source={aura}><Label text="Aura" /></ProgressBar>
|
|
161
|
+
<ProgressBar height={18} source={gcd} />
|
|
162
|
+
<ProgressBar height={22} source={cast} />
|
|
163
|
+
</FlowLayout>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
These timers pass opaque native duration objects to `SetTimerDuration`; they do
|
|
169
|
+
not calculate restricted durations in Lua. `SpellCooldown(spellId)` tracks a
|
|
170
|
+
specific spell, and `GlobalCooldown` supplies the GCD identifier internally.
|
|
171
|
+
`CastTimer` follows casts and channels. `AuraTimer` resolves localized spell names
|
|
172
|
+
and exposes an associated `Texture` source, with status indicating active,
|
|
173
|
+
inactive, restricted, or unavailable data. Aura access still follows the client's
|
|
174
|
+
restrictions; missing readable data is not reconstructed from combat events.
|
|
175
|
+
`Label` and `Icon` are visual Cells. Application code supplies which spells to
|
|
176
|
+
track; native API declarations and reads remain in wuira.
|
|
177
|
+
|
|
178
|
+
### Swing timers
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
import { UI, wuira } from "wuira";
|
|
182
|
+
import { ProgressBar } from "wuira/ui";
|
|
183
|
+
import { SwingTimer, SwingHand } from "wuira/datasources";
|
|
184
|
+
|
|
185
|
+
const mainHand = new SwingTimer(SwingHand.MainHand);
|
|
186
|
+
const view = wuira.Mount(<ProgressBar width={200} height={12} source={mainHand} />);
|
|
187
|
+
|
|
188
|
+
// Other choices: SwingHand.OffHand and SwingHand.Ranged.
|
|
189
|
+
// mainHand.Value: remaining seconds; Max.Value: duration; Percent.Value: remaining percent.
|
|
190
|
+
// When removing the feature:
|
|
191
|
+
if (view !== undefined) wuira.Unmount(view);
|
|
192
|
+
mainHand.Dispose();
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
This source follows the player's `PLAYER_SWING(duration, swingType)` events.
|
|
196
|
+
It does not reconstruct swings from the combat log or track enemy attack cycles.
|
|
197
|
+
`HasTiming` is false until the first readable event and after a weapon/world reset;
|
|
198
|
+
zero before that event is not evidence of a synchronized swing. After a recorded
|
|
199
|
+
cycle expires, remaining time reaches zero. Secret payloads block datasource
|
|
200
|
+
computation until a readable event or reset arrives.
|
|
201
|
+
|
|
202
|
+
Native progress binding uses `C_DurationUtil` and `StatusBar:SetTimerDuration`,
|
|
203
|
+
with no Lua per-frame animation. Range/current overrides are not supported for
|
|
204
|
+
this binding. Unmount detaches each bar; call `Dispose()` to stop the source's
|
|
205
|
+
event listener when its owning feature ends. Support is capability-checked;
|
|
206
|
+
actual timing still needs validation in Forever. The adapter follows the
|
|
207
|
+
[Forever swing API definition](https://github.com/Gethe/wow-ui-source/blob/bd2470aed543f72697a044e989285b6c83e63f73/Interface/AddOns/Blizzard_APIDocumentationGenerated/SwingTimerDocumentation.lua).
|
|
208
|
+
|
|
97
209
|
### Group members
|
|
98
210
|
|
|
99
211
|
```ts
|
|
@@ -309,6 +421,75 @@ Relative output paths resolve from the project directory. Absolute paths can tar
|
|
|
309
421
|
|
|
310
422
|
The CLI, configuration, and build plugin use ESM (`.mjs`). Only Lua and TOC files are needed in game. `npm run build` in the framework repository generates distributable Lua modules and TypeScript declarations in `lib/`; addon builds include the framework modules they import.
|
|
311
423
|
|
|
424
|
+
## Stores
|
|
425
|
+
|
|
426
|
+
Use data classes to define defaults. Without a static token, records live only
|
|
427
|
+
in memory and are keyed by the class itself:
|
|
428
|
+
|
|
429
|
+
```ts
|
|
430
|
+
import { Store, StoreRegistry } from "wuira/store";
|
|
431
|
+
|
|
432
|
+
class SessionSettings extends Store {
|
|
433
|
+
CastSpellId = 1232;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const store = new StoreRegistry();
|
|
437
|
+
const snapshot = store.get(SessionSettings); // One-time, deeply readonly copy.
|
|
438
|
+
|
|
439
|
+
const unsubscribe = store.subscribe(SessionSettings, settings => {
|
|
440
|
+
console.log("New spell:", settings.CastSpellId);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
store.set(SessionSettings, settings => {
|
|
444
|
+
settings.CastSpellId = 635;
|
|
445
|
+
return settings;
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
unsubscribe();
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
`get()` does not subscribe. `subscribe()` observes future commits and returns an
|
|
452
|
+
unsubscribe function; call `get()` for initial data. Each subscriber receives an
|
|
453
|
+
independent snapshot. `set()` works on a detached draft, validates the returned
|
|
454
|
+
data, commits it, and sends one notification per observer. If the updater throws,
|
|
455
|
+
the previous record is preserved. Stores contain data fields, not class methods.
|
|
456
|
+
|
|
457
|
+
For persistence, declare a stable token and the owning addon's SavedVariables:
|
|
458
|
+
|
|
459
|
+
```toc
|
|
460
|
+
## SavedVariables: LumaUIDB
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
```ts
|
|
464
|
+
class LumaSettings extends Store {
|
|
465
|
+
static readonly Token = "luma.settings";
|
|
466
|
+
CastSpellId = 1232;
|
|
467
|
+
Width = 220;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const store = new StoreRegistry({ addon: "LumaUI", variable: "LumaUIDB" });
|
|
471
|
+
store.onReady(() => {
|
|
472
|
+
console.log(store.get(LumaSettings).Width);
|
|
473
|
+
store.set(LumaSettings, settings => {
|
|
474
|
+
settings.Width = 240;
|
|
475
|
+
return settings;
|
|
476
|
+
});
|
|
477
|
+
});
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
Add the TOC declaration to the addon's `addon.toc.in`. The registry waits for
|
|
481
|
+
`ADDON_LOADED` before opening persistent records. Tokenless records can still be
|
|
482
|
+
used immediately. WoW writes the saved table on normal logout/reload; `set()`
|
|
483
|
+
does not force a disk flush. Keep tokens stable across versions. New default
|
|
484
|
+
fields are filled in and incompatible saved field types fall back to defaults;
|
|
485
|
+
renaming keys or changing schema meaning still requires an application migration.
|
|
486
|
+
|
|
487
|
+
Supported values are finite numbers, strings, booleans, arrays, and nested data
|
|
488
|
+
objects. Functions, cycles, and secret values cannot be saved. Two classes cannot
|
|
489
|
+
claim the same token within a registry. Share one registry instance per database.
|
|
490
|
+
`Dispose()` removes its observers and pending initialization listener. Profile
|
|
491
|
+
selection, schema migrations, and reactive widget binding are separate features.
|
|
492
|
+
|
|
312
493
|
## Development
|
|
313
494
|
|
|
314
495
|
```sh
|
package/lib/Spells.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Representative spell IDs; aura sources resolve localized names across ranks. */
|
|
2
|
+
export declare enum Spells {
|
|
3
|
+
SealOfRighteousness = 21084,
|
|
4
|
+
SealOfTheCrusader = 21082,
|
|
5
|
+
SealOfCommand = 20375,
|
|
6
|
+
SealOfJustice = 20164,
|
|
7
|
+
SealOfLight = 20165,
|
|
8
|
+
SealOfWisdom = 20166,
|
|
9
|
+
SealOfFury = 20163
|
|
10
|
+
}
|
package/lib/Spells.lua
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
|
|
2
|
+
local ____exports = {}
|
|
3
|
+
--- Representative spell IDs; aura sources resolve localized names across ranks.
|
|
4
|
+
____exports.Spells = ____exports.Spells or ({})
|
|
5
|
+
____exports.Spells.SealOfRighteousness = 21084
|
|
6
|
+
____exports.Spells[____exports.Spells.SealOfRighteousness] = "SealOfRighteousness"
|
|
7
|
+
____exports.Spells.SealOfTheCrusader = 21082
|
|
8
|
+
____exports.Spells[____exports.Spells.SealOfTheCrusader] = "SealOfTheCrusader"
|
|
9
|
+
____exports.Spells.SealOfCommand = 20375
|
|
10
|
+
____exports.Spells[____exports.Spells.SealOfCommand] = "SealOfCommand"
|
|
11
|
+
____exports.Spells.SealOfJustice = 20164
|
|
12
|
+
____exports.Spells[____exports.Spells.SealOfJustice] = "SealOfJustice"
|
|
13
|
+
____exports.Spells.SealOfLight = 20165
|
|
14
|
+
____exports.Spells[____exports.Spells.SealOfLight] = "SealOfLight"
|
|
15
|
+
____exports.Spells.SealOfWisdom = 20166
|
|
16
|
+
____exports.Spells[____exports.Spells.SealOfWisdom] = "SealOfWisdom"
|
|
17
|
+
____exports.Spells.SealOfFury = 20163
|
|
18
|
+
____exports.Spells[____exports.Spells.SealOfFury] = "SealOfFury"
|
|
19
|
+
return ____exports
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { TimerSource } from "./TimerSource";
|
|
2
|
+
import { TextureSource } from "./TextureSource";
|
|
3
|
+
import { UnitSource } from "./UnitSource";
|
|
4
|
+
import type { UnitInput } from "./UnitSource";
|
|
5
|
+
export interface AuraTimerOptions {
|
|
6
|
+
/** Spell IDs resolve to localized names, so different ranks share a lookup. */
|
|
7
|
+
spellIds: readonly number[];
|
|
8
|
+
filter?: "HELPFUL" | "HARMFUL" | "HELPFUL|PLAYER" | "HARMFUL|PLAYER";
|
|
9
|
+
}
|
|
10
|
+
export type AuraTimerStatus = "active" | "inactive" | "restricted" | "unavailable";
|
|
11
|
+
/** Selected aura duration and icon; selection policy belongs to the application. */
|
|
12
|
+
export declare class AuraTimer extends TimerSource {
|
|
13
|
+
private readonly options;
|
|
14
|
+
readonly target: UnitSource;
|
|
15
|
+
readonly Texture: TextureSource;
|
|
16
|
+
private status;
|
|
17
|
+
constructor(unit: UnitInput, options: AuraTimerOptions);
|
|
18
|
+
get Status(): AuraTimerStatus;
|
|
19
|
+
private ReadAura;
|
|
20
|
+
private ReadDuration;
|
|
21
|
+
}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
|
|
2
|
+
-- Lua Library inline imports
|
|
3
|
+
local function __TS__Class(self)
|
|
4
|
+
local c = {prototype = {}}
|
|
5
|
+
c.prototype.__index = c.prototype
|
|
6
|
+
c.prototype.constructor = c
|
|
7
|
+
return c
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
local function __TS__ClassExtends(target, base)
|
|
11
|
+
target.____super = base
|
|
12
|
+
local staticMetatable = setmetatable({__index = base}, base)
|
|
13
|
+
setmetatable(target, staticMetatable)
|
|
14
|
+
local baseMetatable = getmetatable(base)
|
|
15
|
+
if baseMetatable then
|
|
16
|
+
if type(baseMetatable.__index) == "function" then
|
|
17
|
+
staticMetatable.__index = baseMetatable.__index
|
|
18
|
+
end
|
|
19
|
+
if type(baseMetatable.__newindex) == "function" then
|
|
20
|
+
staticMetatable.__newindex = baseMetatable.__newindex
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
setmetatable(target.prototype, base.prototype)
|
|
24
|
+
if type(base.prototype.__index) == "function" then
|
|
25
|
+
target.prototype.__index = base.prototype.__index
|
|
26
|
+
end
|
|
27
|
+
if type(base.prototype.__newindex) == "function" then
|
|
28
|
+
target.prototype.__newindex = base.prototype.__newindex
|
|
29
|
+
end
|
|
30
|
+
if type(base.prototype.__tostring) == "function" then
|
|
31
|
+
target.prototype.__tostring = base.prototype.__tostring
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
local function __TS__New(target, ...)
|
|
36
|
+
local instance = setmetatable({}, target.prototype)
|
|
37
|
+
instance:____constructor(...)
|
|
38
|
+
return instance
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
local function __TS__CloneDescriptor(____bindingPattern0)
|
|
42
|
+
local value
|
|
43
|
+
local writable
|
|
44
|
+
local set
|
|
45
|
+
local get
|
|
46
|
+
local configurable
|
|
47
|
+
local enumerable
|
|
48
|
+
enumerable = ____bindingPattern0.enumerable
|
|
49
|
+
configurable = ____bindingPattern0.configurable
|
|
50
|
+
get = ____bindingPattern0.get
|
|
51
|
+
set = ____bindingPattern0.set
|
|
52
|
+
writable = ____bindingPattern0.writable
|
|
53
|
+
value = ____bindingPattern0.value
|
|
54
|
+
local descriptor = {enumerable = enumerable == true, configurable = configurable == true}
|
|
55
|
+
local hasGetterOrSetter = get ~= nil or set ~= nil
|
|
56
|
+
local hasValueOrWritableAttribute = writable ~= nil or value ~= nil
|
|
57
|
+
if hasGetterOrSetter and hasValueOrWritableAttribute then
|
|
58
|
+
error("Invalid property descriptor. Cannot both specify accessors and a value or writable attribute.", 0)
|
|
59
|
+
end
|
|
60
|
+
if get or set then
|
|
61
|
+
descriptor.get = get
|
|
62
|
+
descriptor.set = set
|
|
63
|
+
else
|
|
64
|
+
descriptor.value = value
|
|
65
|
+
descriptor.writable = writable == true
|
|
66
|
+
end
|
|
67
|
+
return descriptor
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
local __TS__DescriptorGet
|
|
71
|
+
do
|
|
72
|
+
local getmetatable = _G.getmetatable
|
|
73
|
+
local ____rawget = _G.rawget
|
|
74
|
+
function __TS__DescriptorGet(self, metatable, key)
|
|
75
|
+
while metatable do
|
|
76
|
+
local rawResult = ____rawget(metatable, key)
|
|
77
|
+
if rawResult ~= nil then
|
|
78
|
+
return rawResult
|
|
79
|
+
end
|
|
80
|
+
local descriptors = ____rawget(metatable, "_descriptors")
|
|
81
|
+
if descriptors then
|
|
82
|
+
local descriptor = descriptors[key]
|
|
83
|
+
if descriptor ~= nil then
|
|
84
|
+
if descriptor.get then
|
|
85
|
+
return descriptor.get(self)
|
|
86
|
+
end
|
|
87
|
+
return descriptor.value
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
metatable = getmetatable(metatable)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
local __TS__DescriptorSet
|
|
96
|
+
do
|
|
97
|
+
local getmetatable = _G.getmetatable
|
|
98
|
+
local ____rawget = _G.rawget
|
|
99
|
+
local rawset = _G.rawset
|
|
100
|
+
function __TS__DescriptorSet(self, metatable, key, value)
|
|
101
|
+
while metatable do
|
|
102
|
+
local descriptors = ____rawget(metatable, "_descriptors")
|
|
103
|
+
if descriptors then
|
|
104
|
+
local descriptor = descriptors[key]
|
|
105
|
+
if descriptor ~= nil then
|
|
106
|
+
if descriptor.set then
|
|
107
|
+
descriptor.set(self, value)
|
|
108
|
+
else
|
|
109
|
+
if descriptor.writable == false then
|
|
110
|
+
error(
|
|
111
|
+
((("Cannot assign to read only property '" .. key) .. "' of object '") .. tostring(self)) .. "'",
|
|
112
|
+
0
|
|
113
|
+
)
|
|
114
|
+
end
|
|
115
|
+
descriptor.value = value
|
|
116
|
+
end
|
|
117
|
+
return
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
metatable = getmetatable(metatable)
|
|
121
|
+
end
|
|
122
|
+
rawset(self, key, value)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
local __TS__SetDescriptor
|
|
127
|
+
do
|
|
128
|
+
local getmetatable = _G.getmetatable
|
|
129
|
+
local function descriptorIndex(self, key)
|
|
130
|
+
return __TS__DescriptorGet(
|
|
131
|
+
self,
|
|
132
|
+
getmetatable(self),
|
|
133
|
+
key
|
|
134
|
+
)
|
|
135
|
+
end
|
|
136
|
+
local function descriptorNewIndex(self, key, value)
|
|
137
|
+
return __TS__DescriptorSet(
|
|
138
|
+
self,
|
|
139
|
+
getmetatable(self),
|
|
140
|
+
key,
|
|
141
|
+
value
|
|
142
|
+
)
|
|
143
|
+
end
|
|
144
|
+
function __TS__SetDescriptor(target, key, desc, isPrototype)
|
|
145
|
+
if isPrototype == nil then
|
|
146
|
+
isPrototype = false
|
|
147
|
+
end
|
|
148
|
+
local ____isPrototype_0
|
|
149
|
+
if isPrototype then
|
|
150
|
+
____isPrototype_0 = target
|
|
151
|
+
else
|
|
152
|
+
____isPrototype_0 = getmetatable(target)
|
|
153
|
+
end
|
|
154
|
+
local metatable = ____isPrototype_0
|
|
155
|
+
if not metatable then
|
|
156
|
+
metatable = {}
|
|
157
|
+
setmetatable(target, metatable)
|
|
158
|
+
end
|
|
159
|
+
if not isPrototype and not rawget(metatable, "_isOwnDescriptorMetatable") then
|
|
160
|
+
local instanceMetatable = {}
|
|
161
|
+
instanceMetatable._isOwnDescriptorMetatable = true
|
|
162
|
+
setmetatable(instanceMetatable, metatable)
|
|
163
|
+
setmetatable(target, instanceMetatable)
|
|
164
|
+
metatable = instanceMetatable
|
|
165
|
+
end
|
|
166
|
+
local value = rawget(target, key)
|
|
167
|
+
if value ~= nil then
|
|
168
|
+
rawset(target, key, nil)
|
|
169
|
+
end
|
|
170
|
+
if not rawget(metatable, "_descriptors") then
|
|
171
|
+
metatable._descriptors = {}
|
|
172
|
+
end
|
|
173
|
+
metatable._descriptors[key] = __TS__CloneDescriptor(desc)
|
|
174
|
+
metatable.__index = descriptorIndex
|
|
175
|
+
metatable.__newindex = descriptorNewIndex
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
-- End of Lua Library inline imports
|
|
179
|
+
local ____exports = {}
|
|
180
|
+
local ____TimerSource = require("datasources.TimerSource")
|
|
181
|
+
local TimerSource = ____TimerSource.TimerSource
|
|
182
|
+
local ____TextureSource = require("datasources.TextureSource")
|
|
183
|
+
local TextureSource = ____TextureSource.TextureSource
|
|
184
|
+
local ____UnitSource = require("datasources.UnitSource")
|
|
185
|
+
local resolveUnit = ____UnitSource.resolveUnit
|
|
186
|
+
--- Selected aura duration and icon; selection policy belongs to the application.
|
|
187
|
+
____exports.AuraTimer = __TS__Class()
|
|
188
|
+
local AuraTimer = ____exports.AuraTimer
|
|
189
|
+
AuraTimer.name = "AuraTimer"
|
|
190
|
+
__TS__ClassExtends(AuraTimer, TimerSource)
|
|
191
|
+
function AuraTimer.prototype.____constructor(self, unit, options)
|
|
192
|
+
local target = resolveUnit(nil, unit)
|
|
193
|
+
local events = {
|
|
194
|
+
"UNIT_AURA",
|
|
195
|
+
"PLAYER_ENTERING_WORLD",
|
|
196
|
+
"PLAYER_TARGET_CHANGED",
|
|
197
|
+
"PLAYER_FOCUS_CHANGED",
|
|
198
|
+
"SPELLS_CHANGED"
|
|
199
|
+
}
|
|
200
|
+
TimerSource.prototype.____constructor(
|
|
201
|
+
self,
|
|
202
|
+
function() return self:ReadDuration() end,
|
|
203
|
+
events,
|
|
204
|
+
target.Token
|
|
205
|
+
)
|
|
206
|
+
self.options = options
|
|
207
|
+
self.status = "inactive"
|
|
208
|
+
self.target = target
|
|
209
|
+
self.Texture = __TS__New(
|
|
210
|
+
TextureSource,
|
|
211
|
+
function()
|
|
212
|
+
local ____opt_0 = self:ReadAura()
|
|
213
|
+
return ____opt_0 and ____opt_0.icon
|
|
214
|
+
end,
|
|
215
|
+
events,
|
|
216
|
+
target.Token
|
|
217
|
+
)
|
|
218
|
+
end
|
|
219
|
+
function AuraTimer.prototype.ReadAura(self)
|
|
220
|
+
local query = C_UnitAuras and C_UnitAuras.GetAuraDataBySpellName
|
|
221
|
+
local getName = C_Spell and C_Spell.GetSpellName
|
|
222
|
+
if query == nil or getName == nil then
|
|
223
|
+
self.status = "unavailable"
|
|
224
|
+
return nil
|
|
225
|
+
end
|
|
226
|
+
do
|
|
227
|
+
local function ____catch()
|
|
228
|
+
self.status = "unavailable"
|
|
229
|
+
end
|
|
230
|
+
local ____try, ____hasReturned, ____returnValue = pcall(function()
|
|
231
|
+
for ____, id in ipairs(self.options.spellIds) do
|
|
232
|
+
do
|
|
233
|
+
local __continue8
|
|
234
|
+
repeat
|
|
235
|
+
local name = getName(id)
|
|
236
|
+
if issecretvalue(name) then
|
|
237
|
+
self.status = "restricted"
|
|
238
|
+
return true, nil
|
|
239
|
+
end
|
|
240
|
+
if name == nil then
|
|
241
|
+
__continue8 = true
|
|
242
|
+
break
|
|
243
|
+
end
|
|
244
|
+
local aura = query(self.target.Token, name, self.options.filter or "HELPFUL")
|
|
245
|
+
if issecretvalue(aura) then
|
|
246
|
+
self.status = "restricted"
|
|
247
|
+
return true, nil
|
|
248
|
+
end
|
|
249
|
+
if aura ~= nil then
|
|
250
|
+
self.status = "active"
|
|
251
|
+
return true, aura
|
|
252
|
+
end
|
|
253
|
+
__continue8 = true
|
|
254
|
+
until true
|
|
255
|
+
if not __continue8 then
|
|
256
|
+
break
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
local ____opt_6 = C_Secrets and C_Secrets.ShouldAurasBeSecret
|
|
261
|
+
local restricted = ____opt_6 and ____opt_6()
|
|
262
|
+
self.status = (issecretvalue(restricted) or restricted == true) and "restricted" or "inactive"
|
|
263
|
+
end)
|
|
264
|
+
if not ____try then
|
|
265
|
+
____hasReturned, ____returnValue = ____catch()
|
|
266
|
+
end
|
|
267
|
+
if ____hasReturned then
|
|
268
|
+
return ____returnValue
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
return nil
|
|
272
|
+
end
|
|
273
|
+
function AuraTimer.prototype.ReadDuration(self)
|
|
274
|
+
local aura = self:ReadAura()
|
|
275
|
+
if aura == nil then
|
|
276
|
+
return nil
|
|
277
|
+
end
|
|
278
|
+
do
|
|
279
|
+
local function ____catch()
|
|
280
|
+
self.status = "unavailable"
|
|
281
|
+
return true, nil
|
|
282
|
+
end
|
|
283
|
+
local ____try, ____hasReturned, ____returnValue = pcall(function()
|
|
284
|
+
local id = aura.auraInstanceID
|
|
285
|
+
if (C_UnitAuras and C_UnitAuras.GetAuraDuration) ~= nil and (issecretvalue(id) or id ~= nil) then
|
|
286
|
+
return true, C_UnitAuras.GetAuraDuration(self.target.Token, id)
|
|
287
|
+
end
|
|
288
|
+
local total = aura.duration
|
|
289
|
+
local ____end = aura.expirationTime
|
|
290
|
+
if issecretvalue(total) or issecretvalue(____end) then
|
|
291
|
+
self.status = "restricted"
|
|
292
|
+
return true, nil
|
|
293
|
+
end
|
|
294
|
+
if total == nil or ____end == nil or total <= 0 then
|
|
295
|
+
return true, nil
|
|
296
|
+
end
|
|
297
|
+
if C_DurationUtil == nil then
|
|
298
|
+
self.status = "unavailable"
|
|
299
|
+
return true, nil
|
|
300
|
+
end
|
|
301
|
+
local timer = C_DurationUtil.CreateDuration()
|
|
302
|
+
timer:SetTimeFromStart(____end - total, total)
|
|
303
|
+
return true, timer
|
|
304
|
+
end)
|
|
305
|
+
if not ____try then
|
|
306
|
+
____hasReturned, ____returnValue = ____catch()
|
|
307
|
+
end
|
|
308
|
+
if ____hasReturned then
|
|
309
|
+
return ____returnValue
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
__TS__SetDescriptor(
|
|
314
|
+
AuraTimer.prototype,
|
|
315
|
+
"Status",
|
|
316
|
+
{get = function(self)
|
|
317
|
+
self:ReadAura()
|
|
318
|
+
return self.status
|
|
319
|
+
end},
|
|
320
|
+
true
|
|
321
|
+
)
|
|
322
|
+
return ____exports
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TimerSource } from "./TimerSource";
|
|
2
|
+
import { UnitSource } from "./UnitSource";
|
|
3
|
+
import type { UnitInput } from "./UnitSource";
|
|
4
|
+
/** Remaining cast/channel time using the native duration object. */
|
|
5
|
+
export declare class CastTimer extends TimerSource {
|
|
6
|
+
readonly target: UnitSource;
|
|
7
|
+
get SpellName(): string;
|
|
8
|
+
constructor(unit?: UnitInput);
|
|
9
|
+
}
|