356 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			356 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
{% extends "base.html" %}
 | 
						|
{% set active_page = "npcparty" %}
 | 
						|
 | 
						|
{% block title %}NPC Party Generation{% endblock %}
 | 
						|
{% block content %}
 | 
						|
<div class="uk-flex uk-flex-center uk-margin-bottom uk-margin-top">
 | 
						|
    <h1 class="uk-text-center"><strong>Adventurer Conqueror King</strong>NPC Party Generator</h1>
 | 
						|
</div>
 | 
						|
<div class="uk-flex uk-flex-bottom uk-flex-center uk-margin-large-bottom">
 | 
						|
    <div>
 | 
						|
        <label for="base_level">Base level of party to generate: </label>
 | 
						|
        <input type="number" name="base_level" id="base_level" class="uk-input" value="{{ base_level if base_level else 1 }}" min="0" max="14">
 | 
						|
    </div>
 | 
						|
    <div class="uk-margin-left">
 | 
						|
        <button class="uk-button uk-button-primary" onclick="generateParty();">Generate</button>
 | 
						|
    </div>
 | 
						|
</div>
 | 
						|
 | 
						|
<hr class="uk-divider-icon">
 | 
						|
 | 
						|
{% if party %}
 | 
						|
<div class="uk-flex uk-flex-between uk-margin-large-top">
 | 
						|
    <h3 class="uk-display-inline-block">NPC Party of Size {{ party | length }} </h3>
 | 
						|
    <div class="uk-text-right uk-display-inline-block">
 | 
						|
        <a class="uk-button uk-button-small uk-button-secondary uk-border-rounded" onclick="showExportModal();">Roll20 Export</a>
 | 
						|
    </div>
 | 
						|
</div>
 | 
						|
 | 
						|
