Files
2024-06-03 13:15:14 -04:00

809 lines
37 KiB
HTML

<div class="everything">
<div class="banner"><div class="space"></div><img class="mlprimLogo" src="https://sites.google.com/site/roleplayingismagichome/_/rsrc/1404003237260/0-0/RiM-Logo-Redesign.png" /></div>
<div class="tabsContainer">
<div class="tab">
<input id="sheet-mainRadio" type="radio" class="tabInput" name="tab" checked />
<label for="sheet-mainRadio">Main</label>
<div id="mainPanel" class="tabPanel">
<h2>General</h2>
<div class='column vLayout' style="width: 50%;">
<div class="field">
<label>Name:</label>
<input type="text" name="attr_name">
</div>
<div class="field">
<label>Race:</label>
<input type="text" name="attr_race">
</div>
<div class="field">
<label>Guiding Element:</label>
<select name="attr_guiding_elem">
<option value="def">Select</option>
<option value="generosity">Generosity</option>
<option value="honesty">Honesty</option>
<option value="kindness">Kindness</option>
<option value="laughter">Laughter</option>
<option value="loyalty">Loyalty</option>
<option value="magic">Magic</option>
</select>
</div>
<div class="field">
<label>Fatal Flaw:</label>
<input type="text" name="attr_flaw">
</div>
</div>
<div class="column vLayout">
<div class="field">
<label>XP Spent:</label>
<span class="readOnlyField" name="attr_xpSpent"></span>
</div>
<div class="field">
<label>Fortitude:</label>
<input type="number" name="attr_fortitude"><div class="fraction">/</div>
<span class="readOnlyField" name="attr_fortitude_max"></span>
Modifiers: <input type="number" name="attr_fortitudeOtherMods" value="0" />
</div>
<div class="field">
<label>Willpower:</label>
<input type="number" name="attr_willpower"><div class="fraction">/</div>
<span class="readOnlyField" name="attr_willpower_max"></span>
Modifiers: <input type="number" name="attr_willpowerOtherMods" value="0" />
</div>
<div class="field">
<label>Valor:</label>
<input type="number" name="attr_valor"><div class="fraction">/</div>
<span class="readOnlyField" name="attr_valor_max"></span>
Modifiers: <input type="number" name="attr_valorOtherMods" value="0" />
</div>
</div>
<h2>Attributes</h2>
<table width="100%">
<tr>
<td>
<div class="attrBox field">
<label>MIND</label>
<input type="number" name="attr_mind">
</div>
</td>
<td>
<div class="attrBox field">
<label>BODY</label>
<input type="number" name="attr_body">
</div>
</td>
<td>
<div class="attrBox field">
<label>HEART</label>
<input type="number" name="attr_heart">
</div>
</td>
</tr>
</table>
<h2>Description</h2>
<textarea rows="3" name="attr_description"></textarea>
</div>
</div>
<div class="tab">
<input id="skillsRadio" type="radio" class="tabInput" name="tab" />
<label for="skillsRadio">Skills</label>
<div id="skillsPanel" class="tabPanel scrollingY">
<input type='hidden' name='attr_skillsJSON' value="{}"/>
<h2>MIND Skills</h2>
<fieldset name="skillsMind" class="repeating_skillsMind">
<div>
Name: <input type="text" name="attr_skillM">
Skill Training: <div class="rankBox trained" title="Trained">
<input type="checkbox" name="attr_skillMT" value="1">
<div>T</div>
</div>
<div class="rankBox improved" title="Improved">
<input type="checkbox" name="attr_skillMI" value="1">
<div>I</div>
</div>
<div class="rankBox greater" title="Greater">
<input type="checkbox" name="attr_skillMG" value="1">
<div>G</div>
</div>
Modifier: <input class="skillMod" type="number" name="attr_skillMMisc" value="0" title="Misc. Modifier"/>
<button type="roll" value="!r @{skillM}"></button>
</div>
<div class="conditionalModifiers">
<span>Conditional Modifiers:</span>
<input type="text" name="attr_skillMconditionals">
</div>
</fieldset>
<h2>BODY Skills</h2>
<fieldset name="skillsBody" class="repeating_skillsBody">
<div>
Name: <input type="text" name="attr_skillB">
Skill Training: <div class="rankBox trained" title="Trained">
<input type="checkbox" name="attr_skillBT" value="1">
<div>T</div>
</div>
<div class="rankBox improved" title="Improved">
<input type="checkbox" name="attr_skillBI" value="1">
<div>I</div>
</div>
<div class="rankBox greater" title="Greater">
<input type="checkbox" name="attr_skillBG" value="1">
<div>G</div>
</div>
Modifier: <input class="skillMod" type="number" name="attr_skillBMisc" value="0" title="Misc. Modifier"/>
<button type="roll" value="!r @{skillB}"></button>
</div>
<div class="conditionalModifiers">
<span>Conditional Modifiers:</span>
<input type="text" name="attr_skillBconditionals">
</div>
</fieldset>
<h2>HEART Skills</h2>
<fieldset name="skillsHeart" class="repeating_skillsHeart">
<div>
Name: <input type="text" name="attr_skillH">
Skill Training: <div class="rankBox trained" title="Trained">
<input type="checkbox" name="attr_skillHT" value="1">
<div>T</div>
</div>
<div class="rankBox improved" title="Improved">
<input type="checkbox" name="attr_skillHI" value="1">
<div>I</div>
</div>
<div class="rankBox greater" title="Greater">
<input type="checkbox" name="attr_skillHG" value="1">
<div>G</div>
</div>
Modifier: <input class="skillMod" type="number" name="attr_skillHMisc" value="0" title="Misc. Modifier"/>
<button type="roll" value="!r @{skillH}"></button>
</div>
<div class="conditionalModifiers">
<span>Conditional Modifiers:</span>
<input type="text" name="attr_skillHconditionals">
</div>
</fieldset>
</div>
</div>
<div class="tab">
<input id="edgesRadio" type="radio" class="tabInput" name="tab" />
<label for="edgesRadio">Edges</label>
<div id="edgesPanel" class="tabPanel">
<p>
This section is for all edges other than Skill Training. Those go over in the Skills section.
</p>
<input type='hidden' name='attr_edgesJSON' value="{}" />
<fieldset name="edges" class="repeating_edges">
Name: <input type="text" name="attr_edgeName" style="width: 100px;"/>
Effect: <input type="text" name="attr_edgeEffect" />
Edge rank:
<div class="rankBox trained" title="Trained">
<input type="checkbox" name="attr_edgeT" value="1">
<div>T</div>
</div>
<div class="rankBox trained" title="Improved">
<input type="checkbox" name="attr_edgeI" value="1">
<div>I</div>
</div>
<div class="rankBox trained" title="Greater">
<input type="checkbox" name="attr_edgeG" value="1">
<div>G</div>
</div>
</fieldset>
</div>
</div>
<div class="tab">
<input id="magicRadio" type="radio" class="tabInput" name="tab" />
<label for="magicRadio">Magic</label>
<div id="magicPanel" class="tabPanel">
<fieldset name="spells" class="repeating_spells">
<div class="panel">
<div style="display: inline-block;">
<div class="rankBox" title="Prepared?">
<input type="checkbox" name="attr_spellPrepared"/>
<div>P</div>
</div>
</div>
<div style="display: inline-block; vertical-align: text-top; width: 90%;">
<h2>
<input type="text" name="attr_spellName" placeholder="Spell name"/>
Lv. <input type="number" name="attr_spellLevel" disabled="true"
value="(@{spellTarget} + @{spellRange} + @{spellDuration} + @{spellEffectsTotal} + @{spellSubjectsTotal})"/>
</h2>
<div class="spellBody">
Target: <select name="attr_spellTarget" style="width: 100px;">
<option value=1>Individual</option>
<option value=2>Group</option>
<option value=4>Area</option>
<option value=8>Mass</option>
</select>
Range: <select name="attr_spellRange" style="width: 100px;">
<option value=1>Contact</option>
<option value=2>Seen</option>
<option value=4>Known</option>
<option value=8>Unknown</option>
</select>
Duration: <select name="attr_spellDuration" style="width: 100px;">
<option value=1>Immediate</option>
<option value=2>Sustained</option>
<option value=4>Temporary</option>
<option value=8>Persistent</option>
</select> <br/>
<div style="display: inline-block;">
Effects:
</div>
<div style="display: inline-block; margin-bottom: 10px; vertical-align: text-top;">
<input type="hidden" name="attr_spellEffectsTotal" disabled="true"
value="(@{spellAnimate} + @{spellCombine} + @{spellDeceive} + @{spellDiminish} +
@{spellForge} + @{spellModify} + @{spellReveal} + @{spellSeparate})"/>
<table class="layoutTable">
<tr>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellAnimate" value="1"/>
<div>&nbsp;</div>
</div> Animate
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellCombine" value="1"/>
<div>&nbsp;</div>
</div> Combine
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellDeceive" value="1"/>
<div>&nbsp;</div>
</div> Deceive
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellDiminish" value="1"/>
<div>&nbsp;</div>
</div> Diminish
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellForge" value="1"/>
<div>&nbsp;</div>
</div> Forge
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellModify" value="1"/>
<div>&nbsp;</div>
</div> Modify
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellReveal" value="1"/>
<div>&nbsp;</div>
</div> Reveal
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellSeparate" value="1"/>
<div>&nbsp;</div>
</div> Separate
</td>
</tr>
</table>
</div> <br/>
<div style="display: inline-block;">
Subjects:
</div>
<div style="display: inline-block; margin-bottom: 10px; vertical-align: text-top;">
<input type="hidden" name="attr_spellSubjectsTotal" disabled="true"
value="(@{spellAir} + @{spellAnimal} + @{spellBody} + @{spellConstruct} + @{spellEarth} +
@{spellEnergy} + @{spellForce} + @{spellHeat} + @{spellLight} + @{spellMagic} +
@{spellMind} + @{spellPlant} + @{spellShadow} + @{spellSound} + @{spellSpace} +
@{spellTime} + @{spellWater} + @{spellWeather})"/>
<table class="layoutTable">
<tr>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellAir" value="1"/>
<div>&nbsp;</div>
</div> Air
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellAnimal" value="1"/>
<div>&nbsp;</div>
</div> Animal
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellBody" value="1"/>
<div>&nbsp;</div>
</div> Body
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellConstruct" value="1"/>
<div>&nbsp;</div>
</div> Construct
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellEarth" value="1"/>
<div>&nbsp;</div>
</div> Earth
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellEnergy" value="1"/>
<div>&nbsp;</div>
</div> Energy
</td>
</tr>
<tr>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellForce" value="1"/>
<div>&nbsp;</div>
</div> Force
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellHeat" value="1"/>
<div>&nbsp;</div>
</div> Heat
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellLight" value="1"/>
<div>&nbsp;</div>
</div> Light
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellMagic" value="1"/>
<div>&nbsp;</div>
</div> Magic
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellMind" value="1"/>
<div>&nbsp;</div>
</div> Mind
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellPlant" value="1"/>
<div>&nbsp;</div>
</div> Plant
</td>
</tr>
<tr>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellShadow" value="1"/>
<div>&nbsp;</div>
</div> Shadow
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellSound" value="1"/>
<div>&nbsp;</div>
</div> Sound
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellSpace" value="1"/>
<div>&nbsp;</div>
</div> Space
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellTime" value="1"/>
<div>&nbsp;</div>
</div> Time
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellWater" value="1"/>
<div>&nbsp;</div>
</div> Water
</td>
<td>
<div class="rankBox">
<input type="checkbox" name="attr_spellWeather" value="1"/>
<div>&nbsp;</div>
</div> Weather
</td>
</tr>
</table>
</div> <!-- End effects and subjects -->
<textarea name="attr_spellDescription" rows="3" placeholder="Spell description"></textarea>
</div> <!-- End spellBody -->
</div>
</div> <!-- End panel -->
</fieldset>
</div>
</div>
<div class="tab">
<input id="lootRadio" type="radio" class="tabInput" name="tab" />
<label for="lootRadio">Loot</label>
<div id="lootPanel" class="tabPanel">
<div class="field money">
<label>Bits</label>
<input type="number" name="attr_money">
</div>
<div class="field">
<label>Equipped</label>
<textarea rows="5" name="attr_equipped"></textarea>
</div>
<div class="field">
<label>Inventory</label>
<textarea rows="9" name="attr_inventory"></textarea>
</div>
</div>
</div>
<div class="tab">
<input id="notesRadio" type="radio" class="tabInput" name="tab" />
<label for="notesRadio">Notes</label>
<div id="notesPanel" class="tabPanel">
<textarea rows="20" name="attr_notes"></textarea>
</div>
</div>
</div>
</div>
<span name='attr_debug' style="display:none;"></span>
<script type="text/worker">
var Asem = function(initCount, cb) {
this.count = initCount;
this.cb = cb;
this.hasFired = false;
};
_.extend(Asem.prototype, {
signal: function() {
this.count--;
if(this.count <= 0 && !this.hasFired) {
this.hasFired = true;
this.cb();
}
},
wait: function() {
this.count++;
}
});
/**
* Gets the specified attributes and parses them as an integer or 0.
*/
function parseAttrs(attrs, cb) {
getAttrs(attrs, function(values) {
_.each(attrs, function(attr) {
values[attr] = parseInt(values[attr]) || 0;
});
cb(values);
});
}
function updateFortMax() {
parseAttrs(['body', 'heart', 'edgeVitality', 'edgeVitalityI', 'edgeVitalityG', 'fortitudeOtherMods', 'fortitudeMaxMods'], function(values) {
var fortMax = 10*values.body +
5*(values.heart + values.edgeVitality + values.edgeVitalityI + values.edgeVitalityG) +
values.fortitudeOtherMods;
setAttrs({
fortitude_max: fortMax
});
});
}
function updateWillMax() {
parseAttrs(['mind', 'heart', 'edgeDetermined', 'edgeDeterminedI', 'edgeDeterminedG', 'willpowerOtherMods'], function(values) {
var willMax = 10*values.mind +
5*(values.heart + values.edgeDetermined + values.edgeDeterminedI + values.edgeDeterminedG) +
values.willpowerOtherMods;
setAttrs({
willpower_max: willMax
});
});
}
function updateValorMax() {
parseAttrs(['heart', 'edgeNobleSoul', 'edgeNobleSoulI', 'edgeNobleSoulG', 'valorOtherMods'], function(values) {
var valorMax = values.heart + values.edgeNobleSoul + values.edgeNobleSoulI + values.edgeNobleSoulG +
values.valorOtherMods;
setAttrs({
valor_max: valorMax
});
});
}
function updateHealthGraphic() {
parseAttrs(['fortitude', 'fortitude_max', 'willpower', 'willpower_max'], function(values) {
if(values.fortitude_max === 0 || values.willpower_max === 0) {
setAttrs({
statusImage: 'healthy'
});
}
else {
var alpha = Math.min(values.fortitude/values.fortitude_max, values.willpower/values.willpower_max);
if(alpha > 0.5) {
setAttrs({
statusImage: 'healthy'
});
}
else if(alpha > 0.25) {
setAttrs({
statusImage: 'bloodied'
});
}
else if(alpha > 0) {
setAttrs({
statusImage: 'critical'
});
}
else {
setAttrs({
statusImage: 'sidelined'
});
}
}
});
}
function tallySkillXp(attr, id, callback) {
var prefix = 'repeating_skills'
if(attr === 'mind')
prefix += 'Mind_' + id + '_skillM';
if(attr === 'body')
prefix += 'Body_' + id + '_skillB';
if(attr === 'heart')
prefix += 'Heart_' + id + '_skillH';
getAttrs([prefix, prefix + 'T', prefix + 'I', prefix + 'G', prefix + 'Misc', prefix + 'conditionals'], function(values) {
var name = values[prefix];
var trained = parseInt(values[prefix + 'T']) || 0;
var improved = parseInt(values[prefix + 'I']) || 0;
var greater = parseInt(values[prefix + 'G']) || 0;
var misc = parseInt(values[prefix + 'Misc']) || 0;
var notes = values[prefix + 'conditionals'];
var json = {
id: id,
name: name,
trained: !!trained,
improved: !!improved,
greater: !!greater,
attr: attr,
misc: misc,
notes: notes
};
var xpSpent = 5*trained + 10*improved + 15*greater;
callback(xpSpent, json);
});
}
function debugObj(obj) {
setAttrs({
debug: JSON.stringify(obj)
});
};
function tallyEdgeXp(id, callback) {
var prefix = 'repeating_edges_' + id + '_edge';
getAttrs([prefix + 'Name', prefix + 'Effect', prefix + 'T', prefix + 'I', prefix + 'G'], function(values) {
var name = values[prefix + 'Name'];
var trained = parseInt(values[prefix + 'T']) || 0;
var improved = parseInt(values[prefix + 'I']) || 0;
var greater = parseInt(values[prefix + 'G']) || 0;
var effect = values[prefix + 'Effect'];
var json = {
id: id,
name: name,
trained: !!trained,
improved: !!improved,
greater: !!greater,
effect: effect
};
debugObj(json);
var xpSpent = 5*trained + 10*improved + 15*greater;
callback(xpSpent, json);
});
}
function updateXpSpent() {
var xpSpent = 0;
var skillsJSON = {};
var edgesJSON = {};
var asem = new Asem(1, function() {
setAttrs({
edgesJSON: JSON.stringify(edgesJSON),
skillsJSON: JSON.stringify(skillsJSON),
xpSpent: xpSpent
});
});
// Mind skill training
asem.wait();
getSectionIDs('repeating_skillsMind', function(ids) {
_.each(ids, function(id) {
asem.wait();
tallySkillXp('mind', id, function(xp, json) {
xpSpent += xp;
skillsJSON[json.name] = json;
asem.signal();
});
});
asem.signal();
});
// Body skill training
asem.wait();
getSectionIDs('repeating_skillsBody', function(ids) {
_.each(ids, function(id) {
asem.wait();
tallySkillXp('body', id, function(xp, json) {
xpSpent += xp;
skillsJSON[json.name] = json;
asem.signal();
});
})
asem.signal();
});
// Heart skill training
getSectionIDs('repeating_skillsHeart', function(ids) {
_.each(ids, function(id) {
asem.wait();
tallySkillXp('heart', id, function(xp, json) {
xpSpent += xp;
skillsJSON[json.name] = json;
asem.signal();
});
})
asem.signal();
});
asem.wait();
// Built-in Edges
asem.wait();
parseAttrs(['edgeDetermined', 'edgeDeterminedI', 'edgeDeterminedG',
'edgeVitality', 'edgeVitalityI', 'edgeVitalityG',
'edgeNobleSoul', 'edgeNobleSoulI', 'edgeNobleSoulG'], function(values) {
xpSpent += 5*values.edgeDetermined + 10*values.edgeDeterminedI + 15*values.edgeDeterminedG;
xpSpent += 5*values.edgeVitality + 10*values.edgeVitalityI + 15*values.edgeVitalityG;
xpSpent += 5*values.edgeNobleSoul + 10*values.edgeNobleSoulI + 15*values.edgeNobleSoulG;
asem.signal();
});
// Custom edges
asem.wait();
getSectionIDs('repeating_edges', function(ids) {
_.each(ids, function(id) {
asem.wait();
tallyEdgeXp(id, function(xp, json) {
xpSpent += xp;
edgesJSON[json.name] = json;
asem.signal();
});
});
asem.signal();
});
asem.signal();
}
on('change:body change:heart change:edgeVitality change:edgeVitalityI change:edgeVitalityG change:fortitudeOtherMods', function() {
updateFortMax();
});
on('change:mind change:heart change:edgeDetermined change:edgeDeterminedI change:edgeDeterminedG change:willpowerOtherMods', function() {
updateWillMax();
});
on('change:heart change:edgeNobleSoul change:edgeNobleSoulI change:edgeNobleSoulG change:valorOtherMods', function() {
updateValorMax();
});
on('change:repeating_skillsmind change:repeating_skillsbody change:repeating_skillsheart ' +
'change:edgeDetermined change:edgeDeterminedI change:edgeDeterminedG ' +
'change:edgeVitality change:edgeVitalityI change:edgeVitalityG ' +
'change:edgeNobleSoul change:edgeNobleSoulI change:edgeNobleSoulG ' +
'change:repeating_edges:edgeT change:repeating_edges:edgeI change:repeating_edges:edgeG', function() {
updateXpSpent();
});
on('sheet:opened', function() {
updateFortMax();
updateWillMax();
updateValorMax();
updateXpSpent();
});
</script>
<rolltemplate class="sheet-rolltemplate-skillcheck">
<table>
<thead>
<tr>
<th>
{{charName}} &#x21D2; {{skillName}}
</th>
</tr>
</thead>
<tbody>
<tr class="trainingLevel">
{{#untrained}}
<td class="untrained">Untrained</td>
{{/untrained}}
{{#trained}}
<td class="trained">Trained</td>
{{/trained}}
{{#improved}}
<td class="improved">Improved</td>
{{/improved}}
{{#greater}}
<td class="greater">Greater</td>
{{/greater}}
</tr>
<tr>
<td>Result: {{result}}</td>
</tr>
{{#notes}}
<tr class="rollNotes">
<td>
<div>Notes:</div>
<div>{{notes}}</div>
</td>
</tr>
{{/notes}}
</tbody>
</table>
</rolltemplate>