mirror of
https://github.com/Crocmagnon/charasheet.git
synced 2024-11-10 16:53:54 +01:00
Add recovery points
This commit is contained in:
parent
1f77eb98e1
commit
3a8d7c832f
7 changed files with 160 additions and 87 deletions
|
@ -106,7 +106,7 @@ class CharacterAdmin(admin.ModelAdmin):
|
||||||
"Combat",
|
"Combat",
|
||||||
{"fields": ["initiative", "attack_melee", "attack_range", "attack_magic"]},
|
{"fields": ["initiative", "attack_melee", "attack_range", "attack_magic"]},
|
||||||
),
|
),
|
||||||
("Vitalité", {"fields": ["health_max", "health_remaining"]}),
|
("Vitalité", {"fields": [("health_max", "health_remaining")]}),
|
||||||
("Défense", {"fields": ["armor", "shield", "defense_misc", "defense"]}),
|
("Défense", {"fields": ["armor", "shield", "defense_misc", "defense"]}),
|
||||||
(
|
(
|
||||||
"Armes & équipement",
|
"Armes & équipement",
|
||||||
|
@ -120,8 +120,12 @@ class CharacterAdmin(admin.ModelAdmin):
|
||||||
),
|
),
|
||||||
("Race", {"fields": ["racial_capability"]}),
|
("Race", {"fields": ["racial_capability"]}),
|
||||||
("Capacités", {"fields": ["capabilities"]}),
|
("Capacités", {"fields": ["capabilities"]}),
|
||||||
("Chance", {"fields": ["luck_points_max", "luck_points_remaining"]}),
|
("Chance", {"fields": [("luck_points_max", "luck_points_remaining")]}),
|
||||||
("Mana", {"fields": ["mana_max", "mana_remaining"]}),
|
("Mana", {"fields": [("mana_max", "mana_remaining")]}),
|
||||||
|
(
|
||||||
|
"Récupération",
|
||||||
|
{"fields": [("recovery_points_max", "recovery_points_remaining")]},
|
||||||
|
),
|
||||||
("Notes", {"fields": ["notes"]}),
|
("Notes", {"fields": ["notes"]}),
|
||||||
]
|
]
|
||||||
readonly_fields = [
|
readonly_fields = [
|
||||||
|
@ -137,7 +141,7 @@ class CharacterAdmin(admin.ModelAdmin):
|
||||||
"attack_magic",
|
"attack_magic",
|
||||||
"defense",
|
"defense",
|
||||||
"mana_max",
|
"mana_max",
|
||||||
"mana_remaining",
|
"recovery_points_max",
|
||||||
]
|
]
|
||||||
filter_horizontal = [
|
filter_horizontal = [
|
||||||
"capabilities",
|
"capabilities",
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 4.1.2 on 2022-10-30 20:49
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("character", "0014_remove_character_mana_consumed_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="character",
|
||||||
|
name="recovery_points_remaining",
|
||||||
|
field=models.PositiveSmallIntegerField(
|
||||||
|
default=5, verbose_name="points de récupération restants"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1 +1 @@
|
||||||
0014_remove_character_mana_consumed_and_more
|
0015_character_recovery_points_remaining
|
||||||
|
|
|
@ -138,6 +138,10 @@ class Character(models.Model):
|
||||||
money_pa = models.PositiveSmallIntegerField(default=0, verbose_name="PA")
|
money_pa = models.PositiveSmallIntegerField(default=0, verbose_name="PA")
|
||||||
money_pc = models.PositiveSmallIntegerField(default=0, verbose_name="PC")
|
money_pc = models.PositiveSmallIntegerField(default=0, verbose_name="PC")
|
||||||
|
|
||||||
|
recovery_points_remaining = models.PositiveSmallIntegerField(
|
||||||
|
default=5, verbose_name="points de récupération restants"
|
||||||
|
)
|
||||||
|
|
||||||
notes = models.TextField(blank=True, verbose_name="notes")
|
notes = models.TextField(blank=True, verbose_name="notes")
|
||||||
|
|
||||||
objects = CharacterManager()
|
objects = CharacterManager()
|
||||||
|
@ -227,6 +231,10 @@ class Character(models.Model):
|
||||||
def imc(self) -> float:
|
def imc(self) -> float:
|
||||||
return self.weight / (self.height_m**2)
|
return self.weight / (self.height_m**2)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def recovery_points_max(self) -> int:
|
||||||
|
return 5
|
||||||
|
|
||||||
def get_capabilities_by_path(self) -> dict[Path, list[Capability]]:
|
def get_capabilities_by_path(self) -> dict[Path, list[Capability]]:
|
||||||
capabilities_by_path = collections.defaultdict(list)
|
capabilities_by_path = collections.defaultdict(list)
|
||||||
for capability in self.capabilities.all():
|
for capability in self.capabilities.all():
|
||||||
|
|
|
@ -185,91 +185,114 @@
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<td id="mana-remaining">{{ character.mana_remaining }}</td>
|
<td id="mana-remaining">{{ character.mana_remaining }}</td>
|
||||||
</tr>
|
<tr>
|
||||||
</tbody>
|
<th scope="row">PR max</th>
|
||||||
</table>
|
<td>{{ character.recovery_points_max }}</td>
|
||||||
</div>
|
</tr>
|
||||||
</div>
|
<tr>
|
||||||
<div class="row">
|
<th scope="row">
|
||||||
<div class="col-md-4 mb-3">
|
PR restants
|
||||||
<div class="card">
|
<div class="btn-group btn-group-sm" role="group">
|
||||||
<h5 class="card-header">{{ character.racial_capability.name }}</h5>
|
<button
|
||||||
<div class="card-body">
|
hx-get="{% url "character:recovery_points_change" pk=character.pk %}?value=-1"
|
||||||
<p class="card-text">{{ character.racial_capability.description|capfirst }}</p>
|
hx-target="#recovery-points-remaining"
|
||||||
</div>
|
hx-swap="innerHTML"
|
||||||
|
type="button"
|
||||||
|
class="btn btn-danger">-</button>
|
||||||
|
<button
|
||||||
|
hx-get="{% url "character:recovery_points_change" pk=character.pk %}?value=1"
|
||||||
|
hx-target="#recovery-points-remaining"
|
||||||
|
hx-swap="innerHTML"
|
||||||
|
type="button"
|
||||||
|
class="btn btn-success">+</button>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
<td id="recovery-points-remaining">{{ character.recovery_points_remaining }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-8">
|
<div class="row">
|
||||||
<table class="table table-hover table-sm">
|
<div class="col-md-4 mb-3">
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col">Arme</th>
|
|
||||||
<th scope="col">Attaque</th>
|
|
||||||
<th scope="col">DM</th>
|
|
||||||
<th scope="col">Spécial</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="table-group-divider">
|
|
||||||
{% for weapon in character.weapons.all %}
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{{ weapon.name }}</th>
|
|
||||||
<td>1D20 +</td>
|
|
||||||
<td>{{ weapon.damage }}</td>
|
|
||||||
<td>{{ weapon.special }}</td>
|
|
||||||
</tr>
|
|
||||||
{% empty %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="4">Aucune arme</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<div class="card">
|
|
||||||
<h5 class="card-header">Équipement</h5>
|
|
||||||
<div class="card-body" id="equipment">
|
|
||||||
{% include "character/equipment_display.html" %}
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
{{ character.money_pp }} pp,
|
|
||||||
{{ character.money_po }} po,
|
|
||||||
{{ character.money_pa }} pa,
|
|
||||||
{{ character.money_pc }} pc
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<h4 class="mt-3">Voies & Capacités</h4>
|
|
||||||
<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">
|
||||||
<h5 class="card-header">{{ path.display_name }}</h5>
|
<h5 class="card-header">{{ character.racial_capability.name }}</h5>
|
||||||
{% if path.notes %}
|
<div class="card-body">
|
||||||
<div class="card-body text-bg-light">{{ path.notes }}</div>
|
<p class="card-text">{{ character.racial_capability.description|capfirst }}</p>
|
||||||
{% endif %}
|
</div>
|
||||||
<ul class="list-group list-group-flush">
|
|
||||||
{% 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>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
<div class="col-md-8">
|
||||||
</div>
|
<table class="table table-hover table-sm">
|
||||||
<h4 class="mt-3">Notes</h4>
|
<thead>
|
||||||
<div class="row" id="notes">
|
<tr>
|
||||||
{% include "character/notes_display.html" %}
|
<th scope="col">Arme</th>
|
||||||
</div>
|
<th scope="col">Attaque</th>
|
||||||
|
<th scope="col">DM</th>
|
||||||
|
<th scope="col">Spécial</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="table-group-divider">
|
||||||
|
{% for weapon in character.weapons.all %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{{ weapon.name }}</th>
|
||||||
|
<td>1D20 +</td>
|
||||||
|
<td>{{ weapon.damage }}</td>
|
||||||
|
<td>{{ weapon.special }}</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="4">Aucune arme</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">Équipement</h5>
|
||||||
|
<div class="card-body" id="equipment">
|
||||||
|
{% include "character/equipment_display.html" %}
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
{{ character.money_pp }} pp,
|
||||||
|
{{ character.money_po }} po,
|
||||||
|
{{ character.money_pa }} pa,
|
||||||
|
{{ character.money_pc }} pc
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h4 class="mt-3">Voies & Capacités</h4>
|
||||||
|
<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">
|
||||||
|
<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">
|
||||||
|
{% 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>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<h4 class="mt-3">Notes</h4>
|
||||||
|
<div class="row" id="notes">
|
||||||
|
{% include "character/notes_display.html" %}
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -7,6 +7,11 @@ urlpatterns = [
|
||||||
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>/health_change", views.character_health_change, name="health_change"),
|
||||||
path("<int:pk>/mana_change", views.character_mana_change, name="mana_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>/notes_change", views.character_notes_change, name="notes_change"),
|
path("<int:pk>/notes_change", views.character_notes_change, name="notes_change"),
|
||||||
path(
|
path(
|
||||||
"<int:pk>/equipment_change",
|
"<int:pk>/equipment_change",
|
||||||
|
|
|
@ -40,6 +40,19 @@ def character_mana_change(request: WSGIRequest, pk: int) -> HttpResponse:
|
||||||
return HttpResponse(value)
|
return HttpResponse(value)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def character_recovery_points_change(request: WSGIRequest, pk: int) -> HttpResponse:
|
||||||
|
character = get_object_or_404(
|
||||||
|
Character.objects.only("recovery_points_remaining"), pk=pk
|
||||||
|
)
|
||||||
|
value = get_updated_value(
|
||||||
|
request, character.recovery_points_remaining, character.recovery_points_max
|
||||||
|
)
|
||||||
|
character.recovery_points_remaining = value
|
||||||
|
character.save(update_fields=["recovery_points_remaining"])
|
||||||
|
return HttpResponse(value)
|
||||||
|
|
||||||
|
|
||||||
def get_updated_value(
|
def get_updated_value(
|
||||||
request: WSGIRequest, remaining_value: int, max_value: int
|
request: WSGIRequest, remaining_value: int, max_value: int
|
||||||
) -> int:
|
) -> int:
|
||||||
|
|
Loading…
Reference in a new issue