diff --git a/src/module/helpers.js b/src/module/helpers.js
index d84b497..6b861f2 100644
--- a/src/module/helpers.js
+++ b/src/module/helpers.js
@@ -1,27 +1,25 @@
/* global warpgate */
-import { moduleHelpers } from './globals.js'
+import { moduleHelpers } from './globals.js';
-export async function requestFearRollFromTokens (tokens, options = {}) {
+export async function requestFearRollFromTokens(tokens, options = {}) {
// tokens: list of tokens to request the roll from
// options:
// title: tile for the roll dialog. Will have "- {{ token name }}" appended
// flavour: flavor text for the roll card. Defaults to title
// fear: value of the fear modifier. Defaults to 0. Positive number.
- const requestingUser = game.user
- const title = options?.title || `${requestingUser.name} requests a Fear check`
- const flavour = options?.flavour || options?.flavor || title
- const fear = options.fear || 0
+ const requestingUser = game.user;
+ const title = options?.title || `${requestingUser.name} requests a Fear check`;
+ const flavour = options?.flavour || options?.flavor || title;
+ const fear = options.fear || 0;
const rollOpts = {
title,
flavour,
- mods: [
- { label: 'Fear Penalty', value: Math.abs(fear) * -1, ignore: false }
- ]
- }
- return requestRollFromTokens(tokens, 'attribute', 'spirit', rollOpts)
+ mods: [{ label: 'Fear Penalty', value: Math.abs(fear) * -1, ignore: false }],
+ };
+ return requestRollFromTokens(tokens, 'attribute', 'spirit', rollOpts);
}
-export async function requestRollFromTokens (tokens, rollType, rollDesc, options = {}) {
+export async function requestRollFromTokens(tokens, rollType, rollDesc, options = {}) {
// tokens: list of tokens to request a roll from
// rollType: 'attribute' or 'skill
// rollDesc: name of attribute or skill
@@ -33,91 +31,98 @@ export async function requestRollFromTokens (tokens, rollType, rollDesc, options
// mods: list of modifiers {label: "", value: 0, ignore: false}
// modCallback: callback function that takes a token and returns a list of
// modifiers in the same format as modifiers, above
- const requestingUser = game.user
- const title = options?.title || `${requestingUser.name} requests a ${rollDesc} roll`
- const flavour = options?.flavour || options?.flavor || title
- const targetNumber = options?.targetNumber || 4
- const promises = []
+ const requestingUser = game.user;
+ const title = options?.title || `${requestingUser.name} requests a ${rollDesc} roll`;
+ const flavour = options?.flavour || options?.flavor || title;
+ const targetNumber = options?.targetNumber || 4;
+ const promises = [];
for (const token of tokens) {
- const owner = warpgate.util.firstOwner(token.document)
+ const owner = warpgate.util.firstOwner(token.document);
const rollOpts = {
title: `${title} - ${token.name}`,
targetNumber,
- flavour
- }
- const additionalMods = []
+ flavour,
+ };
+ const additionalMods = [];
if ('mods' in options) {
for (const mod of options.mods) {
- additionalMods.push(mod)
+ additionalMods.push(mod);
}
}
if ('modCallback' in options) {
- const tokenMods = await options.modCallback(token)
+ const tokenMods = await options.modCallback(token);
for (const tm of tokenMods) {
- additionalMods.push(tm)
+ additionalMods.push(tm);
}
}
if (additionalMods.length > 0) {
- rollOpts.additionalMods = additionalMods
+ rollOpts.additionalMods = additionalMods;
}
- promises.push(moduleHelpers.socket.executeAsUser(requestTokenRoll, owner.id,
- token.scene.id, token.id, rollType, rollDesc, rollOpts))
+ promises.push(
+ moduleHelpers.socket.executeAsUser(
+ requestTokenRoll,
+ owner.id,
+ token.scene.id,
+ token.id,
+ rollType,
+ rollDesc,
+ rollOpts,
+ ),
+ );
}
- const results = (await Promise.allSettled(promises)).map(r => r.value)
- const contentExtra = targetNumber === 4 ? '' : ` vs TN: ${targetNumber}`
+ const results = (await Promise.allSettled(promises)).map((r) => r.value);
+ const contentExtra = targetNumber === 4 ? '' : ` vs TN: ${targetNumber}`;
const messageData = {
flavor: flavour,
speaker: { alias: 'Requested Roll Results' },
whisper: [...ChatMessage.getWhisperRecipients('GM'), requestingUser],
content: `
Results of ${rollDesc[0].toUpperCase()}${rollDesc.slice(1)} roll${contentExtra}:
| Token | Roll | Result |
`,
- rolls: []
- }
+ rolls: [],
+ };
for (const result of results) {
- const token = game.scenes.get(result.sceneId).tokens.get(result.tokenId)
- const roll = (
+ const token = game.scenes.get(result.sceneId).tokens.get(result.tokenId);
+ const roll =
result.result instanceof CONFIG.Dice.SwadeRoll
? result.result
- : CONFIG.Dice[result.result.class].fromData(result.result)
- )
- roll.targetNumber = targetNumber
- let textResult = ''
+ : CONFIG.Dice[result.result.class].fromData(result.result);
+ roll.targetNumber = targetNumber;
+ let textResult = '';
if (roll.successes === -1) {
- textResult = 'CRITICAL FAILURE'
+ textResult = 'CRITICAL FAILURE';
} else if (roll.successes === 0) {
- textResult = 'failed'
+ textResult = 'failed';
} else if (roll.successes === 1) {
- textResult = 'success'
+ textResult = 'success';
} else {
- textResult = `success and ${roll.successes - 1} raise${roll.successes > 2 ? 's' : ''}`
+ textResult = `success and ${roll.successes - 1} raise${roll.successes > 2 ? 's' : ''}`;
}
- messageData.content += ('' +
+ messageData.content +=
+ '
' +
`| ${token.name} | ` +
`${roll ? roll.total : 'Canceled'} | ` +
`${textResult} | ` +
- '
')
+ '';
if (roll) {
- messageData.rolls.unshift(roll)
+ messageData.rolls.unshift(roll);
}
}
- messageData.content += '
'
- ChatMessage.create(messageData, {})
- return results
+ messageData.content += '';
+ ChatMessage.create(messageData, {});
+ return results;
}
-export async function requestTokenRoll (
- sceneId, tokenId, rollType, rollDesc, options
-) {
- const scene = game.scenes.get(sceneId)
- const token = scene.tokens.get(tokenId)
- let rollFunc = 'rollAttribute'
- let rollId = rollDesc.toLowerCase()
+export async function requestTokenRoll(sceneId, tokenId, rollType, rollDesc, options) {
+ const scene = game.scenes.get(sceneId);
+ const token = scene.tokens.get(tokenId);
+ let rollFunc = 'rollAttribute';
+ let rollId = rollDesc.toLowerCase();
if (rollType === 'skill') {
- rollFunc = 'rollSkill'
- rollId = token.actor.items.filter(i => i.type === 'skill').find(i => (
- i.system.swid === rollDesc.toLowerCase() ||
- i.name.toLowerCase() === rollDesc.toLowerCase()))?.id
+ rollFunc = 'rollSkill';
+ rollId = token.actor.items
+ .filter((i) => i.type === 'skill')
+ .find((i) => i.system.swid === rollDesc.toLowerCase() || i.name.toLowerCase() === rollDesc.toLowerCase())?.id;
}
- const result = await token.actor[rollFunc](rollId, options)
- return { sceneId, tokenId, result }
+ const result = await token.actor[rollFunc](rollId, options);
+ return { sceneId, tokenId, result };
}
diff --git a/src/module/powers/banish.js b/src/module/powers/banish.js
index 6477899..6b7688f 100644
--- a/src/module/powers/banish.js
+++ b/src/module/powers/banish.js
@@ -1,4 +1,6 @@
import { PowerEffect } from './basePowers.js';
+import { requestRollFromTokens } from '../helpers.js';
+import { getPowerModifiers } from '../rollHelpers.js';
export class BanishEffect extends PowerEffect {
get name() {
@@ -31,6 +33,15 @@ export class BanishEffect extends PowerEffect {
get modifiers() {
const mods = super.modifiers;
+ mods.push({
+ type: 'number',
+ default: 4,
+ name: 'Opposed Target Number',
+ id: 'tn',
+ epic: false,
+ effect: false,
+ value: 0,
+ });
mods.push({
type: 'select',
default: 'none',
@@ -49,6 +60,17 @@ export class BanishEffect extends PowerEffect {
return mods;
}
+ async sideEffects() {
+ await super.sideEffects();
+ const rollOpts = {
+ title: 'Spirit roll to resist banishment',
+ flavor: 'Roll Spirit to resist banishment!',
+ modCallback: getPowerModifiers,
+ targetNumber: this.data.tn,
+ };
+ await requestRollFromTokens(this.targets, 'ability', 'spirit', rollOpts);
+ }
+
get description() {
return (
super.description +
diff --git a/src/module/rollHelpers.js b/src/module/rollHelpers.js
index 6afcfc4..4b82c90 100644
--- a/src/module/rollHelpers.js
+++ b/src/module/rollHelpers.js
@@ -1,60 +1,64 @@
-import { log } from './globals.js'
+import { log } from './globals.js';
-export async function preTraitRollModifiers (actor, trait, roll, modifiers, options) {
- const targets = Array.from(game.user.targets)
- const token = game.canvas.tokens.controlled.length > 0 ? game.canvas.tokens.controlled[0] : null
- if (targets.some(target => target.actor.system.status.isVulnerable)) {
- modifiers.push({ label: 'Target is Vulnerable', value: '+2', ignore: false })
+export async function preTraitRollModifiers(actor, trait, roll, modifiers, options) {
+ const targets = Array.from(game.user.targets);
+ const token = game.canvas.tokens.controlled.length > 0 ? game.canvas.tokens.controlled[0] : null;
+ if (targets.some((target) => target.actor.system.status.isVulnerable)) {
+ modifiers.push({ label: 'Target is Vulnerable', value: '+2', ignore: false });
}
- if (targets.some(
- target => target.actor.effects.filter(
- e => !e.disabled && e.name.toLowerCase().includes('deflection')).length > 0)
+ if (
+ targets.some(
+ (target) =>
+ target.actor.effects.filter((e) => !e.disabled && e.name.toLowerCase().includes('deflection')).length > 0,
+ )
) {
- modifiers.push({ label: 'Target has Deflection', value: '-2', ignore: false })
+ modifiers.push({ label: 'Target has Deflection', value: '-2', ignore: false });
}
- if (targets.some(
- target => target.actor.effects.filter(
- e => !e.disabled && e.name.toLowerCase().includes('glow')).length > 0)
+ if (
+ targets.some(
+ (target) => target.actor.effects.filter((e) => !e.disabled && e.name.toLowerCase().includes('glow')).length > 0,
+ )
) {
modifiers.push({
label: 'Glowing target (negate 1 point of illumination penalty)',
value: '+1',
- ignore: true
- })
+ ignore: true,
+ });
}
- if (targets.some(
- target => target.actor.effects.filter(
- e => !e.disabled && e.name.toLowerCase().includes('shroud')).length > 0)
+ if (
+ targets.some(
+ (target) => target.actor.effects.filter((e) => !e.disabled && e.name.toLowerCase().includes('shroud')).length > 0,
+ )
) {
modifiers.push({
label: 'Shrouded target',
value: '-1',
- ignore: false
- })
+ ignore: false,
+ });
}
if (targets.length === 1 && token) {
- const target = targets[0]
- _addArcaneModifiers(target, modifiers)
- _addRangeModifiers(token, target, options, modifiers)
- const scaleMod = calcScaleMod(token, target)
+ const target = targets[0];
+ _addArcaneModifiers(target, modifiers);
+ _addRangeModifiers(token, target, options, modifiers);
+ const scaleMod = calcScaleMod(token, target);
if (scaleMod !== 0) {
- modifiers.push({ label: 'Scale', value: scaleMod, ignore: false })
+ modifiers.push({ label: 'Scale', value: scaleMod, ignore: false });
}
- if (target.actor.items.find(e => e.type === 'edge' && e.system.swid === 'dodge')) {
- modifiers.push({ label: 'Dodge', value: -2, ignore: true })
+ if (target.actor.items.find((e) => e.type === 'edge' && e.system.swid === 'dodge')) {
+ modifiers.push({ label: 'Dodge', value: -2, ignore: true });
}
if (trait?.type === 'skill' && trait?.system?.swid === 'fighting') {
- const gangUpBonus = calcGangup(token, target)
+ const gangUpBonus = calcGangup(token, target);
if (gangUpBonus > 0) {
- modifiers.push({ label: 'Gang Up', value: gangUpBonus, ignore: false })
+ modifiers.push({ label: 'Gang Up', value: gangUpBonus, ignore: false });
}
}
}
}
-export async function preDamageRollModifiers (actor, item, roll, modifiers, options) {
- const targets = Array.from(game.user.targets)
- const token = game.canvas.tokens.controlled.length > 0 ? game.canvas.tokens.controlled[0] : null
+export async function preDamageRollModifiers(actor, item, roll, modifiers, options) {
+ const targets = Array.from(game.user.targets);
+ const token = game.canvas.tokens.controlled.length > 0 ? game.canvas.tokens.controlled[0] : null;
// log('ACTOR', actor)
// log('TOKEN', token)
// log('ITEM', item)
@@ -63,148 +67,150 @@ export async function preDamageRollModifiers (actor, item, roll, modifiers, opti
// log('OPTIONS', options)
// log('TARGET', targets)
if (targets.length === 1 && token) {
- const target = targets[0]
- _addArcaneModifiers(target, modifiers)
+ const target = targets[0];
+ _addArcaneModifiers(target, modifiers);
const weaknesses = target.actor.items.filter(
- i => i.type === 'ability' && i.system.swid.toLowerCase().includes('environmental-weakness'))
+ (i) => i.type === 'ability' && i.system.swid.toLowerCase().includes('environmental-weakness'),
+ );
if (weaknesses.length > 0) {
- modifiers.push(...weaknesses.map(i => { return { label: i.name, value: '+4', ignore: true } }))
+ modifiers.push(
+ ...weaknesses.map((i) => {
+ return { label: i.name, value: '+4', ignore: true };
+ }),
+ );
}
const resistances = target.actor.items.filter(
- i => i.type === 'ability' && i.system.swid.toLowerCase().includes('environmental-resistance'))
+ (i) => i.type === 'ability' && i.system.swid.toLowerCase().includes('environmental-resistance'),
+ );
if (resistances.length > 0) {
- modifiers.push(...resistances.map(i => { return { label: i.name, value: '-4', ignore: true } }))
+ modifiers.push(
+ ...resistances.map((i) => {
+ return { label: i.name, value: '-4', ignore: true };
+ }),
+ );
}
if (_findItem(token.actor, 'ability', 'pack-tactics')) {
- const gangupBonus = calcGangup(token, target)
+ const gangupBonus = calcGangup(token, target);
if (gangupBonus > 0) {
- modifiers.push({ label: 'Gang Up (Pack Tactics)', value: gangupBonus, ignore: false })
+ modifiers.push({ label: 'Gang Up (Pack Tactics)', value: gangupBonus, ignore: false });
}
}
}
}
-function _addRangeModifiers (token, target, options, modifiers) {
+export async function getPowerModifiers(token) {
+ const modifiers = [];
+ _addArcaneModifiers(token, modifiers);
+ return modifiers;
+}
+
+function _addRangeModifiers(token, target, options, modifiers) {
if (options?.item?.type !== 'weapon' || !options?.item?.system?.range.includes('/')) {
- return
+ return;
}
- const ranges = options.item.system.range.split('/').map(x => parseInt(x))
- const distance = getDistance(token, target)
- const rollmods = CONFIG.SWADE.prototypeRollGroups.find(g => g.name === 'Range').modifiers
- log('ITEM RANGES:', ranges)
+ const ranges = options.item.system.range.split('/').map((x) => parseInt(x));
+ const distance = getDistance(token, target);
+ const rollmods = CONFIG.SWADE.prototypeRollGroups.find((g) => g.name === 'Range').modifiers;
+ log('ITEM RANGES:', ranges);
if (distance <= ranges[0]) {
// nothing here
} else if (ranges.length >= 2 && distance <= ranges[1]) {
- modifiers.push(rollmods[0])
+ modifiers.push(rollmods[0]);
} else if (ranges.length >= 3 && distance <= ranges[2]) {
- modifiers.push(rollmods[1])
+ modifiers.push(rollmods[1]);
} else {
- modifiers.push(rollmods[2]) // extreme range
+ modifiers.push(rollmods[2]); // extreme range
}
}
-function _addArcaneModifiers (target, modifiers) {
+function _addArcaneModifiers(target, modifiers) {
if (_findItem(target.actor, 'edge', 'improved-arcane-resistance')) {
- modifiers.push({ label: 'Arcane Resistance', value: '-4', ignore: true })
+ modifiers.push({ label: 'Arcane Resistance', value: '-4', ignore: true });
} else if (_findItem(target.actor, 'edge', 'arcane-resistance')) {
- modifiers.push({ label: 'Arcane Resistance', value: '-2', ignore: true })
+ modifiers.push({ label: 'Arcane Resistance', value: '-2', ignore: true });
}
- const effect = target.actor.effects.find(
- e => !e.disabled && e.name.toLowerCase().includes('arcane protection'))
+ const effect = target.actor.effects.find((e) => !e.disabled && e.name.toLowerCase().includes('arcane protection'));
if (effect) {
- const effectName = effect.name.toLowerCase()
- const effectMod = (
- -2 +
- (effectName.includes('major') ? -2 : 0) +
- (effectName.includes('greater') ? -2 : 0)
- )
- modifiers.push({ label: 'Target Arcane Protection', value: effectMod, ignore: true })
+ const effectName = effect.name.toLowerCase();
+ const effectMod = -2 + (effectName.includes('major') ? -2 : 0) + (effectName.includes('greater') ? -2 : 0);
+ modifiers.push({ label: 'Target Arcane Protection', value: effectMod, ignore: true });
}
}
-function getScaleDistanceMod (token) {
- const scale = token.actor.system.stats.scale
- return (scale > 0 ? (scale / 2) : 0)
+function getScaleDistanceMod(token) {
+ const scale = token.actor.system.stats.scale;
+ return scale > 0 ? scale / 2 : 0;
}
-function getDistance (origin, target) {
- const ray = new Ray(origin, target)
- const originScale = getScaleDistanceMod(origin)
- const targetScale = getScaleDistanceMod(target)
- const flatDistance = game.canvas.grid.measureDistances(
- [{ ray }], { gridSpaces: true })[0]
- const elevation = Math.abs(origin.document.elevation - target.document.elevation)
- const distance = Math.sqrt(elevation * elevation + flatDistance * flatDistance)
- return distance - (originScale + targetScale)
+function getDistance(origin, target) {
+ const ray = new Ray(origin, target);
+ const originScale = getScaleDistanceMod(origin);
+ const targetScale = getScaleDistanceMod(target);
+ const flatDistance = game.canvas.grid.measureDistances([{ ray }], { gridSpaces: true })[0];
+ const elevation = Math.abs(origin.document.elevation - target.document.elevation);
+ const distance = Math.sqrt(elevation * elevation + flatDistance * flatDistance);
+ return distance - (originScale + targetScale);
}
-function withinRange (origin, target, range) {
- const distance = getDistance(origin, target)
- return range >= distance
+function withinRange(origin, target, range) {
+ const distance = getDistance(origin, target);
+ return range >= distance;
}
-function _findItem (actor, type, swid) {
- return actor.items.find(i => i.type === type && i.system.swid === swid)
+function _findItem(actor, type, swid) {
+ return actor.items.find((i) => i.type === type && i.system.swid === swid);
}
-function calcScaleMod (attacker, target) {
- const attackerScale = attacker.actor.system.stats.scale
- const targetScale = target.actor.system.stats.scale
- const attackerHasSwat = !!_findItem(attacker.actor, 'ability', 'swat')
- let modifier = targetScale - attackerScale
+function calcScaleMod(attacker, target) {
+ const attackerScale = attacker.actor.system.stats.scale;
+ const targetScale = target.actor.system.stats.scale;
+ const attackerHasSwat = !!_findItem(attacker.actor, 'ability', 'swat');
+ let modifier = targetScale - attackerScale;
if (attackerHasSwat && modifier < 0) {
- modifier = Math.min(modifier + 4, 0)
+ modifier = Math.min(modifier + 4, 0);
}
- return modifier
+ return modifier;
}
-function calcGangup (attacker, target, debug) {
- debug = (typeof debug === 'undefined') ? false : debug
- const range = 1.2
- let modifier = 0
+function calcGangup(attacker, target, debug) {
+ debug = typeof debug === 'undefined' ? false : debug;
+ const range = 1.2;
+ let modifier = 0;
if (_findItem(target.actor, 'edge', 'improved-block')) {
- modifier = -2
+ modifier = -2;
} else if (_findItem(target.actor, 'edge', 'block')) {
- modifier = -1
+ modifier = -1;
}
- const attackerHasFormationFighter = !!(_findItem(attacker.actor, 'edge', 'formation-fighter'))
+ const attackerHasFormationFighter = !!_findItem(attacker.actor, 'edge', 'formation-fighter');
- const withinRangeOfToken = game.canvas.tokens.placeables.filter(t =>
- t.id !== attacker.id &&
- t.id !== target.id &&
- t.actor.system.status.isStunned === false &&
- t.visible &&
- withinRange(target, t, range) &&
- !(t.actor.effects.find(c => c.name === 'Incapacitated' || c.name === 'Defeated'))
- )
- const attackerAllies = withinRangeOfToken.filter(
- t => t.document.disposition === attacker.document.disposition)
+ const withinRangeOfToken = game.canvas.tokens.placeables.filter(
+ (t) =>
+ t.id !== attacker.id &&
+ t.id !== target.id &&
+ t.actor.system.status.isStunned === false &&
+ t.visible &&
+ withinRange(target, t, range) &&
+ !t.actor.effects.find((c) => c.name === 'Incapacitated' || c.name === 'Defeated'),
+ );
+ const attackerAllies = withinRangeOfToken.filter((t) => t.document.disposition === attacker.document.disposition);
const targetAllies = withinRangeOfToken.filter(
- t => t.document.disposition === target.document.disposition &&
- withinRange(attacker, t, range)
- )
- const attackersWithFormationFighter = attackerAllies.filter(
- t => !!_findItem(t.actor, 'edge', 'formation-fighter'))
- const attackerCount = attackerAllies.length
- const attackerFormationBonus = (
- (attackerCount > 0 && attackerHasFormationFighter ? 1 : 0) +
- attackersWithFormationFighter.length
- )
- const defenderCount = targetAllies.length
- const gangUp = Math.max(
- 0,
- Math.min(
- 4,
- attackerCount + attackerFormationBonus - defenderCount + modifier))
+ (t) => t.document.disposition === target.document.disposition && withinRange(attacker, t, range),
+ );
+ const attackersWithFormationFighter = attackerAllies.filter((t) => !!_findItem(t.actor, 'edge', 'formation-fighter'));
+ const attackerCount = attackerAllies.length;
+ const attackerFormationBonus =
+ (attackerCount > 0 && attackerHasFormationFighter ? 1 : 0) + attackersWithFormationFighter.length;
+ const defenderCount = targetAllies.length;
+ const gangUp = Math.max(0, Math.min(4, attackerCount + attackerFormationBonus - defenderCount + modifier));
if (debug) {
- log('GANG UP | Attacker:', attacker)
- log('GANG UP | Target:', target)
- log('GANG UP | Others within range:', withinRangeOfToken)
- log('GANG UP | Attacker Allies:', attackerCount)
- log('GANG UP | Attacker Formation Bonus:', attackerFormationBonus)
- log('GANG UP | Effective Defender Allies:', defenderCount)
- log('GANG UP | Target Block Modifier:', modifier)
- log('GANG UP | Total Bonus:', gangUp)
+ log('GANG UP | Attacker:', attacker);
+ log('GANG UP | Target:', target);
+ log('GANG UP | Others within range:', withinRangeOfToken);
+ log('GANG UP | Attacker Allies:', attackerCount);
+ log('GANG UP | Attacker Formation Bonus:', attackerFormationBonus);
+ log('GANG UP | Effective Defender Allies:', defenderCount);
+ log('GANG UP | Target Block Modifier:', modifier);
+ log('GANG UP | Total Bonus:', gangUp);
}
- return gangUp
+ return gangUp;
}
diff --git a/src/templates/powerDialog.html b/src/templates/powerDialog.html
index 85bf557..6a1a6eb 100644
--- a/src/templates/powerDialog.html
+++ b/src/templates/powerDialog.html
@@ -26,12 +26,20 @@
{{#if epic}}⭐ {{/if}}{{name}} ({{numberFormat value decimals=0 sign=true}})
{{/if}}
+ {{#if isText}}
+
+
+ {{/if}}
+ {{#if isNumber}}
+
+
+ {{/if}}
{{#if isSelect}}
{{/if}}
{{#if isRadio}}
- {{radioBoxes id choices checked=default}}
+ {{#if epic}}⭐ {{/if}}{{name}}: {{radioBoxes id choices checked=default}}
{{/if}}
{{/each}}