Skip to content

feat(catalog): implement LTD raffle system#9

Merged
Diddyy merged 5 commits intonitrodevco:devfrom
Diddyy:feature/ltd-raffle-system
Feb 10, 2026
Merged

feat(catalog): implement LTD raffle system#9
Diddyy merged 5 commits intonitrodevco:devfrom
Diddyy:feature/ltd-raffle-system

Conversation

@Diddyy
Copy link
Collaborator

@Diddyy Diddyy commented Feb 8, 2026

Summary

This PR implements a comprehensive Limited Edition (LTD) system tailored for modern Habbo standards. It introduces a
weighted raffle mechanism to combat bot-sniping, a two-phase sale process (Raffle -> FCFS), and full Landing View
integration for drop countdowns.

Key Features

  • Weighted Raffle Engine: Isolated LtdRaffleGrain manages a configurable buffer window (default 20s). Players join a
    pool rather than buying instantly, ensuring fair distribution during high-traffic drops.
  • Fairness Criteria: Dynamic probability calculation based on multiple player metrics (configurable via
    appsettings.json):
    • Badge Count, Account Age, Achievement Score, Friend Count, Room Count, Furniture Count, and Respects.
  • Two-Phase Distribution:
    • Phase 1 (Raffle): Randomized or weighted draw after the timer expires.
    • Phase 2 (FCFS): Automatic transition to "First-Come-First-Served" instant purchases once the raffle concludes.
  • Smart Serial Logic:
    • Support for Habbo-style randomized serials.
    • Dynamic sequential assignment (calculated as (Total - Remaining) + 1) to ensure database consistency.
  • Landing View Sync: Implemented Header 2178 (LimitedOfferAppearingNext) to display countdown timers on the Hotel
    View and automatically disable/hide "Buy" buttons until the drop is live.
  • Anti-Hoarding: Optional "One-Per-Customer" toggle mapping to Habbo Error Code 6.
  • Persistence: Added has_raffle_finished state tracking to ensure raffle states survive emulator restarts.

Technical Highlights

  • Economic Safety: Atomic database transactions (FOR UPDATE locks) and series-specific grain isolation prevent
    double-minting or duplicate serials.
  • Performance: Utilizes IPlayerGrain snapshots for weighting factor lookups to avoid database hammering during the
    20-second rush.
  • Upstream Compatible: Adapted to the latest IPlayerWalletGrain refactoring (removal of GetSnapshotAsync).
  • Code Quality: Clean implementation using C# 12 patterns (Primary Constructors, Collection Expressions) and
    condensed logic to avoid over-engineering.

⚙️ Configuration
Hotel owners can tune fairness and timing directly via appsettings.json:

   1 "Turbo:Catalog": {
   2   "LtdRaffle": {
   3     "DefaultBufferSeconds": 20,
   4     "RandomizeSerials": true,
   5     "LimitOnePerCustomer": true,
   6     "BadgeCount": { "Enabled": true, "BonusPerUnit": 0.02, "MaxBonus": 1.0 },
   7     "AccountAgeDays": { "Enabled": true, "BonusPerUnit": 0.0013, "MaxBonus": 0.5 }
   8   }
   9 }

🗄 Database Changes

  • ltd_series: Stores drop configuration, stock levels, and raffle state.
  • ltd_raffle_entries: Full audit log for every entry attempt, win, and assigned serial.

✅ Checklist

  • Code formatted via csharpier.
  • Builds successfully on latest origin/main.
  • No duplicate serial numbers possible (Atomic Locks).
  • Landing View countdown synced.

- Added weighted selection based on badges, account age, achievement score, friend count, room count, and furniture count
- Implemented 20s buffer window with automatic drawing logic
- Added support for both randomized and sequential serial numbers
- Implemented Landing View countdown timer (Header 2178)
- Added 'One-Per-Customer' anti-hoarding policy
- Refactored to lean, high-performance C# 12 patterns (Primary Constructors, Collection Expressions)
@Diddyy Diddyy force-pushed the feature/ltd-raffle-system branch from c106942 to c1d7cf8 Compare February 9, 2026 08:47
@Diddyy Diddyy changed the base branch from main to dev February 10, 2026 14:32
@Diddyy Diddyy merged commit 9390b99 into nitrodevco:dev Feb 10, 2026
0 of 3 checks passed
@Diddyy Diddyy deleted the feature/ltd-raffle-system branch February 10, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant