152 lines
4.6 KiB
HTML
152 lines
4.6 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Skill Trees - {{ character.name }} - Code of Conquest{% endblock %}
|
|
|
|
{% block extra_head %}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/skills.css') }}">
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
{% include "character/partials/skills_container.html" %}
|
|
|
|
{# Embed skill data as JSON for tooltips #}
|
|
<script>
|
|
// Skill data for tooltips (embedded from server)
|
|
const skillData = {
|
|
{% if player_class and player_class.skill_trees %}
|
|
{% for tree in player_class.skill_trees %}
|
|
{% for node in tree.nodes %}
|
|
"{{ node.skill_id }}": {
|
|
name: "{{ node.name }}",
|
|
description: "{{ node.description | replace('"', '\\"') | replace('\n', ' ') }}",
|
|
tier: {{ node.tier }},
|
|
prerequisites: {{ node.prerequisites | tojson }},
|
|
effects: {{ node.effects | tojson if node.effects else '{}' }}
|
|
}{% if not loop.last %},{% endif %}
|
|
{% endfor %}{% if not loop.last %},{% endif %}
|
|
{% endfor %}
|
|
{% endif %}
|
|
};
|
|
|
|
// Character's unlocked skills
|
|
const unlockedSkills = {{ character.unlocked_skills | tojson }};
|
|
|
|
// Tooltip element
|
|
const tooltip = document.getElementById('skill-tooltip');
|
|
|
|
/**
|
|
* Show tooltip for a skill node
|
|
*/
|
|
function showTooltip(event, skillId) {
|
|
const skill = skillData[skillId];
|
|
if (!skill) return;
|
|
|
|
// Build tooltip HTML
|
|
let html = `
|
|
<div class="tooltip-header">
|
|
<h3 class="tooltip-name">${skill.name}</h3>
|
|
<span class="tooltip-tier">Tier ${skill.tier}</span>
|
|
</div>
|
|
<p class="tooltip-description">${skill.description}</p>
|
|
`;
|
|
|
|
// Stat bonuses
|
|
if (skill.effects && skill.effects.stat_bonuses) {
|
|
const bonuses = skill.effects.stat_bonuses;
|
|
const bonusList = Object.entries(bonuses)
|
|
.map(([stat, value]) => `<li>+${value} ${formatStatName(stat)}</li>`)
|
|
.join('');
|
|
html += `
|
|
<div class="tooltip-section">
|
|
<div class="tooltip-section-title">Stat Bonuses</div>
|
|
<ul class="tooltip-bonuses">${bonusList}</ul>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Abilities unlocked
|
|
if (skill.effects && skill.effects.abilities) {
|
|
const abilities = skill.effects.abilities;
|
|
const abilityList = abilities.map(a => `<li>${formatAbilityName(a)}</li>`).join('');
|
|
html += `
|
|
<div class="tooltip-section">
|
|
<div class="tooltip-section-title">Unlocks Ability</div>
|
|
<ul class="tooltip-abilities">${abilityList}</ul>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Prerequisites
|
|
if (skill.prerequisites && skill.prerequisites.length > 0) {
|
|
const prereqNames = skill.prerequisites.map(p => {
|
|
const prereqSkill = skillData[p];
|
|
const met = unlockedSkills.includes(p);
|
|
return `<span style="color: ${met ? 'var(--accent-green)' : 'var(--accent-red-light)'}">${prereqSkill ? prereqSkill.name : p}</span>`;
|
|
}).join(', ');
|
|
html += `
|
|
<div class="tooltip-section">
|
|
<p class="tooltip-prerequisite"><strong>Requires:</strong> ${prereqNames}</p>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
tooltip.innerHTML = html;
|
|
|
|
// Position tooltip
|
|
const rect = event.target.closest('.skill-node').getBoundingClientRect();
|
|
const tooltipRect = tooltip.getBoundingClientRect();
|
|
|
|
let left = rect.right + 10;
|
|
let top = rect.top;
|
|
|
|
// Check if tooltip goes off right edge
|
|
if (left + 300 > window.innerWidth) {
|
|
left = rect.left - 310;
|
|
}
|
|
|
|
// Check if tooltip goes off bottom edge
|
|
if (top + tooltipRect.height > window.innerHeight) {
|
|
top = window.innerHeight - tooltipRect.height - 10;
|
|
}
|
|
|
|
tooltip.style.left = left + 'px';
|
|
tooltip.style.top = top + 'px';
|
|
tooltip.classList.add('visible');
|
|
}
|
|
|
|
/**
|
|
* Hide tooltip
|
|
*/
|
|
function hideTooltip() {
|
|
tooltip.classList.remove('visible');
|
|
}
|
|
|
|
/**
|
|
* Format stat name for display
|
|
*/
|
|
function formatStatName(stat) {
|
|
const names = {
|
|
strength: 'Strength',
|
|
dexterity: 'Dexterity',
|
|
constitution: 'Constitution',
|
|
intelligence: 'Intelligence',
|
|
wisdom: 'Wisdom',
|
|
charisma: 'Charisma',
|
|
luck: 'Luck',
|
|
defense: 'Defense',
|
|
resistance: 'Resistance',
|
|
mana_points: 'Mana',
|
|
hit_points: 'Hit Points'
|
|
};
|
|
return names[stat] || stat.charAt(0).toUpperCase() + stat.slice(1).replace(/_/g, ' ');
|
|
}
|
|
|
|
/**
|
|
* Format ability name for display
|
|
*/
|
|
function formatAbilityName(ability) {
|
|
return ability.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
|
|
}
|
|
</script>
|
|
{% endblock %}
|