lessons learned

Guide for lessons learned

Lessons Learned

Iterative Design Process

User Feedback Integration

This implementation went through multiple refinement cycles based on user feedback:
  1. Initial Design: Generic "Mind/Chaos/Death/Wrath" bijas
  2. First Refinement: Renamed to deity names (Chandra/Kali/Yama)
  3. Second Refinement: Separated Chaos and Wrath (Rudra vs Rahu)
  4. Third Refinement: Renamed remaining generic bijas (Body→Hanuman, Cosmic→Vishnu, Astral→Indra)
  5. Fourth Refinement: Standardized spell costs per tier
  6. Fifth Refinement: Strict one-catalyst-per-tier rule
Lesson: Be prepared for iterative refinement when implementing culturally-specific systems. User domain knowledge is invaluable.

Naming Matters

User Request: "Bija filled coconuts should not be called coconuts anymore"
Before: "Hastinapur Teleport Coconut" After: "Hastinapur Teleport"
Lesson: Item names should emphasize function over implementation. Players think "I want to teleport to Hastinapur", not "I want to use a coconut".

Technical Challenges

String-to-ID Conversion

Challenge: Data files use string IDs ("air_bija"), but game uses hashed ItemId(u32).
Solution: string_to_id() utility function for consistent hashing.
Pitfall: Must use exact same strings in JSON and code, or hashes won't match.

Inventory API Consistency

Error: inventory.add_item(id, quantity) missing third parameter
Fix: inventory.add_item(id, quantity, &items_db)
Lesson: Always check function signatures when working with refactored APIs. The inventory system was recently updated to require item definitions for validation.

Bevy System Parameter Limits

Problem: ui_main_layout exceeded 16 parameters after adding magic UI.
Solution: Created SystemParam group to bundle related queries.
Lesson: When systems grow complex, use SystemParam to organize and reduce parameter count.

Type Casting in UI

Error: expected i32, found u32 when passing skills.get_level() to UI functions.
Fix: Cast with as i32 at call site.
Lesson: Be explicit about integer types when crossing API boundaries, especially in UI code.

Module Architecture Conflicts

Error: expected systems::magic::SelectSpellEvent, found systems::skills::magic::SelectSpellEvent
Root Cause: Magic system implemented across TWO modules:
  • src/systems/skills/magic.rs (original skill-based implementation)
  • src/systems/magic/ (new combat-focused module)
Both defined SelectSpellEvent, creating incompatible types.
Fix: Consolidate to single canonical module, delete duplicate definitions.
Lesson: When refactoring code between modules, immediately delete old definitions. Use grep -r "EventName" src/ to check for duplicates. Rust's type system treats identically-named structs in different modules as completely different types.
See: troubleshooting/duplicate_event_definitions.md for detailed analysis.

Design Patterns

Event-Driven UI

All UI interactions dispatch events rather than directly modifying state:
  • SelectSpellEvent
  • CastSpellEvent
  • PrepareCoconutEvent
  • BreakCoconutEvent
Benefits:
  • Decoupled UI from game logic
  • Easier to test
  • Network-ready (events can be serialized)
  • Clear audit trail
Lesson: Event-driven architecture scales better than direct state mutation, especially for multiplayer games.

Data-Driven Spells

Spells defined in JSON, not hardcoded in Rust.
Benefits:
  • Rapid iteration (no recompilation)
  • Moddable by players
  • Easy to balance
  • Clear documentation (JSON is self-documenting)
Tradeoffs:
  • Runtime validation needed
  • Slightly more complex loading code
  • Harder to catch typos (no compile-time checks)
Lesson: For content-heavy systems (spells, items, quests), data-driven design is worth the tradeoff.

Tab vs Window UI

Decision: Spell Book as tab, Coconut UI as window.
Rationale:
  • Frequently-used interfaces should be tabs (always accessible)
  • Occasional-use interfaces can be windows (less clutter)
Lesson: Match UI patterns to usage frequency. Don't make players open/close windows for common actions.

Cultural Authenticity

Deity Research

Each bija was carefully mapped to a Hindu deity with appropriate associations:
  • Chandra (Moon): Mind, illusion → Pulse (basic mental focus)
  • Rahu (Shadow Planet): Chaos, eclipse → Volley (chaotic strikes)
  • Yama (Death): Mortality → Cascade (death-dealing)
  • Rudra (Storm): Wrath → Cataclysm (destructive fury)
Lesson: When implementing culturally-specific content, research is essential. Generic fantasy tropes don't work for mythology-based games.

Coconut Ritual

Using coconuts with "three eyes" references:
  1. Actual coconuts (sacred in Hindu rituals)
  2. Shiva's third eye (mystical symbolism)
  3. Unique game mechanic (not just "teleport tablets")
Lesson: Cultural authenticity can inspire unique mechanics that distinguish your game.

Testing Insights

Manual Testing Workflow

  1. Compile and run game
  2. Create test character with Magic level 70
  3. Spawn all bija types in inventory
  4. Test each spell tier
  5. Test coconut ritual UI
  6. Verify XP gains
Lesson: For UI-heavy features, manual testing is essential. Automated tests can't catch UX issues.

Edge Cases to Test

  • Casting spell without enough bijas
  • Casting spell below level requirement
  • Charging coconut with invalid bija combination
  • Breaking coconut without having it in inventory
  • Selecting spell, then deselecting
Lesson: Think through failure cases early. Good error handling improves player experience.

Future Improvements

Suggested Enhancements

  1. Spell Animations: Visual effects for each element
  2. Sound Effects: Unique sounds per deity/element
  3. Spell Combos: Chain spells for bonus effects
  4. Bija Crafting: Tapasya skill for creating bijas from Sphatikas
  5. Teleport Destinations: More locations, unlock via quests
  6. Utility Spell Effects: Actually implement buffs/debuffs
  7. Spell Cooldowns: Prevent spam-casting high-tier spells

Technical Debt

  1. Hardcoded Bija List: Coconut UI uses hardcoded bija IDs (should iterate items_db)
  2. Duplicate Event Definitions: SelectSpellEvent exists in both systems::skills::magic and systems::magic (needs consolidation)
  3. TODO: Actual Teleportation: BreakCoconutEvent only logs destination, doesn't teleport
  4. No Spell Failure: 100% success rate (could add accuracy checks)
  5. No Animation System: Spells cast instantly (needs animation integration)

Conclusion

This implementation demonstrates:
  • ✅ Successful data-driven architecture
  • ✅ Cultural authenticity in game design
  • ✅ Iterative refinement based on user feedback
  • ✅ Event-driven UI patterns
  • ✅ Clean separation of concerns (data/logic/UI)
Key Takeaway: Building culturally-specific game systems requires collaboration with domain experts (the user in this case) and willingness to iterate on design.