Allow adding next capability in path

This commit is contained in:
Gabriel Augendre 2022-10-31 22:32:14 +01:00
parent c08abc2685
commit 0287536ba8
8 changed files with 98 additions and 24 deletions

View file

@ -0,0 +1,24 @@
# Generated by Django 4.1.2 on 2022-10-31 21:09
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("character", "0024_alter_character_notes"),
]
operations = [
migrations.AlterField(
model_name="capability",
name="path",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="capabilities",
to="character.path",
verbose_name="voie",
),
),
]

View file

@ -1 +1 @@
0024_alter_character_notes 0025_alter_capability_path

View file

@ -1,3 +1,5 @@
from __future__ import annotations
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models from django.db import models
from django_extensions.db.models import TimeStampedModel from django_extensions.db.models import TimeStampedModel
@ -56,10 +58,24 @@ class Path(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Model):
else: else:
return None return None
def get_next_capability(self, character) -> Capability:
next_rank = character.capabilities.filter(path=self).count() + 1
return self.capabilities.get(rank=next_rank)
def has_next_capability(self, character) -> bool:
try:
self.get_next_capability(character)
return True
except Capability.DoesNotExist:
return False
class Capability(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Model): class Capability(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Model):
path = models.ForeignKey( path = models.ForeignKey(
"character.Path", on_delete=models.CASCADE, verbose_name="voie" "character.Path",
on_delete=models.CASCADE,
verbose_name="voie",
related_name="capabilities",
) )
rank = models.PositiveSmallIntegerField( rank = models.PositiveSmallIntegerField(
validators=[MinValueValidator(1), MaxValueValidator(5)], verbose_name="rang" validators=[MinValueValidator(1), MaxValueValidator(5)], verbose_name="rang"

View file

@ -0,0 +1,9 @@
<li class="list-group-item">
<strong>
{{ capability.rank }}.
{{ capability.name }}
{% if capability.spell %}<i class="fa-solid fa-hand-sparkles"></i>{% endif %}
{% if capability.limited %}<i class="fa-solid fa-handcuffs"></i>{% endif %}
</strong><br>
{{ capability.description }}
</li>

View file

@ -339,24 +339,26 @@
<div class="row gy-3"> <div class="row gy-3">
{% for path, capabilities in character.get_capabilities_by_path.items %} {% for path, capabilities in character.get_capabilities_by_path.items %}
<div class="col-xl-3 col-md-6"> <div class="col-xl-3 col-md-6">
<div class="card"> <div class="card" data-path-id="{{ path.pk }}">
<h5 class="card-header">{{ path.display_name }}</h5> <h5 class="card-header">{{ path.display_name }}</h5>
{% if path.notes %} {% if path.notes %}
<div class="card-body text-bg-light">{{ path.notes }}</div> <div class="card-body text-bg-light">{{ path.notes }}</div>
{% endif %} {% endif %}
<ul class="list-group list-group-flush"> <ul class="list-group list-group-flush capabilities">
{% for capability in capabilities %} {% for capability in capabilities %}
<li class="list-group-item"> {% include "character/capability.html" %}
<strong>
{{ capability.rank }}.
{{ capability.name }}
{% if capability.spell %}<i class="fa-solid fa-hand-sparkles"></i>{% endif %}
{% if capability.limited %}<i class="fa-solid fa-handcuffs"></i>{% endif %}
</strong><br>
{{ capability.description }}
</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% if path|has_next_capability:character %}
<div class="card-body">
<button hx-get="{% url "character:add_next_in_path" character_pk=character.pk path_pk=path.pk %}"
hx-target="[data-path-id='{{ path.pk }}'] .capabilities"
hx-swap="beforeend"
class="btn btn-primary">
Next
</button>
</div>
{% endif %}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}

View file

@ -1,6 +1,6 @@
from django import template from django import template
from character.models import Character, Weapon from character.models import Character, Path, Weapon
register = template.Library() register = template.Library()
@ -27,3 +27,8 @@ def weapon_modifier(character: Character, weapon: Weapon):
return f"- {abs(value)}" return f"- {abs(value)}"
else: else:
return "" return ""
@register.filter
def has_next_capability(path: Path, character: Character) -> bool:
return path.has_next_capability(character)

View file

@ -7,33 +7,40 @@ urlpatterns = [
path("", views.characters_list, name="list"), path("", views.characters_list, name="list"),
path("create/", views.character_create, name="create"), path("create/", views.character_create, name="create"),
path("<int:pk>/", views.character_view, name="view"), path("<int:pk>/", views.character_view, name="view"),
path("<int:pk>/health_change", views.character_health_change, name="health_change"),
path("<int:pk>/mana_change", views.character_mana_change, name="mana_change"),
path( path(
"<int:pk>/recovery_points_change", "<int:pk>/health_change/", views.character_health_change, name="health_change"
),
path("<int:pk>/mana_change/", views.character_mana_change, name="mana_change"),
path(
"<int:pk>/recovery_points_change/",
views.character_recovery_points_change, views.character_recovery_points_change,
name="recovery_points_change", name="recovery_points_change",
), ),
path( path(
"<int:pk>/luck_points_change", "<int:pk>/luck_points_change/",
views.character_luck_points_change, views.character_luck_points_change,
name="luck_points_change", name="luck_points_change",
), ),
path("<int:pk>/notes_change", views.character_notes_change, name="notes_change"), path("<int:pk>/notes_change/", views.character_notes_change, name="notes_change"),
path("<int:pk>/get_defense", views.character_get_defense, name="get_defense"), path("<int:pk>/get_defense/", views.character_get_defense, name="get_defense"),
path( path(
"<int:pk>/defense_misc_change", "<int:pk>/defense_misc_change/",
views.character_defense_misc_change, views.character_defense_misc_change,
name="defense_misc_change", name="defense_misc_change",
), ),
path( path(
"<int:pk>/equipment_change", "<int:pk>/equipment_change/",
views.character_equipment_change, views.character_equipment_change,
name="equipment_change", name="equipment_change",
), ),
path( path(
"<int:pk>/damage_reduction_change", "<int:pk>/damage_reduction_change/",
views.character_damage_reduction_change, views.character_damage_reduction_change,
name="damage_reduction_change", name="damage_reduction_change",
), ),
path(
"<int:character_pk>/add_next_in_path/<int:path_pk>/",
views.add_next_in_path,
name="add_next_in_path",
),
] ]

View file

@ -4,7 +4,7 @@ from django.shortcuts import get_object_or_404, redirect, render
from django_htmx.http import trigger_client_event from django_htmx.http import trigger_client_event
from character.forms import EquipmentForm from character.forms import EquipmentForm
from character.models import Character from character.models import Character, Path
@login_required @login_required
@ -167,3 +167,14 @@ def update_text_field(request, pk, field):
setattr(character, field, request.POST.get(field)) setattr(character, field, request.POST.get(field))
character.save(update_fields=[field]) character.save(update_fields=[field])
return render(request, f"character/{field}_display.html", context) return render(request, f"character/{field}_display.html", context)
@login_required
def add_next_in_path(request, character_pk: int, path_pk: int):
character = get_object_or_404(
Character.objects.filter(player=request.user), pk=character_pk
)
path = get_object_or_404(Path, pk=path_pk)
capability = path.get_next_capability(character)
character.capabilities.add(capability)
return render(request, "character/capability.html", {"capability": capability})