Compare commits

...
10 Commits
14 changed files with 586 additions and 12 deletions
@@ -0,0 +1,217 @@
---
Reputation: 1
Faction_Type:
Motto:
Ideology:
Symbol:
Colors:
Headquarters:
Territories:
-
Allies:
-
Rivals:
-
SMH_Acronym:
Intel:
Tags:
- faction
---
# Whitewater Civilians
*One-line role/description — e.g., “Elven High House controlling Yathirs docks.”*
---
## 🎨 Artwork
![[Whitewater Civilians.png]]
*Optional caption / artist credit*
---
## 🧭 Identity & Heraldry
- **Motto:** `= default(this.Motto, "—")`
- **Symbol:** `= default(this.Symbol, "—")`
- **Colors:** `= default(this.Colors, "—")`
- **Headquarters:** `= default(this.Headquarters, "—")`
- **Territories:** `= this.Territories`
---
## 📜 Ideology & Goals
- **Ideology / Alignment:** `= default(this.Ideology, "—")`
- **Primary Goals:**
-
- **Taboos / Anathema:**
-
---
## 🤝 Relationship with Party
- **Reputation:** `= this.Reputation`
---
## 🧑‍💼 Leadership & Structure
- **Leader(s):** [[NPC A]], [[NPC B]]
- **Structure:** (council, hierarchy, cells, chapters)
- **Key Offices:** (Intelligence, Logistics, Priory, Treasury, etc.)
---
## 🧰 Assets & Operations
- **Resources:** (coin, troops, mages, ships, safehouses, contacts)
- **Notable Holdings:**
- **Typical Ops / Tactics:**
---
## 🕊️ Diplomacy & Relations
- **Allies:** `= this.Allies`
- **Rivals:** `= this.Rivals`
- **Stance toward “SMH” (their wording):** `= default(this.SMH_Acronym, "—")`
---
## 🧠 Intelligence & Mentions
```button
name Add Intel
type command
action Templater: Insert Add Intel Entry to Faction
```
```dataviewjs
const THIS = dv.current();
const thisName = String(THIS.file.name);
const thisLC = thisName.toLowerCase();
const factions = dv.pages("#faction");
// mention detector (same logic as your table)
function mentionsThisFaction(entry) {
const sum = String(entry.summary ?? "");
if (sum.includes(`[[${thisName}]]`) || sum.includes(`[[${thisName}|`)) return true;
const src = entry.source;
const list = Array.isArray(src) ? src : (src ? [src] : []);
for (const s of list) {
if (typeof s === "string") {
if (s.includes(`[[${thisName}]]`) || s.includes(`[[${thisName}|`)) return true;
if (s.toLowerCase() === thisLC) return true;
} else if (s && typeof s === "object" && s.path) {
const base = s.path.split("/").pop().replace(/\.md$/i,"").toLowerCase();
if (base === thisLC) return true;
}
}
return false;
}
const own = (THIS.Intel ?? []).length;
let mentions = 0;
for (const p of factions.where(p => p.file.name !== thisName)) {
for (const it of (p.Intel ?? [])) if (mentionsThisFaction(it)) mentions++;
}
dv.paragraph(`_Entries: ${own + mentions} (own ${own} + mentions ${mentions})_`);
```
```dataviewjs
// Current faction
const THIS = dv.current();
const thisName = String(THIS.file.name);
const thisLC = thisName.toLowerCase();
// All faction pages (including this one)
const factions = dv.pages("#faction");
// Mention detector: summary has [[This Faction]] OR source points at this faction
function mentionsThisFaction(entry) {
const sum = String(entry.summary ?? "");
if (sum.includes(`[[${thisName}]]`) || sum.includes(`[[${thisName}|`)) return true;
const src = entry.source;
const list = Array.isArray(src) ? src : (src ? [src] : []);
for (const s of list) {
if (typeof s === "string") {
if (s.includes(`[[${thisName}]]`) || s.includes(`[[${thisName}|`)) return true;
if (s.toLowerCase() === thisLC) return true; // fallback: plain text match
} else if (s && typeof s === "object" && s.path) { // wikilink object
const base = s.path.split("/").pop().replace(/\.md$/i,"").toLowerCase();
if (base === thisLC) return true;
}
}
return false;
}
// Collect rows
const rows = [];
// 1) Own intel
for (const it of (THIS.Intel ?? [])) {
rows.push({
date: it.date ?? "",
from: THIS.file.link,
type: it.type ?? "",
summary: String(it.summary ?? ""),
source: it.source ?? "",
rel: it.reliability ?? "",
cred: it.credibility ?? "",
tags: Array.isArray(it.tags) ? it.tags.join(", ") : (it.tags ?? "")
});
}
// 2) Mentions from other factions
for (const p of factions.where(p => p.file.name !== thisName)) {
for (const it of (p.Intel ?? [])) {
if (mentionsThisFaction(it)) {
rows.push({
date: it.date ?? "",
from: p.file.link,
type: it.type ?? "",
summary: String(it.summary ?? ""),
source: it.source ?? "",
rel: it.reliability ?? "",
cred: it.credibility ?? "",
tags: Array.isArray(it.tags) ? it.tags.join(", ") : (it.tags ?? "")
});
}
}
}
// Sort newest first
rows.sort((a,b) => String(b.date).localeCompare(String(a.date)));
if (!rows.length) {
dv.paragraph("_No intel yet._");
} else {
dv.table(
["Date","From Faction","Type","Summary","Source","Rel","Cred","Tags"],
rows.map(r => [r.date, r.from, r.type, r.summary, r.source, r.rel, r.cred, r.tags])
);
}
```
> Add new entries in the **frontmatter** under `Intel:` (keep newest on top). Suggested fields: `date, type, summary, source, reliability, credibility, tags`.
---
## 🔗 Related NPCs (auto)
```dataview
TABLE link(file.name) AS NPC, number(Level_of_Influence) AS Influence, default(SMH_Acronym, "—") AS SMH
FROM #npc
WHERE file.name != "NPC Template"
AND (
Faction = this.file.link
OR lower(string(Faction)) = lower(this.file.name)
OR contains(lower(string(Faction)), lower(this.file.name))
)
SORT number(Level_of_Influence) DESC
```
---
## 📌 Plot Hooks & Notes
-
-
---
## 🗒 Session Updates
- 2026-07-22: …
@@ -1,5 +1,5 @@
--- ---
Level_of_Influence: 5 Level_of_Influence: 6
Faction: Faction:
Tags: Tags:
- npc - npc
@@ -5,6 +5,13 @@ SMH_Acronym:
Tags: Tags:
- npc - npc
Intel: Intel:
- date: 2026-07-08
type: op
summary: While infiltrating the Arch, we find out that [[Fritch]] has been working on the dig under the Arch - currently serving as a Dig Leader for the day we do our infiltration. We're currently not sure how he managed to end up down here, but it's plausible to assume that he got drafted down here in the shakeup of Whitewater.
session: "[[Session 33 - Infiltration of the Arch]]"
reliability: A
credibility: 5
tags: []
- date: 2026-01-07 - date: 2026-01-07
type: interaction type: interaction
summary: "[[Metternich]] tells [[Fritch]] that [[House Elidari]] plans to supplant [[The Archmasons]]. [[Metternich]] says that he doesn't ask for anything in return at the moment, but asks for an opportunity to solve problems." summary: "[[Metternich]] tells [[Fritch]] that [[House Elidari]] plans to supplant [[The Archmasons]]. [[Metternich]] says that he doesn't ask for anything in return at the moment, but asks for an opportunity to solve problems."
@@ -144,7 +151,8 @@ type command
action Templater: Insert Add Intel Entry to NPC action Templater: Insert Add Intel Entry to NPC
``` ```
---
## 🏛️ Relations & Factions ## 🏛️ Relations & Factions
- **Primary Faction:** [[The Archmasons]] - **Primary Faction:** [[The Archmasons]]
@@ -1,5 +1,5 @@
--- ---
Level_of_Influence: 17 Level_of_Influence: 18
Faction: "[[House Asase]]" Faction: "[[House Asase]]"
Tags: Tags:
- npc - npc
@@ -1,5 +1,5 @@
--- ---
Level_of_Influence: 9 Level_of_Influence: 10
Faction: Faction:
SMH_Acronym: Synchronized Mushroom Hiccup SMH_Acronym: Synchronized Mushroom Hiccup
Tags: Tags:
@@ -1,5 +1,5 @@
--- ---
Level_of_Influence: 6 Level_of_Influence: 8
Faction: Faction:
SMH_Acronym: SMH_Acronym:
Tags: Tags:
@@ -17,10 +17,10 @@ Tags:
## 🧑 NPC Overview ## 🧑 NPC Overview
- **Full Name:** Morag Tenrae - **Full Name:** Morag Tenrae
- **Race / Ancestry:** - **Race / Ancestry:** Sun Elf
- **Gender / Pronouns:** - **Gender / Pronouns:** Female
- **Occupation / Role:** - **Occupation / Role:** Governor of Whitewater
- **Faction / Allegiance:** - **Faction / Allegiance:** [[House Tenrae]]
- **SMH (what THEY call it):** `= this.SMH_Acronym` - **SMH (what THEY call it):** `= this.SMH_Acronym`
- **Notable Traits:** (quirks, mannerisms, appearance) - **Notable Traits:** (quirks, mannerisms, appearance)
- **First Impression:** (how the party perceives them) - **First Impression:** (how the party perceives them)
@@ -137,7 +137,7 @@ action Templater: Insert Add Intel Entry to NPC
--- ---
## 🏛️ Relations & Factions ## 🏛️ Relations & Factions
- **Primary Faction:** [[Faction Name]] - **Primary Faction:** [[House Tenrae]]
- **Allied Factions:** [[Faction A]], [[Faction B]] - **Allied Factions:** [[Faction A]], [[Faction B]]
- **Rival Factions:** [[Faction C]] - **Rival Factions:** [[Faction C]]
- **Personal Enemies / Allies:** [[NPC or PC]] - **Personal Enemies / Allies:** [[NPC or PC]]
@@ -162,6 +162,7 @@ action Templater: Insert Add Intel Entry to NPC
- **Current Location:** - **Current Location:**
- **Important Items / Assets:** - **Important Items / Assets:**
- **Plot Hooks / Ties to PCs:** - **Plot Hooks / Ties to PCs:**
- Known to be single.
- **Session Notes / Updates:** - **Session Notes / Updates:**
- 2026-07-01: … - 2026-07-01: …
@@ -1,5 +1,5 @@
--- ---
Level_of_Influence: 9 Level_of_Influence: 11
Faction: "[[House Vyshaan]]" Faction: "[[House Vyshaan]]"
SMH_Acronym: SMH_Acronym:
Tags: Tags:
@@ -1,5 +1,5 @@
--- ---
Level_of_Influence: 0 Level_of_Influence: 1
Faction: "[[House Asase]]" Faction: "[[House Asase]]"
SMH_Acronym: SMH_Acronym:
Tags: Tags:
@@ -0,0 +1,180 @@
---
Date: 2026-07-08
Session_Name: Session 33 - Infiltration of the Arch
Tags:
- pf2e
- session
---
# Session 33 - Infiltration of the Arch
> **Date:** `= this.Date` • **Name:** `= this.Session_Name`
---
## 📄 Session Summary (auto)
<!-- SUMMARY-START -->
*No summary yet — click “Generate Summary” below.*
<!-- SUMMARY-END -->
```button
name ✍️ Generate AI Summary
type template
action Templates/Generate AI Session Summary.md
templater true
```
## 🧭 Where / When
- **Region / Location:**
- **In-game Date / Time:**
- **Weather / Conditions:**
---
## 👥 PCs Present / Absent
- **Present:**
- **Absent:**
---
## ⭐ Highlights (feed the auto-summary)
> Add one or more `Highlight::` lines. The button will build a summary from these.
- Highlight::
- Highlight::
- Highlight::
---
## 🎯 Quests & Progress
- **Active Objectives:**
- **Progress / Resolutions:**
---
## 🗣️ NPCs Met / Factions
- **NPCs:** [[ ]] [[ ]] [[ ]]
- **Factions Touched:** [[ ]] [[ ]]
---
## ⚔️ Encounters
- **Social / Exploration:**
- Infiltration of the Arch
- Edge Points: 2
- My Current Deception DC: 22 (1 + 7 + 4 +10) (+3 when lying with Metternich, per following the Expert)
- We talk our way past the first couple of guards and say that we're running early due to mis-planning and misunderstood timing.
- A couple guards in front of the stairs heading down to the dig site, questions us a bit more; getting all our names and mentioning that we won't be able to come back up to the base camp for 12 hours (8hr shift + 4hrs early)
- We also learn that [[Fritch]] is working as the Dig Leader for the day of our infiltration.
- The group opts to explore around the dig area first before reporting to [[Fritch]]
- Exploring some of the area, we find an Elevator that heads down - a sheer drop back into the City. [[Kite]] and [[Calen]] pick up trash with the minecart and overhear a conversation with [[Morag Tenrae]] and a robed individual. They speak on letting the Governor know if they find any other pieces or bringing things back up to the basecamp to help sustain the workers.
- We find a hidden room in one of the rooms, which leads to a chamber which contains what is effectively a computer that contains information about the peoples and lifeforms that have passed through the portal or who have accessed the life system - called the [[Lifeform Catalog]]
- The last access prior to us was 32 hours prior and was [[Kite's Husband]]
- [[Calen]] questions [[Kite]] as to the purpose and [[Kite]] says that it was a system used to identify health and detect diseases - but Calen realizes there is something off to what he is told.
- An Empirical Analysis: Theoretically, large amounts of biological data would allow for the tracking of generational tendencies towards certain diseases. With modern medicine, biological and genetic manipulation via magical means could even allow the erradication of certain ailments that living creatures are predisposed towards.
- **Combat:**
- **Outcome / Loot:**
---
## 🧠 Intel Captured (auto)
```dataviewjs
const THIS = dv.current();
const sessName = THIS.file.name;
const sessDate = THIS.Date ?? dv.current().file.frontmatter?.Date ?? "";
const sessLC = sessName.toLowerCase();
const pages = dv.pages("#npc or #faction").where(p => p.Intel);
function matchesSessionField(sessionField) {
const list = Array.isArray(sessionField) ? sessionField : [sessionField];
for (const s of list) {
if (!s) continue;
if (typeof s === "object" && s.path) {
const base = s.path.split("/").pop().replace(/\.md$/i,"");
if (base.toLowerCase() === sessLC) return true;
} else {
const text = String(s);
if (text.includes(`[[${sessName}]]`)) return true;
if (text.toLowerCase() === sessLC) return true;
}
}
return false;
}
const rows = [];
for (const p of pages) {
for (const it of p.Intel) {
let ok = false;
if (it.session) ok = matchesSessionField(it.session);
if (!ok && sessDate && it.date) ok = String(it.date) === String(sessDate); // fallback
if (ok) {
rows.push({
from: p.file.link,
date: it.date ?? "",
type: it.type ?? "",
summary: String(it.summary ?? ""),
source: it.source ?? "",
rel: it.reliability ?? "",
cred: it.credibility ?? "",
tags: Array.isArray(it.tags) ? it.tags.join(", ") : (it.tags ?? "")
});
}
}
}
rows.sort((a,b)=> String(b.date).localeCompare(String(a.date)));
if (!rows.length) {
dv.paragraph("_No intel captured for this session yet._");
} else {
dv.table(
["From", "Date", "Type", "Summary", "Source", "Rel", "Cred", "Tags"],
rows.map(r => [r.from, r.date, r.type, r.summary, r.source, r.rel, r.cred, r.tags])
);
}
```
---
## 📦 Treasure & Rewards
- **Items:**
- **Coin:**
- **XP / Milestones:**
---
## 🔜 Next Hooks / To-Dos
- [ ]
- [ ]
- [ ]
@@ -0,0 +1,168 @@
---
Date: 2026-07-15
Session_Name: Session 34 - Infiltration of the Arch Part 2
Tags:
- pf2e
- session
---
# Session 34 - Infiltration of the Arch Part 2
> **Date:** `= this.Date` • **Name:** `= this.Session_Name`
---
## 📄 Session Summary (auto)
<!-- SUMMARY-START -->
*No summary yet — click “Generate Summary” below.*
<!-- SUMMARY-END -->
```button
name ✍️ Generate AI Summary
type template
action Templates/Generate AI Session Summary.md
templater true
```
## 🧭 Where / When
- **Region / Location:**
- **In-game Date / Time:**
- **Weather / Conditions:**
---
## 👥 PCs Present / Absent
- **Present:**
- **Absent:**
---
## ⭐ Highlights (feed the auto-summary)
> Add one or more `Highlight::` lines. The button will build a summary from these.
- Highlight::
- Highlight::
- Highlight::
---
## 🎯 Quests & Progress
- **Active Objectives:**
- **Progress / Resolutions:**
---
## 🗣️ NPCs Met / Factions
- **NPCs:** [[ ]] [[ ]] [[ ]]
- **Factions Touched:** [[ ]] [[ ]]
---
## ⚔️ Encounters
- **Social / Exploration:**
- **Combat:**
- **Outcome / Loot:**
---
## 🧠 Intel Captured (auto)
```dataviewjs
const THIS = dv.current();
const sessName = THIS.file.name;
const sessDate = THIS.Date ?? dv.current().file.frontmatter?.Date ?? "";
const sessLC = sessName.toLowerCase();
const pages = dv.pages("#npc or #faction").where(p => p.Intel);
function matchesSessionField(sessionField) {
const list = Array.isArray(sessionField) ? sessionField : [sessionField];
for (const s of list) {
if (!s) continue;
if (typeof s === "object" && s.path) {
const base = s.path.split("/").pop().replace(/\.md$/i,"");
if (base.toLowerCase() === sessLC) return true;
} else {
const text = String(s);
if (text.includes(`[[${sessName}]]`)) return true;
if (text.toLowerCase() === sessLC) return true;
}
}
return false;
}
const rows = [];
for (const p of pages) {
for (const it of p.Intel) {
let ok = false;
if (it.session) ok = matchesSessionField(it.session);
if (!ok && sessDate && it.date) ok = String(it.date) === String(sessDate); // fallback
if (ok) {
rows.push({
from: p.file.link,
date: it.date ?? "",
type: it.type ?? "",
summary: String(it.summary ?? ""),
source: it.source ?? "",
rel: it.reliability ?? "",
cred: it.credibility ?? "",
tags: Array.isArray(it.tags) ? it.tags.join(", ") : (it.tags ?? "")
});
}
}
}
rows.sort((a,b)=> String(b.date).localeCompare(String(a.date)));
if (!rows.length) {
dv.paragraph("_No intel captured for this session yet._");
} else {
dv.table(
["From", "Date", "Type", "Summary", "Source", "Rel", "Cred", "Tags"],
rows.map(r => [r.from, r.date, r.type, r.summary, r.source, r.rel, r.cred, r.tags])
);
}
```
---
## 📦 Treasure & Rewards
- **Items:**
- **Coin:**
- **XP / Milestones:**
---
## 🔜 Next Hooks / To-Dos
- [ ]
- [ ]
- [ ]
Binary file not shown.

After

Width:  |  Height:  |  Size: 410 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 KiB