campaign update

This commit is contained in:
Eric Woodward 2024-07-01 16:58:03 -04:00
parent fe50c52a7f
commit b0e81bc80d
9 changed files with 307 additions and 59 deletions

View File

@ -12,14 +12,14 @@
<li class="dayName">Saedo</li>
<li class="firstDay">1</li>
<li class="currDay">2</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li class="currDay">9</li>
<li>10</li>
<li>11</li>
<li>12</li>

View File

@ -1,5 +1,5 @@
<div class="todayWrapper">
As of last session, it is **the night of Tudo, the 2nd day of Porma, in the 78th year since the Eradication of King Ranulf the Just and his court**.
As of last session, it is the **early afternoon of Trado, the 9th day of Porma, in the 78th year since the Eradication of King Ranulf the Just and his court**.
</div>

View File

@ -21,11 +21,13 @@ export default (() => {
document.documentElement.className.replace('no-js', 'js');
// Enable cached fonts ASAP
/*
if (!!Cookies.get('fonts_loaded')) {
document.documentElement.className += ' js-hasFontsLoaded';
}
*/
docReady(() => {
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
// Lazy-Load Media
if (typeof loadMedia === 'function') {

View File

@ -19,6 +19,46 @@ const getRandomValue = (max = 1, min = 1) =>
const vals = [...Array(count).keys()].map(() => getRandomValue(sides)),
total = vals.reduce((v, a) => a + v, 0);
return [total, ...vals];
},
getRandomValueFromArray = (array = []) => {
if (!array.length) return '';
const roll = getRandomValue(array.length);
return `${array[roll - 1]} (${roll})`;
},
elementBuilder = (tag) => {
const el = document.createElement(tag);
return {
// need to use `function` rather than `=>` to keep `this` intact
addEventListener: function (type, fn) {
el.addEventListener(type, fn);
return this;
},
appendChild: function (child) {
el.appendChild(child);
return this;
},
appendToId: function (targetId) {
const target = document.getElementById(targetId);
if (target) target.append(el);
return this;
},
getElement: function () {
return el;
},
prependToId: function (targetId) {
const target = document.getElementById(targetId);
if (target) target.prepend(el);
return this;
},
set: function (attr, val) {
el[attr] = val;
return this;
},
setInnerHTML: function (val) {
el.innerHTML = val;
return this;
},
};
};
// Die Roller script
@ -28,6 +68,7 @@ const addRollerForm = () => {
rollerOutput = document.getElementById('js-rollerOutput'),
isExpressionRE =
/(?:(?:^|[-+_*/])(?:\s*-?\d*d?\d+(\.\d+)?(?:[+-]\s*\d*d?\d+)?\s*))+$/i;
if (!rollerForm) return;
// double-click [x] to clear list
rollerForm.addEventListener('reset', (e) => {
@ -47,12 +88,6 @@ const addRollerForm = () => {
.map((roll) => {
const result = dice.roll(roll),
stringifiedResult = dice.stringify(result);
/*
console.log(
{ roll, result, stringifiedResult },
isExpressionRE.test(roll)
);
*/
return `${stringifiedResult.replaceAll(
'!!!mods listing not yet complete!!!',
''
@ -96,6 +131,8 @@ const RoomTypes = {
const roomForm = document.getElementById('js-roomForm'),
roomOutput = document.getElementById('js-roomOutput');
if (!roomForm) return;
roomForm?.addEventListener('submit', (e) => {
e.preventDefault();
@ -130,6 +167,9 @@ const shuffleContainer = (parentId) => {
addComplicationForm = () => {
const complicationForm = document.getElementById('js-complicationForm'),
formControls = document.createElement('div');
if (!complicationForm) return;
formControls.innerHTML = [
'<button id="js-btnSetDungeon">Dungeon</button>',
'<button id="js-btnSetWilderness">Wilderness</button>',
@ -185,6 +225,8 @@ const shuffleContainer = (parentId) => {
const complicationForm = document.getElementById(
'js-astralComplicationForm'
);
if (!complicationForm) return;
complicationForm?.addEventListener('submit', (e) => {
e.preventDefault();
shuffleContainer('js-astralComplicationList');
@ -247,19 +289,25 @@ const reactionButtonVal = [
// combine monster roll total + surprise + roll data
const monsterRollText = `<strong>${monsterTotal}${surpriseText}</strong><br /><em>[${monsterRolls}]</em>`;
outputTable.innerHTML = [
`<thead><th colspan="2">${
type === 'W' ? 'Wilderness' : 'Dungeon'
} Encounter<br />(3d${sides}): ${dayjs().format(
'YYYY-MM-DD HH:mm:ss'
)}</th></thead>`,
'<tbody>',
`<tr><th>Monster</th><td>${monsterRollText}</td></tr>`,
`<tr><th>Distance</th><td>${distanceText}</td></tr>`,
`<tr><th>Reaction</th><td>${reactionText}</td></tr>`,
'</tbody>',
].join('\n');
outputTable.innerHTML = `
<thead>
<th colspan="2">
${type === 'W' ? 'Wilderness' : 'Dungeon'} Encounter<br />
${dayjs().format('YYYY-MM-DD HH:mm:ss')}
</th>
</thead>
<tbody>
<tr>
<th>Monster</th><td>${monsterRollText}</td>
</tr>
<tr>
<th>Distance</th><td>${distanceText}</td>
</tr>
<tr>
<th>Reaction</th><td>${reactionText}</td>
</tr>
</tbody>
`;
outputTable.classList.add('encounterResultTable');
encounterOutput.prepend(outputTable);
@ -267,19 +315,24 @@ const reactionButtonVal = [
addEncounterRoller = () => {
const complicationForm = document.getElementById('js-encounterForm'),
formControls = document.createElement('div');
formControls.innerHTML = [
'<div class="encounterButtonsWrapper">',
'<div class="encounterButtonsDungeonWrapper"><em>Dungeon</em><br />',
'<button id="js-btnRollDungeonEncounter3d4">3d4</button>',
'<button id="js-btnRollDungeonEncounter3d6">3d6</button>',
'<button id="js-btnRollDungeonEncounter3d8">3d8</button>',
'</div>',
'<div class="encounterButtonsWildernessWrapper"><em>Wilderness</em><br />',
'<button id="js-btnRollWildernessEncounter3d4">3d4</button>',
'<button id="js-btnRollWildernessEncounter3d6">3d6</button>',
'<button id="js-btnRollWildernessEncounter3d8">3d8</button>',
'</div></div>',
].join('\n');
if (!complicationForm) return;
formControls.innerHTML = `
<div class="encounterButtonsWrapper">
<div class="encounterButtonsDungeonWrapper">
<em>Dungeon</em><br />
<button id="js-btnRollDungeonEncounter3d4">3d4</button>
<button id="js-btnRollDungeonEncounter3d6">3d6</button>
<button id="js-btnRollDungeonEncounter3d8">3d8</button>
</div>
<div class="encounterButtonsWildernessWrapper">
<em>Wilderness</em><br />
<button id="js-btnRollWildernessEncounter3d4">3d4</button>
<button id="js-btnRollWildernessEncounter3d6">3d6</button>
<button id="js-btnRollWildernessEncounter3d8">3d8</button>
</div>
</div>
`;
complicationForm?.appendChild(formControls);
@ -334,12 +387,145 @@ const reactionButtonVal = [
});
};
// Magic Item Concept Roller
// Based on http://recedingrules.blogspot.com/2010/03/spell-like-effect-spur.html
const modeOpts = ['Wielder', 'Touch', 'Distance', 'Area Effect'],
intentOpts = ['Attack', 'Defense', 'Utility', 'Transport', 2, 3],
rangeOpts = [10, 20, 30, 40, 50, 60, 70, 'Sight'],
durationOpts = [
'Instant',
'1 round',
'1d6 rounds',
'1 turn',
'1d6 turns',
'1 hour',
'1d6 hours',
'1 day',
'1d6 days',
'Permanent',
],
effectOpts = [
'Alter',
'Animate',
'Charm / Compel',
'Conjure',
'Delude',
'Dispel / Disappear',
'Distort',
'Divine',
'Evoke',
'Shield',
'Summon',
'Transmute',
],
mediumOpts = [
'Animal',
'Vegetable',
'Mineral',
'Metal',
'Fire',
'Earth',
'Water',
'Air',
'Law',
'Chaos',
'Shadow',
'Light',
'Sound',
'Dead',
'Infernal',
'Time',
'Space / Dimension',
'Human',
'Demihuman',
'Humanoid',
'Monster',
'Terrain',
],
getIntent = () => {
const roll = getRandomValue(intentOpts.length),
idx = roll - 1;
if (typeof intentOpts[idx] === 'number') {
const [total, ...rolls] = rollDice(4, intentOpts[idx]);
return `${rolls
.map((r) => `${intentOpts[r - 1]} (${r})`)
.join(' / ')}`;
}
return `${intentOpts[idx]} (${roll})`;
},
getRange = () => {
const roll = getRandomValue(rangeOpts.length),
idx = roll - 1;
if (typeof rangeOpts[idx] === 'number') {
const val = rangeOpts[idx];
return `${val}' / ${val * 2}' / ${val * 3}' (${roll})`;
}
return `${rangeOpts[idx]} (${roll})`;
},
getResultList = () => {
return `
Magic Item Results
<em>(${dayjs().format('YYYY-MM-DD HH:mm:ss')})</em>
<ul>
<li>
Mode:
<strong>${getRandomValueFromArray(modeOpts)}</strong>
</li>
<li>
Intent:
<strong>${getIntent()}</strong>
</li>
<li>
Range:
<strong>${getRange()}</strong>
</li>
<li>
Duration:
<strong>${getRandomValueFromArray(durationOpts)}</strong>
</li>
<li>
Effect:
<strong>${getRandomValueFromArray(effectOpts)}</strong>
</li>
<li>
Medium:
<strong>${getRandomValueFromArray(mediumOpts)}</strong>
</li>
</ul>
`;
},
addMagicItemConceptRoller = () => {
const magicItemConceptForm = document.getElementById(
'js-magicItemConcept'
);
if (!magicItemConceptForm) return;
magicItemConceptForm?.appendChild(
elementBuilder('input')
.set('type', 'submit')
.set('value', 'Roll!')
.getElement()
);
magicItemConceptForm?.addEventListener('submit', (e) => {
e.preventDefault();
elementBuilder('li')
.setInnerHTML(getResultList())
.prependToId('js-magicItemConcept-output');
});
};
export default (() => {
addRollerForm();
addRoomForm();
addComplicationForm();
addAstralComplicationForm();
addEncounterRoller();
addMagicItemConceptRoller();
})();
// @license-end

View File

@ -472,6 +472,21 @@ a.licenseLink:hover {
border-color: #e94e5c;
}
.magicItemConcept-controls {
align-items: center;
display: flex;
flex-direction: row;
}
.magicItemConcept-controls p {
margin: 0;
}
.magicItemConcept-output {
padding-left: 0;
}
.menu-icon {
display: block;
position: absolute;
@ -1219,10 +1234,6 @@ a.pageTitle-sublink {
box-shadow: rgba(0, 0, 0, 0.35) 0px 50px 36px 28px inset;
}
.zineIssue-wrapper .table-of-contents {
display: none;
}
/****************************************************************************
* JS Overrides

View File

@ -33,7 +33,7 @@ While in **Blacktyde Bay**, the party answers a job posting from local merchant
- Hired by merchant **Thoryio Barbarosa** to accompany him to **Isle of Dread**.
- Set sail on the **Prosperity**, captained by **Mararo Sorris**. _[Fendo, 11th of Trama]_
- 7 days at sea, storm wreck, washed ashore on Isle of Dread. _[Saedo, 18th of Trama]_
- Spent 3 days wandering around peninsula.
- Spent first 3 days wandering around peninsula.
- **Panitube**, met chief **Lufa**, traded some stuff for the services of **Daas**, a young male guide.
- **Burowao**, met chief **Belz**.
@ -58,28 +58,28 @@ While in **Blacktyde Bay**, the party answers a job posting from local merchant
- Beyond the Wall
- 1st day over wall: saw dragon over eastern bay. _[Fendo, 23rd of Trama]_
- 2nd day over wall: fought off some lizard men in the hills. _[Saedo, 24th of Trama]_
- 5th day overall (1st day over wall): saw dragon over eastern bay. _[Fendo, 23rd of Trama]_
- 6th day: fought off some lizard men in the hills. _[Saedo, 24th of Trama]_
- While sleeping that night, attacked by 13 skeletons.
- After attack, found blood symbol, Truplea realized it was a name: **Melfora**
- 3rd day was uneventful, camped near the lake. _[Undo, 25th of Trama]_
- 4th day was uneventful, got stuck in a swamp. _[Tudo, 26th of Trama]_
- 5th day in hills, felt a tremor, heard some shouting, saw a couple of humanoid figures in furry skins chasing (or being chased by)... something. _[Trado - 27th of Trama]_
- camped in hills
- 6th day, rested in cave, saw elephant come through near them. _[Pordo - 2th of Trama]_
- 7th day, parted from Bumo, found the dragon bone bridge, arrived as night fell. _[Fendo, 29th of Trama]_
- 7th day was uneventful, camped near the lake. _[Undo, 25th of Trama]_
- 8th day was uneventful, got stuck in a swamp. _[Tudo, 26th of Trama]_
- 9th day, while traveling through hills: felt a tremor, heard some shouting, saw a couple of humanoid figures in furry skins chasing (or being chased by) something. _[Trado - 27th of Trama]_
- Camped in hills overnight.
- 10th day: Rested in cave, saw elephant come through near them. _[Pordo - 2th of Trama]_
- 11th day: Parted from Bumo, found the dragon bone bridge, arrived as night fell. _[Fendo, 29th of Trama]_
- The Central Plateau
- 8th day, crossed the dragon bone bridge and moved across the central plateau, made it to the volcanic crater by nightfall. _[Saedo, 30th of Trama]_
- 12th day: Crossed the dragon bone bridge and moved across the central plateau, made it to the volcanic crater by nightfall. _[Saedo, 30th of Trama]_
- For dinner, the party used a powerful magic ring to "capture" an antelope.
- 9th day, climbed the volcanic crater. _[Undo, 1st of Porma]_
- 13th day: Climbed the volcanic crater. _[Undo, 1st of Porma]_
- Had some close calls thanks to some slippage and an earthquake, extra long day (12 hours up, 8 hours down)
- Arrived only to find Isling's puppies waiting on the other side.
- Inside the crater
- 10th day, slept late, went into nearby village of **Mantru**. _[Tudo, 2nd of Porma]_
- 14th day: Slept late, went into nearby village of **Mantru**. _[Tudo, 2nd of Porma]_
- Natives weren't very welcome, at first.
- Village had a notable lack of men.
- The party met:
@ -96,8 +96,57 @@ While in **Blacktyde Bay**, the party answers a job posting from local merchant
- His dying words were: "In the boiling earth, the dread masters lie, dreaming..."
- He also wore a shiny ring with an (as-yet-undeciphered) inscription on it.
- The fight was long and vicious, and left one of Isling's wolves dead.
- Following the assault (and 27's near-death experience), they investigated the mouth on the wall.
- Following the assault (and 27's near-death experience), they investigated the mouth on the wall and the surrounding rooms.
- Truplea determined it could shoot flame, but wasn't sure about a trigger or source.
- Toric found a trick sconce that opened a secret door to a cove behind the face statue (where Isling found the controls for the mouth).
- In the hidden area, they found another secret door (synchronized to be in the opposite position of the first secret door) which lead to a hallway.
- Further down the hallway, they found a room with a pedestal and a box.
- Opening the box revealed a magical statue carved from a huge black pearl, which turned Lo, Truplea, and Isling into "Servants of the Darkness"
- After a brief but brutal battle, the statue was broken, and everyone was restored to normal.
- Believing they set the old masters back, the party decided to retreat and return in a few weeks with a larger force.
- The group left the temple, closing all of the secret doors, and removing the trick sconce from the wall on their way out.
- They returned to the village of Mantru
- The natives were happy to see them, but confused, as no one has returned yet.
- They spoke to the chief, via Umlatta, who requested they take the villagers back to the peninsula.
- Also did a weird healing ritual which appeared to make the chief glow momentarily.
- The chief said something about the watchers giving one of them "the power of the pride"
- "The old masters will turn many, but the towns that remain true will help, as will others - the barbarians on the plain, the keepers of the webs, even the necromancer in the cave.... unless the green death has his way."
- Freed tribesmen started walking into camp a few hours later, kept arriving throughout the night.
- Trip Back to Peninsula
- 15th day: Traveling across Central Plateau _[Trado, 3rd of Porma]_
- They set out at dawn with most of the villagers, except for Umlatta (who stayed behind to send along the stragglers).
- They acquired stragglers every so often, taking them up to 54 (at last count)
- As they left via the collapsed entrance, they found tunnels in the crater wall.
- Isling spent time training Ae'gu (pronounced yay-gu), a young warrior from Mantru
- 16th day: Dragon bridge crossing _[Pordo, 4th of Porma]_
- As they crossed the dragon bridge, 27 nearly fell (and was saved by Lo) before a pteronadon attacked.
- Isling hit it with an arrow and it fled.
- That night, while stopped at river crossing, Lo heard howling nearby.
- 17th day _[Fendo, 5th of Porma]_
- Heard scuffle near start of day, but avoided it.
- About midday, some of the villagers got exhausted, so they took a rest.
- 6 more villagers have joined up over past few days (54 total).
- 18th day _[Saedo, 6th of Porma]_
- Saw a couple of pterodactyls flying overhead.
- Camped (and fished) along lake's edge.
- 19th day _[Undo, 7th of Porma]_
- Heard some boars back in the woods from the lake's edge.
- Isling sent wolf to investigate, ID'd by smell, but they had passed.
- 20th day: Mostly uneventful. _[Tudo, 8th of Porma]_
- That night, both Lo and Toric heard a weird "whooshing" sound come from above them during their watches.
- 21st day: Back to the wall _[Trado, 9th of Porma]_
- **Esun, Dead God and Ancient Green Dragon** arrived just as they were breaking camp
- He told the party about his part in overthrowing the old masters.
- He also told them about artifacts that they could use to fight the old masters in the "crypt of the first men", currently run by a necromancer.
- After threatening the party, they reluctantly agreed to come back the next day to go to the crypt.
- Arrived at wall around midday, allowed to pass through.
- Arrived at Tanaroa shortly after midday
- The party met with chief Koma, asked her to send messages to other villages about old masters.
- The village kinda freaked out over old masters.
- Chief Koma offers to call war council with other chiefs
- Party decided to return to meet Esun.
### Links

View File

@ -30,7 +30,7 @@ An adventurer with a special bond with one (or more) animal companions.
### Animal Companions
- To establish a connection, must make a peaceful approach towards a single animal.
- Referee rolls reaction roll: On an 8 or higher, the animal is bonded to the animist.
- Referee rolls reaction roll: On an 8 or higher, the animal is bonded to the beast walker.
- Companions may be wild or domestic.
- Companions may be magical or giant, at the referee's discretion.
- May have up to one animal companion per level.
@ -38,7 +38,7 @@ An adventurer with a special bond with one (or more) animal companions.
- If a companion is dismissed or dies, may establish connection with new animal.
- Companions follow everywhere.
- Companions can understand and execute basic commands.
- Companions will fight to the death to defend their animist.
- Companions will fight to the death to defend their beast walker.
- Companions do not check morale.
### Speak with Animals
@ -53,8 +53,8 @@ An adventurer with a special bond with one (or more) animal companions.
After 9th level, may construct a stronghold in the wilderness.
- Automatically befriends all creatures within 5 mile radius.
- They may perform simple tasks for animist (carry messages, warn about intruders, etc).
- In exchange, they expect to be protected from harm by animist.
- They may perform simple tasks for beast walker (carry messages, warn about intruders, etc).
- In exchange, they expect to be protected from harm by beast walker.
### Advancement

View File

@ -10,4 +10,4 @@ short_code: m10n
Silver-framed spectacles with mirrored lenses.
- While worn, wearer can see undead and ethereal beings within 30 feet, even when invisible or hidden.
- Once per day, the wearer may ask three questions of the spirit of a deceased being within 30', as per the [Speak with Dead](/spells/speak-with-dead.html) spell.
- Once per day, the wearer may ask three questions of the spirit of a deceased being within 30', as per the [Speak with Dead](/spells/speak-with-dead.html) spell, but with no limit on the maximum deceased time.

View File

@ -32,7 +32,7 @@ short_code: t1
<ul class="rollerOutput" id="js-rollerOutput"></ul>
<p class="rollerLink">Powered by <a href="https://github.com/lordnull/dice.js" target="_blank">Dice.js</a></p>
</details>
<details class="toolDetails" open>
<details class="toolDetails" open>
<summary>
<h3>Encounter Roller</h3>
</summary>