D&D Character Builder: Optional Subraces!
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!