<div class="uk-grid-medium uk-grid-match uk-flex-center" uk-grid>
 | 
						|
    {% for npc in party %}
 | 
						|
    <div class="acks-npc-card">
 | 
						|
        <div class="uk-card uk-card-body uk-card-default uk-box-shadow-hover-large">
 | 
						|
            <h4 class="uk-card-title uk-margin-small-top">{{ npc.name }}</h4>
 | 
						|
            <div class="uk-card-badge uk-label uk-label-primary">{{ npc.guild.name }}</div>
 | 
						|
            <div class="uk-flex uk-flex-around uk-text-center uk-margin-bottom">
 | 
						|
                <div>
 | 
						|
                    <div class="uk-text-bold">Level</div>
 | 
						|
                    <div>{{ npc.level }}</div>
 | 
						|
                </div>
 | 
						|
                <div>
 | 
						|
                    <div class="uk-text-bold">HP</div>
 | 
						|
                    <div>{{ npc.hp }}</div>
 | 
						|
                </div>
 | 
						|
                <div>
 | 
						|
                    <div class="uk-text-bold">AC</div>
 | 
						|
                    <div>{{ npc.armour.ac_mod }}</div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
            <div class="uk-flex uk-flex-around stat-block">
 | 
						|
                <div>
 | 
						|
                    <div title="{{ npc.str_mod }}">{{ npc.str }}</div>
 | 
						|
                    <div title="{{ npc.str_mod }}">Str</div>
 | 
						|
                </div>
 | 
						|
                <div>
 | 
						|
                    <div title="{{ npc.int_mod }}">{{ npc.int }}</div>
 | 
						|
                    <div title="{{ npc.int_mod }}">Int</div>
 | 
						|
                </div>
 | 
						|
                <div>
 | 
						|
                    <div title="{{ npc.wis_mod }}">{{ npc.wis }}</div>
 | 
						|
                    <div title="{{ npc.wis_mod }}">Wis</div>
 | 
						|
                </div>
 | 
						|
                <div>
 | 
						|
                    <div title="{{ npc.dex_mod }}">{{ npc.dex }}</div>
 | 
						|
                    <div title="{{ npc.dex_mod }}">Dex</div>
 | 
						|
                </div>
 | 
						|
                <div>
 | 
						|
                    <div title="{{ npc.con_mod }}">{{ npc.con }}</div>
 | 
						|
                    <div title="{{ npc.con_mod }}">Con</div>
 | 
						|
                </div>
 | 
						|
                <div>
 | 
						|
                    <div title="{{ npc.chr_mod }}">{{ npc.chr }}</div>
 | 
						|
                    <div title="{{ npc.chr_mod }}">Chr</div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
            <hr class="uk-divider-small uk-text-center">
 | 
						|
            <div class="uk-flex uk-flex-around uk-text-center uk-margin-bottom save-block uk-margin-top">
 | 
						|
                <div>
 | 
						|
                    <div title="Petrification & Paralysis">{{ npc.save_pp }}</div>
 | 
						|
                    <div title="Petrification & Paralysis">P & P</div>
 | 
						|
                </div>
 | 
						|
                <div>
 | 
						|
                    <div title="Poison & Death">{{ npc.save_pd }}</div>
 | 
						|
                    <div title="Poison & Death">P & D</div>
 | 
						|
                </div>
 | 
						|
                <div>
 | 
						|
                    <div title="Blast & Breath">{{ npc.save_bb }}</div>
 | 
						|
                    <div title="Blast & Breath">B & B</div>
 | 
						|
                </div>
 | 
						|
                <div>
 | 
						|
                    <div title="Staffs & Wands">{{ npc.save_sw }}</div>
 | 
						|
                    <div title="Staffs & Wands">S & W</div>
 | 
						|
                </div>
 | 
						|
                <div>
 | 
						|
                    <div title="Spells">{{ npc.save_sp }}</div>
 | 
						|
                    <div title="Spells">Spells</div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
            <ul uk-tab>
 | 
						|
                <li class="uk-active"><a href="">Equipment</a></li>
 | 
						|
                <li {% if not npc.is_divine_spellcaster and not npc.is_arcane_spellcaster %}class="uk-disabled"{% endif %}><a href="">Spells</a></li>
 | 
						|
            </ul>
 | 
						|
            <ul class="uk-switcher uk-margin">
 | 
						|
                <li>
 | 
						|
                    <table class="uk-table uk-table-hover uk-table-small item-table">
 | 
						|
                        <thead>
 | 
						|
                            <tr> <th>Name</th><th>Worth</th><th>Thr</th><th>Dmg</th> </tr>
 | 
						|
                        </thead>
 | 
						|
                        <tbody>
 | 
						|
                            <tr>
 | 
						|
                                <td>{{ npc.melee.name }}</td>
 | 
						|
                                <td>{{ npc.melee.gp_value }}gp</td>
 | 
						|
                                <td>{{ npc.attack_throw }}</td>
 | 
						|
                                <td>{{ npc.melee.damage_die }}</td>
 | 
						|
                            </tr>
 | 
						|
                            {% if npc.ranged %}
 | 
						|
                            <tr>
 | 
						|
                                <td>{{ npc.ranged.name }}</td>
 | 
						|
                                <td>{{ npc.ranged.gp_value }}gp</td>
 | 
						|
                                <td>{{ npc.attack_throw }}</td>
 | 
						|
                                <td>{{ npc.ranged.damage_die }}</td>
 | 
						|
                            </tr>
 | 
						|
                            {% endif %}
 | 
						|
                            <tr>
 | 
						|
                                <td>{{ npc.armour.name }}</td>
 | 
						|
                                <td>{{ npc.armour.gp_value }}gp</td>
 | 
						|
                                <td></td>
 | 
						|
                                <td></td>
 | 
						|
                            </tr>
 | 
						|
                        </tbody>
 | 
						|
                    </table>
 | 
						|
                </li>
 | 
						|
                <li>
 | 
						|
                    <table class="uk-table uk-table-hover uk-table-small spell-table">
 | 
						|
                        <thead>
 | 
						|
                            <tr> <th>Name</th><th>Range</th><th>Duration</th><th>Level</th> </tr>
 | 
						|
                        </thead>
 | 
						|
                        <tbody>
 | 
						|
                            {% for level in npc.spell_list() %}
 | 
						|
                                {% for spell in npc.spell_list()[level] %}
 | 
						|
                                    <tr>
 | 
						|
                                        <td data-spell-id="{{ spell.id }}" onclick="showSpellModal();">{{ spell.name }}</td>
 | 
						|
                                        <td>{{ spell.range }}</td>
 | 
						|
                                        <td>{{ spell.duration }}</td>
 | 
						|
                                        <td>{{ spell.level_for(npc) }}</td>
 | 
						|
                                    </tr>
 | 
						|
                                {% endfor %}
 | 
						|
                            {% endfor %}
 | 
						|
                        </tbody>
 | 
						|
                    </table>
 | 
						|
                </li>
 | 
						|
            </ul>
 | 
						|
        </div>
 | 
						|
    </div>
 | 
						|
    {% endfor %}
 | 
						|
</div>
 | 
						|
{% else %}
 | 
						|
<div class="uk-grid-medium uk-grid-match uk-flex-center" uk-grid>
 | 
						|
</div>
 | 
						|
{% endif %}
 | 
						|
 | 
						|
