mirror of
https://github.com/Crocmagnon/charasheet.git
synced 2024-11-05 06:13:55 +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.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"
|
||||||
|
|
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">
|
<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 %}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -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})
|
||||||
|
|
Loading…
Reference in a new issue