D&D Character Builder: Optional Subraces!

by Admin 42 views
Character Builder: Use `subrace_required` Flag for Optional Subrace Selection

Hey guys! Let's dive into some exciting improvements for our D&D character builder. This update focuses on giving players more flexibility when choosing their character's race and subrace. We're going to implement a subrace_required flag, which will make the subrace selection optional for races like Human and Dragonborn. This means you won't be forced to pick a subrace if you don't want to! This is all part of the grand plan to make the character builder even better, as outlined in Issue #175. And it builds directly upon the backend changes made in Issue #183.

Problem: Forced Subrace Selection

Currently, the character builder wizard makes you pick a subrace whenever a race has subraces in the database. Check out the TypeScript code below:

// Current logic in useWizardSteps.ts
visible: () => {
 const store = useCharacterBuilderStore()
 return store.needsSubrace // True if subraces.length > 0
}

This can be a real pain, especially for races like Human and Dragonborn, where the base race is perfectly complete without needing a subrace. These subraces are meant to be optional variants, not mandatory choices. We want to give players the freedom to keep their characters as the base race if they prefer.

Solution: The subrace_required Flag

The backend team has been awesome and added a subrace_required flag to races. Now, we need to update the frontend to use this flag. This will allow us to determine whether a subrace selection is actually required or if it's optional.

Changes Required: Let's Get Coding!

Here's a breakdown of the changes we need to make to the character builder:

1. Update needsSubrace Computed Property

First, we need to update the needsSubrace computed property in the characterBuilder.ts store. Instead of just checking if the race has subraces, we'll use the new subrace_required flag from the API.

// stores/characterBuilder.ts
const needsSubrace = computed(() => {
 if (!selectedBaseRace.value) return false
 // Use the API flag instead of just checking array length
 return selectedBaseRace.value.subrace_required === true
})

2. Add Optional Subrace Step

Next, we'll add an optional subrace step for races where subrace_required === false. This step will only appear if the race has subraces but doesn't require one to be selected.

  • Show the subrace step, but make it optional.
  • Add a "None - Keep base [Race]" option at the top of the list.
  • Allow the player to proceed without selecting a subrace.

Here's the code for the new computed property:

// New computed
const hasOptionalSubraces = computed(() => {
 if (!selectedBaseRace.value) return false
 const hasSubraces = (selectedBaseRace.value.subraces?.length ?? 0) > 0
 return hasSubraces && selectedBaseRace.value.subrace_required === false
})

3. Update Step Visibility Logic

Now, let's update the step visibility logic in useWizardSteps.ts to incorporate the new hasOptionalSubraces property. The subrace step should be visible if a subrace is required OR if optional subraces exist.

// useWizardSteps.ts
{
 name: 'subrace',
 label: 'Subrace',
 icon: 'i-heroicons-sparkles',
 visible: () => {
 const store = useCharacterBuilderStore()
 // Show if required OR if optional subraces exist
 return store.needsSubrace || store.hasOptionalSubraces
 }
}

4. Update StepSubrace.vue

The StepSubrace.vue component needs to be updated to handle both required and optional subrace selections.

  • If subrace_required === true: Keep the current behavior, where the player must select a subrace.
  • If subrace_required === false:
    • Add a "None" option to the list of subraces.
    • Update the validation to allow no selection.
    • Change the button text to reflect the optional nature of the selection:
      • "Continue without subrace" if no subrace is selected.
      • "Continue with [Subrace]" if a subrace is selected.

5. Update TypeScript Types

Finally, we need to update the TypeScript types to include the new subrace_required field in the Race interface.

interface Race {
 // ... existing fields
 subrace_required?: boolean
}

Acceptance Criteria: How to Know We're Done

Here's a checklist to ensure we've implemented the changes correctly:

  • [ ] Human can proceed without selecting Variant Human.
  • [ ] Dragonborn can proceed without selecting a variant.
  • [ ] Elf still requires subrace selection (High/Wood/Drow).
  • [ ] Dwarf still requires subrace selection (Hill/Mountain).
  • [ ] When optional subraces exist, the "None" option is available.
  • [ ] Selecting "None" clears any previous subrace selection.
  • [ ] The review step shows "Human" not "Human (None)".

Test Cases: Putting It to the Test

Here's a table summarizing the expected behavior for different races:

Race Has Subraces subrace_required Expected Behavior
Human Yes (Variant) false Optional step, can skip
Dragonborn Yes (Chromatic, etc.) false Optional step, can skip
Elf Yes (High, Wood, Drow) true Required step, must select
Dwarf Yes (Hill, Mountain) true Required step, must select
Half-Orc No N/A Step hidden

With these changes, the character builder will be much more user-friendly and flexible. Players will have the freedom to create the characters they want without being forced into unwanted subrace selections. Let's get this done and make the character builder even better! Thanks, team!