<div id="spell-modal" uk-modal>
 | 
						|
    <div class="uk-modal-dialog uk-margin-auto-vertical">
 | 
						|
        <button class="uk-modal-close-default" type="button" uk-close></button>
 | 
						|
        <div class="uk-modal-header">
 | 
						|
            <h2 class="uk-modal-title"><span id="spell-modal-title">{Spell Title}</h2>
 | 
						|
        </div>
 | 
						|
        <div class="uk-modal-body">
 | 
						|
            <ul>
 | 
						|
                <li>Range: <span id="spell-modal-range">{Spell Range}</span></li>
 | 
						|
                <li>Duration: <span id="spell-modal-duration">{Spell Duration}</span></li>
 | 
						|
                <li><span id="spell-modal-school">{Spell School}</span></li>
 | 
						|
            </ul>
 | 
						|
            <p id="spell-modal-desc">{Spell Description}</p>
 | 
						|
        </div>
 | 
						|
    </div>
 | 
						|
</div>
 | 
						|
 | 
						|
<div id="party-export-modal" uk-modal>
 | 
						|
    <div class="uk-modal-dialog uk-margin-auto-vertical">
 | 
						|
        <button class="uk-modal-close-default" type="button" uk-close></button>
 | 
						|
        <div class="uk-modal-header">
 | 
						|
            <h2 class="uk-modal-title">Roll20 Export</h2>
 | 
						|
        </div>
 | 
						|
        <div class="uk-modal-body">
 | 
						|
            <div class="uk-margin">
 | 
						|
                <h5>Characters to Export:</h5>
 | 
						|
                <div id="pe_selects" class="uk-grid-small uk-grid uk-child-width-auto">
 | 
						|
                {% if party %}
 | 
						|
                    {% for npc in party %}
 | 
						|
                    <label><input class="uk-checkbox" type="checkbox" name="ch{{ loop.index }}" onchange="prepareSelectiveExport();" checked> {{ npc.name }}</label>
 | 
						|
                    {% endfor %}
 | 
						|
                {% endif %}
 | 
						|
                </div>
 | 
						|
                <div class="uk-margin uk-align-right">
 | 
						|
                    <div class="uk-button-group">
 | 
						|
                        <button id="pe_none" class="uk-button uk-button-small uk-button-default" onclick="partyExportToggle();">None</button>
 | 
						|
                        <button id="pe_all" class="uk-button uk-button-small uk-button-secondary" onclick="partyExportToggle();">All</button>
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
            <textarea id="party-export-show" class="uk-textarea uk-text-small" rows="10"></textarea>
 | 
						|
            <textarea id="party-export-data" class="uk-textarea uk-hidden"></textarea>
 | 
						|
        </div>
 | 
						|
        <div class="uk-modal-footer uk-text-right">
 | 
						|
            <button class="uk-button uk-button-default uk-modal-close" type="button">Cancel</button>
 | 
						|
            <button class="uk-button uk-button-primary" type="button" onclick="exportParty();">Copy</button>
 | 
						|
        </div>
 | 
						|
    </div>
 | 
						|
</div>
 | 
						|
 | 
						|
<br>
 | 
						|
 | 
						|
<style>
 | 
						|
table.item-table, table.item-table th, table.spell-table, table.spell-table th {
 | 
						|
    font-size: 12px;
 | 
						|
}
 | 
						|
div.stat-block > div {
 | 
						|
    text-align: center;
 | 
						|
    padding: 3px;
 | 
						|
    width: 26px;
 | 
						|
}
 | 
						|
div.stat-block > div > div:first-child {
 | 
						|
    font-weight: bold;
 | 
						|
    color: green;
 | 
						|
}
 | 
						|
div.stat-block > div > div:last-child {
 | 
						|
    font-weight: bold;
 | 
						|
    font-size: 12px;
 | 
						|
    color: #888;
 | 
						|
}
 | 
						|
div.save-block > div > div:first-child {
 | 
						|
    font-weight: bold;
 | 
						|
    color: purple;
 | 
						|
}
 | 
						|
div.save-block > div > div:last-child {
 | 
						|
    font-weight: bold;
 | 
						|
    font-size: 12px;
 | 
						|
    color: #888;
 | 
						|
}
 | 
						|
div.acks-npc-card {
 | 
						|
    width: 400px;
 | 
						|
}
 | 
						|
h1 strong {
 | 
						|
    display: block;
 | 
						|
    font-size: 50%;
 | 
						|
    opacity: 0.65;
 | 
						|
}
 | 
						|
</style>
 | 
						|
