Seasonal Events

Last updated: July 5, 2026

dMUD Seasonal Event System

Added: June 2026 — commits b03682a6 (core), 3deed0af (per-system integration), 3d8f05ff (character pass) Core module: dmud/seasonal.go (new module, intentionally isolated from events.go core churn)

A time-aware seasonal layer for dMUD that drives festivals, weather, seasonal NPC spawns, and seasonal stat/equipment bonuses. Built as a sibling module to the existing event system so the legacy events.go switch remains untouched.

🌍 Seasons

Season detection uses meteorological windows (not astronomical):

Season Window (approx)
Spring March–May
Summer June–August
Autumn September–November
Winter December–February

API:

  • GetCurrentSeason() — current season enum
  • GetSeasonForTime(t time.Time) — season for arbitrary timestamp
  • GetSeasonInfo(season) — metadata record from SeasonInfo registry

🎪 Festivals

Time-boxed windows with their own NPCs/lore/effects:

Festival Period
halloween Oct–early Nov
midsummer June–July
harvest September
wintersfeast December–January
springbloom April–May

IsFestivalActive(name) returns true inside the active window; FestivalInfo returns the metadata record.

🌧️ Weather

WeatherState enum: clear / rain / snow / thunder / fog

Helpers:

  • FormatSeasonBanner(season) / FormatWeatherBanner(weather) — ANSI-coloured banners for the terminal

🎯 Stat Bonuses (Character Pass — commit 3d8f05ff)

SeasonalStatBonus table gives per-season fishing/mining/woodcutting XP bonuses:

Helper Returns
GetSeasonalStatBonus(season, skill) Bonus multiplier for one skill in one season
GetActiveSeasonalBonuses() All active bonuses (season + festival stacking)

The character pass also adds seasonal equipment effects — equipment items can carry season-triggered modifiers (e.g. a midsummer sword granting bonus fishing XP only during midsummer).

🔁 Event System Integration (events.go)

Commit b03682a6 extended events.go without disrupting the existing dispatcher:

  • New EventType values: seasonal, seasonal_start, seasonal_end, weather, festival (and random, which was defined but previously undistributed).
  • Event struct gained optional fields: Season, Weather, Festival, BonusXP, StatSkill, StatBonus, parsed from INI.
  • Dispatchers added to checkEvents: handleSeasonal, handleFestival, handleWeather, handleRandom.
  • New actions: give_xp, apply_seasonal_bonus, set_weather.

🧩 Per-System Integration (commit 3deed0af)

Seasonal logic is surfaced per-room/per-NPC so individual rooms and NPC Lua scripts can react:

  • Rooms can declare seasonal behaviour via INI.
  • NPC Lua scripts gain get_game_time / get_time_of_day (already present from previous NPC-events pass) and the new seasonal context.
  • Spawning: seasonalNPCs registry — adding a seasonal NPC requires only a registry entry + a Lua script (no Go changes).

🧹 Holiday End Event Fix

Commit 9fe6c6be stopped holiday_end events from re-triggering every minute. The previous loop reset its own cooldown marker each tick, causing a flood of post-holiday announcements.

📁 Key Files

File Purpose
dmud/seasonal.go Season / festival / weather / stat-bonus registry, helpers
dmud/events.go New event types + dispatchers + new actions
dmud/data/rooms/*.ini Rooms with seasonal hooks (e.g. ambient time-aware rooms)
dmud/data/scripts/*.lua on_time_change, on_seasonal_start, on_festival, on_weather handlers

🧪 Test Bot Coverage

Per AGENTS.md guidance, the headless test bot (cmd/dmud-bot/) must gain phase assertions for:

  • Season detection (current season matches meteorological window)
  • Festival activation window
  • Holiday-end event not re-triggering
  • apply_seasonal_bonus action applying StatSkill/StatBonus to the user

🔗 Related