Compare commits

...
2 Commits
11 changed files with 598 additions and 10 deletions
@@ -0,0 +1,217 @@
---
Reputation: 5
Faction_Type:
Motto:
Ideology:
Symbol:
Colors:
Headquarters:
Territories:
-
Allies:
-
Rivals:
-
SMH_Acronym:
Intel:
Tags:
- faction
---
# Alsatian Soldiers
*One-line role/description — e.g., “Elven High House controlling Yathirs docks.”*
---
## 🎨 Artwork
![[Alsatian Soldiers.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-01: …
@@ -14,6 +14,13 @@ Rivals:
- -
SMH_Acronym: SMH_Acronym:
Intel: Intel:
- date: 2026-07-01
type: interaction
summary: "[[Iniana Asase]] mentions that representatives from [[House Evandra]] are visiting with [[House Asase]]. She also does not know anything about the [[House Miiran]] representatives that are in the city; she will however try to find out."
source: "[[Iniana Asase]]"
reliability: B
credibility: 5
tags: []
- date: 2026-02-03 - date: 2026-02-03
type: interaction type: interaction
summary: According to Freddie, those of [[House Asase]] reports to a few different houses in the iupper echelons - tha parents have connections with [[House Evandra]] which they attempt to leverage regularly. It is part of the reason that they're attempting to work around. It is also rumored that the Assase has operations in the Wells - possibly the one that is abducting all of the Halflings. The Eldest Child is more interested in his rules and books to have loyalties to anyone.' summary: According to Freddie, those of [[House Asase]] reports to a few different houses in the iupper echelons - tha parents have connections with [[House Evandra]] which they attempt to leverage regularly. It is part of the reason that they're attempting to work around. It is also rumored that the Assase has operations in the Wells - possibly the one that is abducting all of the Halflings. The Eldest Child is more interested in his rules and books to have loyalties to anyone.'
@@ -57,9 +64,10 @@ Tags:
# House Asase # House Asase
*One-line role/description — e.g., “Elven High House controlling Yathirs docks.”* *Child House of [[House Evandra]]*
---
## 🎨 Artwork ## 🎨 Artwork
![[House Asase.png]] ![[House Asase.png]]
@@ -1,5 +1,5 @@
--- ---
Reputation: 5 Reputation: 8
Faction_Type: Gang Faction_Type: Gang
Motto: Motto:
Ideology: Semi-Communism Ideology: Semi-Communism
@@ -50,7 +50,15 @@ Knows About HQ: "True"
- **Notes on Influence:** (what actions improve/worsen standing) - **Notes on Influence:** (what actions improve/worsen standing)
- ***Discovery Skills*** - ***Discovery Skills***
- ***Influence Skills*** - ***Influence Skills***
- DC 14 Mercantile Lore
- DC 17 Thievery
- DC 19 Acrobatics
- DC 19 Society
- DC 21 Diplomacy
- DC 21 Deception
- DC 24 Intimidation
- ***Weaknesses*** - ***Weaknesses***
- Working towards a more stable future for her and her sisters. Trying to introduce stability to Yathyr.
- ***Resistances*** - ***Resistances***
- ***Biases*** - ***Biases***
@@ -1,5 +1,5 @@
--- ---
Level_of_Influence: 4 Level_of_Influence: 5
Faction: Faction:
Tags: Tags:
- npc - npc
@@ -36,9 +36,13 @@ Knows About HQ: "False"
- DC 17 Society - DC 17 Society
- DC 19 Perception - DC 19 Perception
- ***Influence Skills*** - ***Influence Skills***
- DC 24 Deception - DC 14 Trackless Lore
- DC 21 Intimidation - DC 17 Nature (discussing the terrain and its effects on cultural differences)
- DC 17 Acrobatics/Athletics
- DC 19 Diplomacy - DC 19 Diplomacy
- DC 19 Religion
- DC 21 Intimidation
- DC 24 Deception
- ***Weaknesses*** - ***Weaknesses***
- Most happy when offered fresh drink/food. Reduces Influence DC by 2. - Most happy when offered fresh drink/food. Reduces Influence DC by 2.
- ***Resistances*** - ***Resistances***
@@ -1,5 +1,5 @@
--- ---
Level_of_Influence: 11 Level_of_Influence: 13
Faction: "[[Draycott Family]]" Faction: "[[Draycott Family]]"
SMH_Acronym: SMH_Acronym:
Tags: Tags:
@@ -1,5 +1,5 @@
--- ---
Level_of_Influence: 13 Level_of_Influence: 17
Faction: "[[House Asase]]" Faction: "[[House Asase]]"
Tags: Tags:
- npc - npc
@@ -1,5 +1,5 @@
--- ---
Level_of_Influence: 4 Level_of_Influence: 6
Faction: Faction:
SMH_Acronym: SMH_Acronym:
Tags: Tags:
@@ -0,0 +1,174 @@
---
Level_of_Influence: 0
Faction: "[[House Tenrae]]"
SMH_Acronym:
Tags:
- npc
---
# Morag Tenrae
*Governor of Whitewater District*
## 🎨 Artwork
![[Morag Tenrae.png]]
*Optional caption / alt text*
---
## 🧑 NPC Overview
- **Full Name:** Morag Tenrae
- **Race / Ancestry:**
- **Gender / Pronouns:**
- **Occupation / Role:**
- **Faction / Allegiance:**
- **SMH (what THEY call it):** `= this.SMH_Acronym`
- **Notable Traits:** (quirks, mannerisms, appearance)
- **First Impression:** (how the party perceives them)
---
## 🤝 Relationship with Party
- **Level of Influence:** `= this.Level_of_Influence` (10 to +10)
- **Notes on Influence:** (what actions improve/worsen standing)
- ***Discovery Skills***
- ***Influence Skills***
- ***Weaknesses***
- ***Resistances***
- ***Biases***
---
## 🧠 Intel (auto)
```dataviewjs
const THIS = dv.current();
const thisName = String(THIS.file.name);
const thisLC = thisName.toLowerCase();
// Scan faction & NPC notes that have Intel arrays
const pages = dv.pages("#npc or #faction").where(p => p.Intel);
// Does an Intel entry reference THIS NPC?
function mentionsThisNPC(entry) {
const sum = String(entry.summary ?? "");
// 1) Explicit wikilink in summary
if (sum.includes(`[[${thisName}]]`) || sum.includes(`[[${thisName}|`)) return true;
// 2) Source field (string/link/list)
const src = entry.source;
const arr = Array.isArray(src) ? src : (src ? [src] : []);
for (const s of arr) {
if (typeof s === "string") {
// quoted link or plain text
const unq = s.replace(/^"+|"+$/g, ""); // drop surrounding quotes if any
if (unq.includes(`[[${thisName}]]`) || unq.includes(`[[${thisName}|`)) return true;
// if they typed just the name
if (unq.replace(/\[\[|\]\]/g, "").trim().toLowerCase() === thisLC) return true;
} 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;
}
}
// Optional (looser): plain text mention in summary
// return sum.toLowerCase().includes(thisLC);
return false;
}
// Collect rows: 1) own Intel, 2) mentions from other notes
const rows = [];
// Own Intel (from this NPC note)
for (const it of (THIS.Intel ?? [])) {
rows.push({
from: THIS.file.link,
date: it.date ?? "",
type: it.type ?? "",
summary: String(it.summary ?? ""),
session: it.session ?? "",
source: it.source ?? "",
rel: it.reliability ?? "",
cred: it.credibility ?? "",
tags: Array.isArray(it.tags) ? it.tags.join(", ") : (it.tags ?? "")
});
}
// Mentions elsewhere
for (const p of pages.where(p => p.file.path !== THIS.file.path)) {
for (const it of (p.Intel ?? [])) {
if (mentionsThisNPC(it)) {
rows.push({
from: p.file.link,
date: it.date ?? "",
type: it.type ?? "",
summary: String(it.summary ?? ""),
session: it.session ?? "",
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.paragraph(`_Entries: ${rows.length} (own ${(THIS.Intel ?? []).length} + mentions ${Math.max(0, rows.length - (THIS.Intel ?? []).length)})_`);
dv.table(
["From Note","Date","Type","Summary","Session","Source","Rel","Cred","Tags"],
rows.map(r => [r.from, r.date, r.type, r.summary, r.session, r.source, r.rel, r.cred, r.tags])
);
}
```
```button
name Add Intel
type command
action Templater: Insert Add Intel Entry to NPC
```
---
## 🏛️ Relations & Factions
- **Primary Faction:** [[Faction Name]]
- **Allied Factions:** [[Faction A]], [[Faction B]]
- **Rival Factions:** [[Faction C]]
- **Personal Enemies / Allies:** [[NPC or PC]]
---
## 📖 History & Background
- **Origin / Past:**
- **Known Motivations:**
- **Secrets / Rumors:**
---
## 🎭 Roleplay Notes
- **Personality:** (e.g., stern, practical, loyal)
- **Speech Style / Quirks:** (catchphrases, accent, tics)
- **Appearance Details:** (clothing, scars, distinguishing features)
---
## 🗺️ Miscellaneous
- **Current Location:**
- **Important Items / Assets:**
- **Plot Hooks / Ties to PCs:**
- **Session Notes / Updates:**
- 2026-07-01: …
---
## 🔗 Connections
- **Related NPCs:**
- [[NPC A]] (Mentor)
- [[NPC B]] (Rival)
- **PC Ties:** (how the party knows them)
@@ -1,5 +1,5 @@
--- ---
Level_of_Influence: 3 Level_of_Influence: 5
Faction: "[[House Elidari]]" Faction: "[[House Elidari]]"
SMH_Acronym: SMH_Acronym:
Tags: Tags:
@@ -0,0 +1,177 @@
---
Date: 2026-07-01
Session_Name: Session 32 - Downtime Activities
Tags:
- pf2e
- session
---
# Session 32 - Downtime Activities
> **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:**
- The group performs some downtime activities..
- Calen reaches out to the High Curate and requests some Acolyte's to be sent to the new SMH Headquarters.
- Discovery on Celosia and Influence the Thin Wisps.
- Influence [[Iniana Asase]] and learns some information about what the City Watch in Whitewater is up to:
- Most of the guards are just [[The Archmasons]] in new armor. They have been put through some efficacy training and under the new governance, the brutality of [[The Archmasons]] is being tamped down.
- That is not to say to that it's not happening, only that it's getting better.
- The most loyal of the guards are being recruited for some other branch of the City Watch.
- [[Metternich]]
- Mentions that the City Watch who are being recruited for the Special branch of the Watch are likely for [[House Elidari]] and will likely be fiercely loyal.
-
- **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
- [ ]
- [ ]
- [ ]