+556
-1
Diff
round #0
+12
public/lang/en.json
+12
public/lang/en.json
+52
public/module.json
+52
public/module.json
···
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
]
47
+
},
48
+
"esmodules": [
49
+
"main.iife.js"
50
+
],
51
+
"languages": [
52
+
{
src/styles/kingdom-sheet.css
public/styles/kingdom-sheet.css
src/styles/kingdom-sheet.css
public/styles/kingdom-sheet.css
src/templates/levels/level-1.hbs
public/templates/levels/level-1.hbs
src/templates/levels/level-1.hbs
public/templates/levels/level-1.hbs
src/templates/levels/level-10.hbs
public/templates/levels/level-10.hbs
src/templates/levels/level-10.hbs
public/templates/levels/level-10.hbs
src/templates/levels/level-11.hbs
public/templates/levels/level-11.hbs
src/templates/levels/level-11.hbs
public/templates/levels/level-11.hbs
src/templates/levels/level-12.hbs
public/templates/levels/level-12.hbs
src/templates/levels/level-12.hbs
public/templates/levels/level-12.hbs
src/templates/levels/level-13.hbs
public/templates/levels/level-13.hbs
src/templates/levels/level-13.hbs
public/templates/levels/level-13.hbs
src/templates/levels/level-14.hbs
public/templates/levels/level-14.hbs
src/templates/levels/level-14.hbs
public/templates/levels/level-14.hbs
src/templates/levels/level-15.hbs
public/templates/levels/level-15.hbs
src/templates/levels/level-15.hbs
public/templates/levels/level-15.hbs
src/templates/levels/level-16.hbs
public/templates/levels/level-16.hbs
src/templates/levels/level-16.hbs
public/templates/levels/level-16.hbs
src/templates/levels/level-17.hbs
public/templates/levels/level-17.hbs
src/templates/levels/level-17.hbs
public/templates/levels/level-17.hbs
src/templates/levels/level-18.hbs
public/templates/levels/level-18.hbs
src/templates/levels/level-18.hbs
public/templates/levels/level-18.hbs
src/templates/levels/level-19.hbs
public/templates/levels/level-19.hbs
src/templates/levels/level-19.hbs
public/templates/levels/level-19.hbs
src/templates/levels/level-2.hbs
public/templates/levels/level-2.hbs
src/templates/levels/level-2.hbs
public/templates/levels/level-2.hbs
src/templates/levels/level-20.hbs
public/templates/levels/level-20.hbs
src/templates/levels/level-20.hbs
public/templates/levels/level-20.hbs
src/templates/levels/level-3.hbs
public/templates/levels/level-3.hbs
src/templates/levels/level-3.hbs
public/templates/levels/level-3.hbs
src/templates/levels/level-4.hbs
public/templates/levels/level-4.hbs
src/templates/levels/level-4.hbs
public/templates/levels/level-4.hbs
src/templates/levels/level-5.hbs
public/templates/levels/level-5.hbs
src/templates/levels/level-5.hbs
public/templates/levels/level-5.hbs
src/templates/levels/level-6.hbs
public/templates/levels/level-6.hbs
src/templates/levels/level-6.hbs
public/templates/levels/level-6.hbs
src/templates/levels/level-7.hbs
public/templates/levels/level-7.hbs
src/templates/levels/level-7.hbs
public/templates/levels/level-7.hbs
src/templates/levels/level-8.hbs
public/templates/levels/level-8.hbs
src/templates/levels/level-8.hbs
public/templates/levels/level-8.hbs
src/templates/levels/level-9.hbs
public/templates/levels/level-9.hbs
src/templates/levels/level-9.hbs
public/templates/levels/level-9.hbs
src/templates/sheet.hbs
public/templates/sheet.hbs
src/templates/sheet.hbs
public/templates/sheet.hbs
src/templates/tab-link.hbs
public/templates/tab-link.hbs
src/templates/tab-link.hbs
public/templates/tab-link.hbs
src/templates/tab.hbs
public/templates/tab.hbs
src/templates/tab.hbs
public/templates/tab.hbs
src/templates/tabs/tab-effects.hbs
public/templates/tabs/tab-effects.hbs
src/templates/tabs/tab-effects.hbs
public/templates/tabs/tab-effects.hbs
src/templates/tabs/tab-kingdom.hbs
public/templates/tabs/tab-kingdom.hbs
src/templates/tabs/tab-kingdom.hbs
public/templates/tabs/tab-kingdom.hbs
src/templates/tabs/tab-relations.hbs
public/templates/tabs/tab-relations.hbs
src/templates/tabs/tab-relations.hbs
public/templates/tabs/tab-relations.hbs
src/templates/tabs/tab-settlements.hbs
public/templates/tabs/tab-settlements.hbs
src/templates/tabs/tab-settlements.hbs
public/templates/tabs/tab-settlements.hbs
src/templates/tabs/tab-turn.hbs
public/templates/tabs/tab-turn.hbs
src/templates/tabs/tab-turn.hbs
public/templates/tabs/tab-turn.hbs
+14
package-lock.json
+14
package-lock.json
···
8
8
"@league-of-foundry-developers/foundry-vtt-types": "^13.346.0-beta.20250812191140",
9
9
"@sveltejs/vite-plugin-svelte": "^6.2.1",
10
10
"@tsconfig/svelte": "^5.0.5",
11
+
"dotenv": "^17.2.3",
11
12
"terser": "^5.44.0",
12
13
"vite": "^7.1.7"
13
14
}
···
2078
2079
"url": "https://github.com/fb55/domutils?sponsor=1"
2079
2080
}
2080
2081
},
2082
+
"node_modules/dotenv": {
2083
+
"version": "17.2.3",
2084
+
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
2085
+
"integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==",
2086
+
"dev": true,
2087
+
"license": "BSD-2-Clause",
2088
+
"engines": {
2089
+
"node": ">=12"
2090
+
},
2091
+
"funding": {
2092
+
"url": "https://dotenvx.com"
2093
+
}
2094
+
},
2081
2095
"node_modules/dunder-proto": {
2082
2096
"version": "1.0.1",
2083
2097
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+1
package.json
+1
package.json
+38
config.ts
+38
config.ts
···
1
+
import dotenv from "dotenv";
2
+
import path from "path";
3
+
4
+
dotenv.config({ path: path.resolve(__dirname, ".env") });
5
+
6
+
interface ENV {
7
+
MODULE_DIR: string | undefined;
8
+
}
9
+
10
+
interface Config {
11
+
outdir: string;
12
+
}
13
+
14
+
const getConfig = (): ENV => {
15
+
return {
16
+
MODULE_DIR: process.env.MODULE_DIR
17
+
};
18
+
}
19
+
20
+
const getSanitizedConfig = (config: ENV): Config => {
21
+
let outdir: string;
22
+
23
+
if (config.MODULE_DIR === undefined) {
24
+
outdir = path.join(process.cwd(), "dist");
25
+
} else {
26
+
outdir = config.MODULE_DIR;
27
+
}
28
+
29
+
return {
30
+
outdir
31
+
} as Config;
32
+
}
33
+
34
+
const config = getConfig();
35
+
36
+
const sanitizedConfig = getSanitizedConfig(config);
37
+
38
+
export default sanitizedConfig;
+36
src/module/data/charter.json
+36
src/module/data/charter.json
···
1
+
[
2
+
{
3
+
"id": "conquest",
4
+
"boosts": [
5
+
"loyalty",
6
+
"free"
7
+
]
8
+
},
9
+
{
10
+
"id": "expansion",
11
+
"boosts": [
12
+
"culture",
13
+
"free"
14
+
]
15
+
},
16
+
{
17
+
"id": "exploration",
18
+
"boosts": [
19
+
"stability",
20
+
"free"
21
+
]
22
+
},
23
+
{
24
+
"id": "grant",
25
+
"boosts": [
26
+
"economy",
27
+
"free"
28
+
]
29
+
},
30
+
{
31
+
"id": "open",
32
+
"boosts": [
33
+
"free"
34
+
]
35
+
}
36
+
]
+56
src/module/data/governments.json
+56
src/module/data/governments.json
···
1
+
[
2
+
{
3
+
"id": "despotism",
4
+
"boosts": [
5
+
"stability",
6
+
"economy",
7
+
"free"
8
+
],
9
+
"feat": "crush-dissent"
10
+
},
11
+
{
12
+
"id": "feudalism",
13
+
"boosts": [
14
+
"stability",
15
+
"culture",
16
+
"free"
17
+
],
18
+
"feat": "fortified-fiefs"
19
+
},
20
+
{
21
+
"id": "oligarchy",
22
+
"boosts": [
23
+
"loyalty",
24
+
"economy",
25
+
"free"
26
+
],
27
+
"feat": "insider-trading"
28
+
},
29
+
{
30
+
"id": "republic",
31
+
"boosts": [
32
+
"stability",
33
+
"loyalty",
34
+
"free"
35
+
],
36
+
"feat": "pull-together"
37
+
},
38
+
{
39
+
"id": "thaumocracy",
40
+
"boosts": [
41
+
"economy",
42
+
"culture",
43
+
"free"
44
+
],
45
+
"feat": "practical-magic"
46
+
},
47
+
{
48
+
"id": "yeomanry",
49
+
"boosts": [
50
+
"loyalty",
51
+
"culture",
52
+
"free"
53
+
],
54
+
"feat": "muddle-through"
55
+
}
56
+
]
+18
src/module/data/heartland.json
+18
src/module/data/heartland.json
src/module/data/charter.json
src/data/charter.json
src/module/data/charter.json
src/data/charter.json
src/module/data/governments.json
src/data/governments.json
src/module/data/governments.json
src/data/governments.json
src/module/data/heartland.json
src/data/heartland.json
src/module/data/heartland.json
src/data/heartland.json
+30
src/kingdom-sheet.ts
+30
src/kingdom-sheet.ts
···
1
+
import { Kingdom } from "./kingdom";
2
+
3
+
interface NPCPF2e {
4
+
flags: {
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
foundry.documents.collections.Actors.registerSheet("pf2e", KingdomSheet, {
24
+
types: [
25
+
"npc"
26
+
],
27
+
label: (game as foundry.Game).i18n!.localize("kingdom-homebrew.kingdom-title")
28
+
});
29
+
}
30
+
+216
src/kingdom.ts
+216
src/kingdom.ts
···
1
+
import * as data from "./data";
2
+
3
+
/**
4
+
* A Kingdom structure.
5
+
* @typedef {Object} Kingdom
6
+
* @property {string} name - The name of the Kingdom
7
+
* @property {string} charter - The id of the charter
8
+
* @property {string} government - The id of the government
9
+
* @property {string} heartland - The id of the heartland
10
+
* @property {string[]} boosts - An array of free boosts for the Kingdom
11
+
* @property {LeaderInfo} leaders - Leaders of the kingdom.
12
+
* @property {string[]} feats - An array of feats for the Kingdom
13
+
* @property {number} size - The size of the Kingdom
14
+
* @property {ResourceInfo} resourceDice - The resource dice for the Kingdom
15
+
* @property {CommodityInfo} commodities - The commodities for the Kingdom
16
+
* @property {ResourceInfo} resourcePoints - The resource points for the Kingdom
17
+
* @property {ResourceLimitInfo} unrest - The unrest for the Kingdom
18
+
* @property {RuinInfo} ruin - The ruin for the Kingdom
19
+
* @property {Relation[]} groups - Other groups the Kingdom has relations with
20
+
* @property {ResourceLimitInfo} krp - The Kingdom Reputation Points
21
+
* @property {string[]} settlements - An array of Scene IDs for the Kingdom's settlements
22
+
* @property {number} level - The level of the Kingdom
23
+
*/
24
+
export class Kingdom {
25
+
name: string;
26
+
charter: data.Charter;
27
+
government: data.Government;
28
+
heartland: data.Heartland;
29
+
boosts: data.Boost[];
30
+
leaders: LeaderInfo;
31
+
feats: string[];
32
+
size: number;
33
+
resourceDice: ResourceInfo;
34
+
commodities: CommodityInfo;
35
+
resourcePoints: ResourceInfo;
36
+
unrest: ResourceLimitInfo;
37
+
ruin: RuinInfo;
38
+
groups: Relation[];
39
+
krp: ResourceLimitInfo;
40
+
settlements: string[];
41
+
level: number;
42
+
43
+
constructor() {
44
+
this.name = "";
45
+
this.level = 0;
46
+
this.charter = {
47
+
id: "",
48
+
boosts: []
49
+
};
50
+
this.government = {
51
+
id: "",
52
+
boosts: [],
53
+
feat: ""
54
+
};
55
+
this.heartland = {
56
+
id: "",
57
+
boost: data.Boost.None
58
+
};
59
+
this.boosts = [];
60
+
this.leaders = new LeaderInfo();
61
+
this.feats = [];
62
+
this.size = 0;
63
+
this.resourceDice = new ResourceInfo();
64
+
this.commodities = new CommodityInfo();
65
+
this.resourcePoints = new ResourceInfo();
66
+
this.unrest = new ResourceLimitInfo();
67
+
this.ruin = new RuinInfo();
68
+
this.groups = [];
69
+
this.krp = new ResourceLimitInfo();
70
+
this.settlements = [];
71
+
}
72
+
}
73
+
74
+
/**
75
+
* Information about a Kingdom's leaders.
76
+
* @typedef {Object} LeaderInfo
77
+
* @property {string} ruler - The actor ID of the ruler
78
+
* @property {string} counselor - The actor ID of the counselor
79
+
* @property {string} viceroy - The actor ID of the viceroy
80
+
* @property {string} emissary - The actor ID of the emissary
81
+
* @property {string} warden - The actor ID of the warden
82
+
* @property {stirng} general - The actor ID of the general
83
+
* @property {string} magister - The actor ID of the magister
84
+
* @property {string} treasurer - The actor ID of the treasurer
85
+
*/
86
+
export class LeaderInfo {
87
+
ruler: string;
88
+
counselor: string;
89
+
viceroy: string;
90
+
emissary: string;
91
+
warden: string;
92
+
general: string;
93
+
magister: string;
94
+
treasurer: string;
95
+
96
+
constructor() {
97
+
this.ruler = "";
98
+
this.counselor = "";
99
+
this.viceroy = "";
100
+
this.emissary = "";
101
+
this.warden = "";
102
+
this.general = "";
103
+
this.magister = "";
104
+
this.treasurer = "";
105
+
}
106
+
}
107
+
108
+
/**
109
+
* Information about a resource. This resource has a Next and Current value.
110
+
* @typedef {Object} ResourceInfo
111
+
* @property {number} next - The amount to add on the next turn.
112
+
* @property {number} current - The current value of this resource.
113
+
*/
114
+
export class ResourceInfo {
115
+
next: number;
116
+
current: number;
117
+
118
+
constructor() {
119
+
this.next = 0;
120
+
this.current = 0;
121
+
}
122
+
}
123
+
124
+
/**
125
+
* Information about the Kingdom's commodities
126
+
* @typedef {Object} CommodityInfo
127
+
* @property {ResourceInfo} ore - The amount of Ore the Kingdom has
128
+
* @property {ResourceInfo} lumber - The amount of Lumber the Kingdom has
129
+
* @property {ResourceInfo} stone - The amount of Stone the Kingdom has
130
+
* @property {ResourceInfo} food - The amount of Food the Kingdom has
131
+
* @property {ResourceInfo} luxuries - The amount of Luxuries the Kingdom has
132
+
*/
133
+
export class CommodityInfo {
134
+
ore: ResourceInfo;
135
+
lumber: ResourceInfo;
136
+
stone: ResourceInfo;
137
+
food: ResourceInfo;
138
+
luxuries: ResourceInfo;
139
+
140
+
constructor() {
141
+
this.ore = new ResourceInfo();
142
+
this.lumber = new ResourceInfo();
143
+
this.stone = new ResourceInfo();
144
+
this.food = new ResourceInfo();
145
+
this.luxuries = new ResourceInfo();
146
+
}
147
+
}
148
+
149
+
/**
150
+
* Information about a resource. This resource has Next, Current, and Threshold values.
151
+
* @typedef {Object} ResourceLimitInfo
152
+
* @property {number} next - The amount to add on the next turn.
153
+
* @property {number} current - The current value of this resource.
154
+
* @property {number} threshold - The maximum value of this resource.
155
+
*/
156
+
export class ResourceLimitInfo {
157
+
next: number;
158
+
current: number;
159
+
threshold: number;
160
+
161
+
constructor() {
162
+
this.next = 0;
163
+
this.current = 0;
164
+
this.threshold = 0;
165
+
}
166
+
}
167
+
168
+
/**
169
+
* Information about the Kingdom's Ruin values.
170
+
* @typedef {Object} RuinInfo
171
+
* @property {ResourceLimitInfo} corruption - The amount of Corruption a Kingdom has
172
+
* @property {ResourceLimitInfo} crime - The amount of Crime a Kingdom has
173
+
* @property {ResourceLimitInfo} decay - The amount of Decay a Kingdom has
174
+
* @property {ResourceLimitInfo} strife - The amount of Strife a Kingdom has
175
+
*/
176
+
export class RuinInfo {
177
+
corruption: ResourceLimitInfo;
178
+
crime: ResourceLimitInfo;
179
+
decay: ResourceLimitInfo;
180
+
strife: ResourceLimitInfo;
181
+
182
+
constructor() {
183
+
this.corruption = new ResourceLimitInfo();
184
+
this.crime = new ResourceLimitInfo();
185
+
this.decay = new ResourceLimitInfo();
186
+
this.strife = new ResourceLimitInfo();
187
+
}
188
+
}
189
+
190
+
/**
191
+
* Information about a relation with another group the Kingdom has.
192
+
* @typedef {Object} Relation
193
+
* @property {string} name - The name of the group
194
+
* @property {string} relation - The type of relation the Kingdom has with this group
195
+
* @property {number} dc - The base Negotiation DC for this group
196
+
* @property {boolean} atWar - Is the Kingdom at war with this group?
197
+
*/
198
+
export class Relation {
199
+
name: string;
200
+
relation: RelationType;
201
+
dc: number;
202
+
atWar: boolean;
203
+
204
+
constructor() {
205
+
this.name = "";
206
+
this.relation = RelationType.None;
207
+
this.dc = 0;
208
+
this.atWar = false;
209
+
}
210
+
}
211
+
212
+
export enum RelationType {
213
+
None = "none",
214
+
TradeAgreement = "tradeAgreement",
215
+
DiplomaticRelations = "diplomaticRelations"
216
+
}
+17
src/main.ts
+17
src/main.ts
···
1
+
import KingdomSheet from "./kingdom-sheet";
2
+
import preloadTemplates from "./preloadTemplates";
3
+
import type { Socket, isocketlib } from "./utils";
4
+
5
+
declare var socketlib: isocketlib;
6
+
7
+
let socket: Socket;
8
+
9
+
Hooks.on("init", async (): Promise<void> => {
10
+
KingdomSheet.register();
11
+
await preloadTemplates();
12
+
console.log("Kingdom Homebrew loaded");
13
+
});
14
+
15
+
Hooks.once("socketlib.ready", (): void => {
16
+
socket = socketlib.registerModule("kingdom-homebrew");
17
+
});
+5
src/preloadTemplates.ts
+5
src/preloadTemplates.ts
src/data/governments.json
src/data/government.json
src/data/governments.json
src/data/government.json
+42
src/data/index.ts
+42
src/data/index.ts
···
1
+
import charters from "./charter.json";
2
+
import governments from "./government.json";
3
+
import heartlands from "./heartland.json";
4
+
5
+
export interface Charter {
6
+
id: string;
7
+
boosts: Boost[];
8
+
}
9
+
10
+
export interface Government {
11
+
id: string;
12
+
boosts: Boost[];
13
+
feat: string;
14
+
}
15
+
16
+
export interface Heartland {
17
+
id: string;
18
+
boost: Boost;
19
+
}
20
+
21
+
export enum Attribute {
22
+
Loyalty = "loyalty",
23
+
Culture = "culture",
24
+
Stability = "stability",
25
+
Economy = "economy",
26
+
None = ""
27
+
}
28
+
29
+
export enum Boost {
30
+
Loyalty = "loyalty",
31
+
Culture = "culture",
32
+
Stability = "stability",
33
+
Economy = "economy",
34
+
None = "",
35
+
Free = "free"
36
+
}
37
+
38
+
export const data = {
39
+
charters,
40
+
governments,
41
+
heartlands
42
+
};
+2
-1
tsconfig.json
+2
-1
tsconfig.json
+14
src/utils.ts
+14
src/utils.ts
···
1
+
export interface isocketlib {
2
+
registerModule: (moduleName: string) => Socket
3
+
}
4
+
5
+
export interface Socket {
6
+
register: (name: string, func: (...args: any[]) => any) => void,
7
+
executeAsGM: (handler: string, ...args: any[]) => Promise<any>,
8
+
executeAsUser: (handler: string, userId: string, ...parameters: any[]) => Promise<any>,
9
+
executeForAllGMs: (handler: string, ...parameters: any[]) => Promise<any>,
10
+
executeForOtherGMs: (handler: string, ...parameters: any[]) => Promise<any>,
11
+
executeForEveryone: (handler: string, ...args: any[]) => Promise<any>,
12
+
executeForOthers: (handler: string, ...args: any[]) => Promise<any>,
13
+
executeForUsers: (handler: string, recipients: string[], ...parameters: any[]) => Promise<any>
14
+
}
History
1 round
1 comment
cass.cityboundforest.com
submitted
#0
18 commits
expand
collapse
Moving static files to public folder to be automatically copied to out
Changing module filename to support new filename
Adding sourcemap generation
Adding dotenv build dependency
Adding config loading to change module directory to folder in Foundry folder
Adding in stock data
Moving files out of unnecessary module folder
Adding JSDoc info for the Kingdom class
Renaming governments data file to match naming convention of other files
Adding data into code
Enabling resolving json as modules
Adding in Kingdom data
Adding kingdom classes
Adding some utils to interface typescript with socketlib module
Adding types to socket
Working on registering templates
Fixing some issues with loading socketlib
Fixing label for Kingdom Sheet not showing
expand 1 comment
closed without merging
lol I don't know how to work pulls on here yet