<script type="text/javascript">
 | 
						|
    var party = [];
 | 
						|
 | 
						|
    function generateParty() {
 | 
						|
        let bl = document.querySelector('#base_level').value;
 | 
						|
        if(bl < 0) { bl = 0; }
 | 
						|
        if(bl > 14) { bl = 14; }
 | 
						|
        window.location = "/npc/party/" + bl.toString();
 | 
						|
    }
 | 
						|
 | 
						|
    function showSpellModal() {
 | 
						|
        spells = new Set();
 | 
						|
        {% if party %}
 | 
						|
            {% for npc in party %}
 | 
						|
                {% for level in npc.spell_list() %}
 | 
						|
                    {% for spell in npc.spell_list()[level] %}
 | 
						|
        spells.add({{ spell.roll20_format | tojson }});
 | 
						|
                    {% endfor %}
 | 
						|
                {% endfor %}
 | 
						|
            {% endfor %}
 | 
						|
        {% endif %}
 | 
						|
 | 
						|
        var modal_spell, spell_id = event.target.dataset.spellId;
 | 
						|
        for(var spell of spells) {
 | 
						|
            if(spell.id == spell_id) {
 | 
						|
                modal_spell = spell
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // Fill in spell details
 | 
						|
        document.querySelector('#spell-modal-title').innerText = modal_spell.name;
 | 
						|
        document.querySelector('#spell-modal-desc').innerText = atob(modal_spell.description);
 | 
						|
 | 
						|
        if(spell.range) {
 | 
						|
            document.querySelector('#spell-modal-range').innerText = modal_spell.range;
 | 
						|
        }
 | 
						|
 | 
						|
        if(spell.duration) {
 | 
						|
            document.querySelector('#spell-modal-duration').innerText = modal_spell.duration;
 | 
						|
        }
 | 
						|
 | 
						|
        var school = '';
 | 
						|
        if(modal_spell.is_arcane) {
 | 
						|
            school += 'Arcane ' + modal_spell.arcane + ' ';
 | 
						|
        }
 | 
						|
        if(modal_spell.is_divine) {
 | 
						|
            school += 'Divine ' + modal_spell.divine + ' ';
 | 
						|
        }
 | 
						|
        document.querySelector('#spell-modal-school').innerText = school;
 | 
						|
 | 
						|
        UIkit.modal(document.querySelector('#spell-modal')).show();
 | 
						|
    }
 | 
						|
 | 
						|
    function showExportModal() {
 | 
						|
        {% if party %}
 | 
						|
        {% for npc in party %}
 | 
						|
        party.push(JSON.parse('{{ npc.roll20_format | tojson }}'));
 | 
						|
        {% endfor %}
 | 
						|
        {% endif %}
 | 
						|
 | 
						|
        for(let cb of document.querySelectorAll('#pe_selects > label > input')) {
 | 
						|
            cb.checked = true;
 | 
						|
        }
 | 
						|
 | 
						|
        prepareSelectiveExport();
 | 
						|
        UIkit.modal(document.querySelector('#party-export-modal')).show();
 | 
						|
    }
 | 
						|
 | 
						|
    function prepareSelectiveExport() {
 | 
						|
        var selected_party = [];
 | 
						|
        var checkboxes = document.querySelectorAll('#pe_selects > label > input');
 | 
						|
        for(let [i, cb] of checkboxes.entries()) {
 | 
						|
            if(cb.checked) {
 | 
						|
                selected_party.push(party[i]);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        document.querySelector('#party-export-data').value = "!acksimport " + JSON.stringify(selected_party);
 | 
						|
        document.querySelector('#party-export-show').value = JSON.stringify(selected_party, undefined, 2);
 | 
						|
    }
 | 
						|
 | 
						|
    function exportParty() {
 | 
						|
        let party_data = document.querySelector('#party-export-data')
 | 
						|
        party_data.classList.remove('uk-hidden');
 | 
						|
 | 
						|
        party_data.select();
 | 
						|
        document.execCommand("copy");
 | 
						|
 | 
						|
        party_data.classList.add('uk-hidden');
 | 
						|
        UIkit.modal(document.querySelector('#party-export-modal')).hide();
 | 
						|
    }
 | 
						|
 | 
						|
    function partyExportToggle() {
 | 
						|
        var checkboxes = document.querySelectorAll('#pe_selects > label > input');
 | 
						|
        for(let cb of checkboxes) {
 | 
						|
            if(event.target.id === "pe_none") {
 | 
						|
                cb.checked = false;
 | 
						|
            }
 | 
						|
            if(event.target.id === "pe_all") {
 | 
						|
                cb.checked = true;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        prepareSelectiveExport();
 | 
						|
    }
 | 
						|
</script>
 | 
						|
{% endblock %}
 |