Agent skill
tg-character-templates
Character template system for World of Darkness character creation. Use when implementing template selection in character creation flows, creating/managing CharacterTemplate objects, adding template support to new character types, or working with the template import/export features. Triggers on character template work, pre-configured character concepts, template selection views.
Stars
163
Forks
31
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/product/tg-character-templates
SKILL.md
Character Template System
Pre-configured character concepts from sourcebooks that speed up character creation.
Overview
- 30 pre-configured templates (5 per gameline)
- Optional template selection during character creation
- Full customization after template application
- Usage tracking and admin management at
/admin/core/charactertemplate/
Template Data Structure
python
CharacterTemplate(
# Identity
name="Template Name",
gameline="mta", # vtm, wta, mta, wto, ctd, dtf
character_type="mage",
concept="Concept Name",
# Character Data (JSONFields)
basic_info={"nature": "FK:Archetype:Name", "demeanor": "FK:Archetype:Name"},
attributes={"strength": 2, "perception": 4, ...},
abilities={"alertness": 2, "investigation": 3, ...},
backgrounds=[{"name": "Contacts", "rating": 3}],
powers={"auspex": 2, "celerity": 1},
merits_flaws=[{"name": "Merit Name", "rating": 2}],
specialties=["Ability (Specialty)"],
languages=["English", "Latin"],
# Metadata
is_official=True,
is_public=True,
times_used=0, # Auto-incremented
)
Note: Use "FK:Model:Name" format for foreign key references (resolved during apply).
Adding Template Selection to Character Types
Step 1: Add Form and View (in character views file)
python
from core.models import CharacterTemplate
from django import forms
class CharacterTemplateSelectionForm(forms.Form):
template = forms.ModelChoiceField(
queryset=CharacterTemplate.objects.none(),
required=False,
empty_label="No template - build from scratch",
widget=forms.RadioSelect,
)
def __init__(self, *args, gameline="vtm", character_type="vampire", **kwargs):
super().__init__(*args, **kwargs)
self.fields["template"].queryset = CharacterTemplate.objects.filter(
gameline=gameline, character_type=character_type, is_public=True
).order_by("name")
class VampireTemplateSelectView(LoginRequiredMixin, FormView):
form_class = CharacterTemplateSelectionForm
template_name = "characters/vampire/vampire/template_select.html"
def dispatch(self, request, *args, **kwargs):
self.object = get_object_or_404(Vampire, pk=kwargs["pk"], owner=request.user)
if self.object.creation_status > 0:
return redirect("characters:vampire:vampire_creation", pk=self.object.pk)
return super().dispatch(request, *args, **kwargs)
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["gameline"] = "vtm"
kwargs["character_type"] = "vampire"
return kwargs
def form_valid(self, form):
template = form.cleaned_data.get("template")
if template:
template.apply_to_character(self.object)
messages.success(self.request, f"Applied template '{template.name}'.")
self.object.creation_status = 1
self.object.save()
return redirect("characters:vampire:vampire_creation", pk=self.object.pk)
Step 2: Add URL
python
path("vampire/<int:pk>/template/", VampireTemplateSelectView.as_view(), name="vampire_template"),
Step 3: Update Basics View
python
def get_success_url(self):
return reverse("characters:vampire:vampire_template", kwargs={"pk": self.object.pk})
Step 4: Create Template Selection Template
html
{% extends "core/base.html" %}
{% block content %}
<div class="tg-card mb-4" data-gameline="vtm">
<div class="tg-card-header">
<h4 class="tg-card-title vtm_heading">Choose a Starting Template</h4>
</div>
<div class="tg-card-body">
<form method="post">
{% csrf_token %}
{% for template in available_templates %}
<div class="template-option" onclick="selectTemplate(this, {{ template.pk }})">
<h5>{{ template.name }}</h5>
<p>{{ template.description|truncatewords:30 }}</p>
</div>
{% endfor %}
<div class="template-option" onclick="selectTemplate(this, '')">
<h5>Build from Scratch</h5>
</div>
<input type="hidden" name="template" id="selected-template" value="">
<button type="submit" class="btn btn-primary mt-3">Continue</button>
</form>
</div>
</div>
{% endblock %}
Loading Templates
bash
# Load all templates
python populate_db/character_templates/__init__.py
# Load specific gameline
python populate_db/character_templates/vampire_templates.py
Template Application Logic
CharacterTemplate.apply_to_character(character):
- Resolves
"FK:Model:Name"→ actual objects - Sets attributes and abilities directly
- Creates BackgroundRating entries
- Sets power ratings (disciplines/spheres/gifts)
- Creates MeritFlawRating entries
- Links Language objects
- Creates Specialty entries
- Creates TemplateApplication record
- Increments times_used counter
Reference Implementation
Mage (MtAHuman) is fully integrated. Files:
characters/views/mage/mtahuman.py- Template selection viewcharacters/urls/mage/detail.py- Template and creation URLscharacters/templates/characters/mage/mtahuman/template_select.html
Didn't find tool you were looking for?