-
Notifications
You must be signed in to change notification settings - Fork 191
Documentation for moonwatch.lic
moonwatch tracks the three DragonRealms moons (Katamba, Xibar, Yavash), the sun, and the full Elanthian calendar in real time. It tells you what is up right now, how long until the next rise or set, each moon's lunar phase, and the current date, season, and time of day. It works the instant you start it, with no setup and no network connection, on every game instance.
Everything it computes is published to UserVars, so other scripts
(combat-trainer, gate, autocontingency, mm, the moonmage common library) read it
directly.
See also: Technical Reference (how the model works and how the constants were derived) and Design History (the changelog and the retired Firebase design).
- Quick start
- What it does
- Commands
- The status window
- The moon alias
- Using moonwatch data in other scripts
- Accuracy and self-correction
- Game instances
- Calibration logging
- Troubleshooting
- Changelog
;moonwatch
That is all that is required. The script begins predicting immediately and keeps itself accurate by watching for moon and sun events in the game. Add it to your autostart so it is always running:
;e autostart('moonwatch')
To see status at a glance, add the moon alias once:
;moonwatch alias
Then type moon any time to print all three moons.
- Predicts moon rise and set times to the exact game second.
- Reports each moon's lunar phase (new, waxing crescent, first quarter, waxing gibbous, full, waning gibbous, third quarter, waning crescent) and an approximate countdown to the next phase.
- Predicts sunrise and sunset across the seasons (the day is longest in summer, shortest in winter).
- Tracks the full calendar: year, month, day, anlas, rois, season, and a named time of day such as "mid-morning" or "dusk".
- Self-corrects. Every time you witness a moon or the sun rise or set, the script compares it to its prediction and tightens the result. You never have to do anything.
- Works offline and on every game instance (Prime, Platinum, Fallen, Test). There is no shared database and no network traffic.
All toggle settings are saved per character and persist across sessions until you turn them off.
| Command | Effect |
|---|---|
;moonwatch |
Start tracking. |
;moonwatch debug |
Turn on debug output (stays on for future runs). |
;moonwatch nodebug |
Turn off debug output. |
;moonwatch window |
Open a small moon status window (stays on for future runs). |
;moonwatch nowindow |
Close the moon status window. |
;moonwatch alias |
Add a global moon alias that prints all three moons. |
;moonwatch log |
Start logging events to CSV for calibration, and auto-observe each moon at rise (this character). |
;moonwatch nolog |
Stop logging events and rise auto-observe. |
;moonwatch reset |
Reset all offsets to zero and exit. Use if predictions look wrong. |
You can combine the start command with toggles, for example ;moonwatch debug window.
;moonwatch window opens a compact window showing all three moons in short form:
[k]+(45) [y]-(12) [x]+(78)
The letter is the moon (k, y, x). A plus means it is up; a minus means it is down.
The number is minutes until the next event. So [k]+(45) means Katamba is up and
sets in 45 minutes, while [y]-(12) means Yavash is down and rises in 12 minutes.
The window updates whenever the minute value changes and refreshes itself once a minute even when the game is quiet, so it stays correct after a reconnect or an idle stretch.
After running ;moonwatch alias, typing moon prints the full status of all
three moons, for example:
katamba is up for 45 minutes (waxing crescent) : yavash will rise in 12 minutes (new) : xibar is up for 78 minutes (full)
The alias is self-aware: it checks whether moonwatch is actually running
before it reads the data. If moonwatch is not running, typing moon tells you so
instead of echoing stale numbers:
moonwatch is not running - start it with ;moonwatch
The alias also keeps itself up to date automatically. When a new version of
moonwatch changes what the moon alias should print, the next ;moonwatch start
silently upgrades your existing alias in place -- you do not have to re-run
;moonwatch alias. moonwatch only ever touches a moon alias it recognizes as
its own; if you have created your own moon alias for something else, it is left
alone, and moonwatch never creates the alias unless you asked for it with
;moonwatch alias.
moonwatch publishes everything to UserVars, which any other script can read.
These fields are kept up to date every loop while moonwatch runs.
UserVars.moons['visible'] # array of moons currently up, e.g. ['katamba','xibar']
UserVars.moons['running'] # true while moonwatch is maintaining this data
UserVars.moons['katamba']['visible'] # true if Katamba is up
UserVars.moons['katamba']['timer'] # whole minutes until next event
UserVars.moons['katamba']['timer_seconds'] # seconds until next event
UserVars.moons['katamba']['t'] # 0..1 progress across the current arc
UserVars.moons['katamba']['phase'] # 'waxing crescent'
UserVars.moons['katamba']['phase_index'] # 0..7 (0 = new)
UserVars.moons['katamba']['next_phase'] # upcoming phase name
UserVars.moons['katamba']['next_phase_seconds'] # approx seconds to next phase
UserVars.moons['katamba']['pretty'] # "katamba is up for 45 minutes (waxing crescent)"
UserVars.moons['katamba']['short'] # "[k]+(45)"UserVars.sun['day'] # true if the sun is up
UserVars.sun['night'] # true if the sun is down
UserVars.sun['visible'] # same as 'day'
UserVars.sun['timer'] # whole minutes until next event
UserVars.sun['timer_seconds'] # seconds until next event
UserVars.sun['season'] # 'winter' | 'spring' | 'summer' | 'fall'
UserVars.sun['time_of_day'] # e.g. 'mid-afternoon'
UserVars.sun['pretty'] # "sun sets in 45 minutes (mid-afternoon)"
UserVars.sun['short'] # "[S]+(45)"
UserVars.sun['running'] # true while moonwatch is maintaining this dataUserVars.calendar['date_string'] # "446-01-15 06:12"
UserVars.calendar['year'] # 446
UserVars.calendar['month'] # 1..10
UserVars.calendar['day'] # 1..40
UserVars.calendar['day_of_year'] # 0..399
UserVars.calendar['anlas'] # 0..11 (DR hour)
UserVars.calendar['rois'] # 0..29 (DR minute)
UserVars.calendar['season'] # season string
UserVars.calendar['time_of_day'] # named period
UserVars.calendar['year_name'] # "Year of the Emerald Dolphin"
UserVars.calendar['month_name'] # "Akroeg the Ram"
UserVars.calendar['anlas_name'] # "Phelim's Vigil"
UserVars.calendar['running'] # true while moonwatch is maintaining this dataScripts that read UserVars.moons['visible'], the per-moon timer, and
UserVars.sun['day']/['night'] (such as the combat trainer, gate,
autocontingency, mm, and the moonmage common library) work unchanged.
The ['running'] flag is optional and non-destructive: it is true while
moonwatch is live and set to false when moonwatch exits cleanly, without
removing any other keys. A consumer that wants to know whether the data is fresh
can check it; existing consumers that ignore it are unaffected.
Predictions are accurate the moment the script starts, with no warm-up.
- Moons are predicted to the exact game second. The game fires moon events on 60-second boundaries, and moonwatch computes the precise boundary rather than an average, so it does not drift. When you witness a rise or set, moonwatch only adjusts if its prediction was genuinely on the wrong tick, so a correct prediction is left exactly where it is.
- The sun is predicted from an empirical day-of-year table built from observed sun events, so its cold-start prediction is essentially exact. (A seasonal cosine is kept only as a fallback for any uncovered day.) It also self-corrects from the first sunrise or sunset you witness.
-
Lunar phase is computed from the DR client's own orbital constants. It is
model-only (there is no passive phase broadcast to correct against) but has been
validated against the in-game
observe <moon>verb.
If predictions ever look clearly wrong, run ;moonwatch reset and start the
script again. It will recalibrate from your next observed events.
moonwatch works identically on Prime, Platinum, Fallen, and Test. The moon and sun periods are game-code constants that are the same on every instance, and each character's correction offsets are stored per instance and per character, so instances never bleed into each other. On a non-Prime instance the script prints a one-time startup notice that the absolute phase self-calibrates from your observed rise/set events; predictions converge after the first one.
If you want to contribute calibration data or re-derive the constants, enable
logging with ;moonwatch log. It writes CSV files to your Lich data directory
(moon events, sun events, and moon-phase observations) recording the raw observed
intervals and phase wordings. While logging is on, moonwatch also auto-observes
each moon as it rises to capture its phase readout. Disable with
;moonwatch nolog. Logging is per character and off by default. See the
Technical Reference for the file formats and the
re-derivation procedure.
Predictions are wrong. Run ;moonwatch reset, then ;moonwatch again. The
model recalibrates as you observe events. Watching one full cycle of each body is
enough to lock it in.
The window shows zeros or stale data. Kill and restart: ;kill moonwatch,
then ;moonwatch window. The window cache is cleared on every start.
Typing moon says moonwatch is not running. That is the alias working
correctly -- start moonwatch with ;moonwatch.
Typing moon shows the same numbers every time. You have an older moon
alias from before the self-aware version and moonwatch has not upgraded it yet
(for example it has not been restarted since you updated). Run ;moonwatch alias
once to install the current alias; after that it self-updates on start.
Nothing seems to update. Confirm the script is running with ;list. Other
scripts that depend on moon data will start moonwatch automatically if it is not
already running.
- Instance-awareness. The moon and sun periods are game-code constants (cross-validated against the DR client's own hard-coded sidereal periods to within ~0.05s), so they are identical on every instance; offsets are already scoped per instance and per character, so each instance self-calibrates independently. Non-Prime instances print a one-time startup notice.
-
Self-aware, self-updating
moonalias. The alias now reports when moonwatch is not running instead of echoing stale data, and an existing moonwatch alias auto-upgrades to the current body on the next start (read from the alias service database). It never creates an alias you did not ask for and never overwrites an unrelatedmoonalias. -
UserVars.*['running']freshness flag. Non-destructively marks moon/sun/ calendar data live at startup and stale on exit.
-
Lunar phase. Each moon now reports its phase and an approximate next-phase
countdown, exposed via
UserVars(phase,phase_index,next_phase,next_phase_seconds). While logging is on, moonwatch auto-observes each moon at rise to capture the game's phase wording and validate the model.
-
Drift-free moon periods. The moon cycle constants use the game's true
fractional periods instead of rounded integers, so moon predictions no longer
drift over weeks and offsets stay near zero on their own. After updating, run
;moonwatch resetonce per character to clear old offsets (the internal moon anchors moved).
-
Empirical sun lookup table. Sunrise and sunset are read from a day-of-year
table built from observed sun events, replacing the seasonal cosine (kept only
as a fallback). This makes the sun prediction essentially exact from a cold
start.
UserVars.sunfields are unchanged.
- Bresenham tick prediction for moons, replacing an average that was always a little off.
- Local self-correction only; corrections come entirely from your own observed events.
-
Removed Firebase and the
correctargument. No network calls, no shared database. If you havecorrectin an autostart or profile, remove it. -
Full calendar exposed via
UserVars.calendar, plustimer_secondsalongside the whole-minutetimer.
For the complete version history (back to v2.0) and the retired Firebase design, see Design History.