mirror of
https://github.com/Crocmagnon/charasheet.git
synced 2024-12-22 22:01:48 +01:00
Allow adding next capability in path
This commit is contained in:
parent
c08abc2685
commit
0287536ba8
8 changed files with 98 additions and 24 deletions
24
src/character/migrations/0025_alter_capability_path.py
Normal file
24
src/character/migrations/0025_alter_capability_path.py
Normal 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",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -1 +1 @@
|
|||
0024_alter_character_notes
|
||||
0025_alter_capability_path
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django_extensions.db.models import TimeStampedModel
|
||||
|
@ -56,10 +58,24 @@ class Path(DocumentedModel, UniquelyNamedModel, TimeStampedModel, models.Model):
|
|||
else:
|
||||
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):
|
||||
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(
|
||||
validators=[MinValueValidator(1), MaxValueValidator(5)], verbose_name="rang"
|
||||
|
|
9
src/character/templates/character/capability.html
Normal file
9
src/character/templates/character/capability.html
Normal 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>
|
|
@ -339,24 +339,26 @@
|
|||
<div class="row gy-3">
|
||||
{% for path, capabilities in character.get_capabilities_by_path.items %}
|
||||
<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>
|
||||
{% if path.notes %}
|
||||
<div class="card-body text-bg-light">{{ path.notes }}</div>
|
||||
{% endif %}
|
||||
<ul class="list-group list-group-flush">
|
||||
<ul class="list-group list-group-flush capabilities">
|
||||
{% for capability in capabilities %}
|
||||
<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>
|
||||
{% include "character/capability.html" %}
|
||||
{% endfor %}
|
||||
</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>
|
||||
{% endfor %}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django import template
|
||||
|
||||
from character.models import Character, Weapon
|
||||
from character.models import Character, Path, Weapon
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
@ -27,3 +27,8 @@ def weapon_modifier(character: Character, weapon: Weapon):
|
|||
return f"- {abs(value)}"
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
@register.filter
|
||||
def has_next_capability(path: Path, character: Character) -> bool:
|
||||
return path.has_next_capability(character)
|
||||
|
|
|
@ -7,33 +7,40 @@ urlpatterns = [
|
|||
path("", views.characters_list, name="list"),
|
||||
path("create/", views.character_create, name="create"),
|
||||
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(
|
||||
"<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,
|
||||
name="recovery_points_change",
|
||||
),
|
||||
path(
|
||||
"<int:pk>/luck_points_change",
|
||||
"<int:pk>/luck_points_change/",
|
||||
views.character_luck_points_change,
|
||||
name="luck_points_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>/notes_change/", views.character_notes_change, name="notes_change"),
|
||||
path("<int:pk>/get_defense/", views.character_get_defense, name="get_defense"),
|
||||
path(
|
||||
"<int:pk>/defense_misc_change",
|
||||
"<int:pk>/defense_misc_change/",
|
||||
views.character_defense_misc_change,
|
||||
name="defense_misc_change",
|
||||
),
|
||||
path(
|
||||
"<int:pk>/equipment_change",
|
||||
"<int:pk>/equipment_change/",
|
||||
views.character_equipment_change,
|
||||
name="equipment_change",
|
||||
),
|
||||
path(
|
||||
"<int:pk>/damage_reduction_change",
|
||||
"<int:pk>/damage_reduction_change/",
|
||||
views.character_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",
|
||||
),
|
||||
]
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.shortcuts import get_object_or_404, redirect, render
|
|||
from django_htmx.http import trigger_client_event
|
||||
|
||||
from character.forms import EquipmentForm
|
||||
from character.models import Character
|
||||
from character.models import Character, Path
|
||||
|
||||
|
||||
@login_required
|
||||
|
@ -167,3 +167,14 @@ def update_text_field(request, pk, field):
|
|||
setattr(character, field, request.POST.get(field))
|
||||
character.save(update_fields=[field])
|
||||
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})
|
||||
|
|
Loading…
Reference in a new issue