When using combat abilities (like "smite"), the web frontend was calling GET /api/v1/abilities/{ability_id} to fetch ability details for display, but this endpoint didn't exist, causing a 404 error.
Additionally, after fixing that, the ability would execute but:
1. Modal onclick issue: The onclick="closeModal()" on ability buttons was removing the button from the DOM before HTMX could fire the request
2. Field name mismatch: The API returns mana_cost but the frontend expected mp_cost
3. Duplicate text in combat log: The web view was adding "You" as actor and damage separately, but the API message already contained both
4. Page not auto-refreshing: Various attempts to use HX-Trigger headers failed due to HTMX overwriting them
Fixes Made
1. Created /api/app/api/abilities.py - New abilities API endpoint with GET /api/v1/abilities and GET /api/v1/abilities/<ability_id>
2. Modified /api/app/__init__.py - Registered the new abilities blueprint
3. Modified /public_web/templates/game/partials/ability_modal.html - Changed onclick="closeModal()" to hx-on::before-request="closeModal()" so HTMX captures the request before modal closes
4. Modified /public_web/app/views/combat_views.py:
- Fixed mp_cost → mana_cost field name lookup
- Removed duplicate actor/damage from combat log entries (API message is self-contained)
- Added inline script to trigger page refresh after combat actions
5. Modified /public_web/templates/game/combat.html - Updated JavaScript for combat action handling (though final fix was server-side script injection)
62 lines
3.1 KiB
HTML
62 lines
3.1 KiB
HTML
{# Ability Selection Modal - Shows available abilities during combat #}
|
|
|
|
<div class="modal-overlay" onclick="if(event.target === this) closeModal()">
|
|
<div class="modal-content modal-content--md">
|
|
<div class="modal-header">
|
|
<h3 class="modal-title">Select Ability</h3>
|
|
<button class="modal-close" onclick="closeModal()" aria-label="Close modal">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
{% if abilities %}
|
|
<div class="ability-list">
|
|
{% for ability in abilities %}
|
|
<button class="ability-btn"
|
|
hx-post="{{ url_for('combat.combat_action', session_id=session_id) }}"
|
|
hx-vals='{"action_type": "ability", "ability_id": "{{ ability.id }}"}'
|
|
hx-target="#combat-log"
|
|
hx-swap="beforeend"
|
|
hx-disabled-elt="this"
|
|
hx-on::before-request="closeModal()"
|
|
{% if not ability.available %}disabled{% endif %}>
|
|
<span class="ability-icon">
|
|
{% if ability.damage_type == 'fire' %}🔥
|
|
{% elif ability.damage_type == 'ice' %}❄
|
|
{% elif ability.damage_type == 'lightning' %}⚡
|
|
{% elif ability.effect_type == 'heal' %}❤
|
|
{% elif ability.effect_type == 'buff' %}⬆
|
|
{% elif ability.effect_type == 'debuff' %}⬇
|
|
{% else %}✨
|
|
{% endif %}
|
|
</span>
|
|
<div class="ability-info">
|
|
<span class="ability-name">{{ ability.name }}</span>
|
|
<span class="ability-description">{{ ability.description|default('A powerful ability.') }}</span>
|
|
</div>
|
|
<div class="ability-meta">
|
|
{% if ability.mp_cost > 0 %}
|
|
<span class="ability-cost">{{ ability.mp_cost }} MP</span>
|
|
{% endif %}
|
|
{% if ability.cooldown > 0 %}
|
|
<span class="ability-cooldown ability-cooldown--active">{{ ability.cooldown }} turns CD</span>
|
|
{% elif ability.max_cooldown > 0 %}
|
|
<span class="ability-cooldown">{{ ability.max_cooldown }} turns CD</span>
|
|
{% endif %}
|
|
</div>
|
|
</button>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<div class="items-empty">
|
|
<p>No abilities available.</p>
|
|
<p style="font-size: var(--text-xs); margin-top: 0.5rem; color: var(--text-muted);">
|
|
Learn abilities by leveling up or finding skill tomes.
|
|
</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn btn--secondary" onclick="closeModal()">Cancel</button>
|
|
</div>
|
|
</div>
|
|
</div>
|