A repository for a FoundryVTT plugin for Kingmaker homebrew.

Adding stuff to the kingdom tab

+333 -32
+146
src/module/kingdom.ts
··· 1 + /** 2 + * A Kingdom structure. 3 + * @typedef {Object} Kingdom 4 + * @property {string} name - The name of the Kingdom 5 + * @property {string} charter - The id of the charter 6 + * @property {string} government - The id of the government 7 + * @property {string} heartland - The id of the heartland 8 + * @property {string[]} boosts - An array of free boosts for the Kingdom 9 + * @property {object} leaders - Leaders of the kingdom. 10 + * @property {string[]} feats - An array of feats for the Kingdom 11 + * @property {number} size - The size of the Kingdom 12 + * @property {object} resourceDice - The resource dice for the Kingdom 13 + * @property {object} commodities - The commodities for the Kingdom 14 + * @property {object} resourcePoints - The resource points for the Kingdom 15 + * @property {object} unrest - The unrest for the Kingdom 16 + * @property {object} ruin - The ruin for the Kingdom 17 + * @property {object[]} groups - Other groups the Kingdom has relations with 18 + * @property {object} krp - The Kingdom Reputation Points 19 + * @property {string[]} settlements - An array of Scene IDs for the Kingdom's settlements 20 + * @property {number} level - The level of the Kingdom 21 + */ 22 + 23 + export class Kingdom { 24 + name: string; 25 + charter: string; 26 + government: string; 27 + heartland: string; 28 + boosts: string[]; 29 + leaders: LeaderInfo; 30 + feats: string[]; 31 + size: number; 32 + resourceDice: ResourceInfo; 33 + commodities: CommodityInfo; 34 + unrest: ResourceLimitInfo; 35 + ruin: RuinInfo; 36 + groups: Relation[]; 37 + krp: ResourceLimitInfo; 38 + settlements: string[]; 39 + level: number; 40 + } 41 + 42 + /** 43 + * Information about a Kingdom's leaders. 44 + * @typedef {Object} LeaderInfo 45 + * @property {string} ruler - The actor ID of the ruler 46 + * @property {string} counselor - The actor ID of the counselor 47 + * @property {string} viceroy - The actor ID of the viceroy 48 + * @property {string} emissary - The actor ID of the emissary 49 + * @property {string} warden - The actor ID of the warden 50 + * @property {stirng} general - The actor ID of the general 51 + * @property {string} magister - The actor ID of the magister 52 + * @property {string} treasurer - The actor ID of the treasurer 53 + */ 54 + 55 + export interface LeaderInfo { 56 + ruler: string; 57 + counselor: string; 58 + viceroy: string; 59 + emissary: string; 60 + warden: string; 61 + general: string; 62 + magister: string; 63 + treasurer: string; 64 + } 65 + 66 + /** 67 + * Information about a resource. This resource has a Next and Current value. 68 + * @typedef {Object} ResourceInfo 69 + * @property {number} next - The amount to add on the next turn. 70 + * @property {number} current - The current value of this resource. 71 + */ 72 + 73 + export interface ResourceInfo { 74 + next: number; 75 + current: number; 76 + } 77 + 78 + /** 79 + * Information about the Kingdom's commodities 80 + * @typedef {Object} CommodityInfo 81 + * @property {object} ore - The amount of Ore the Kingdom has 82 + * @property {object} lumber - The amount of Lumber the Kingdom has 83 + * @property {object} stone - The amount of Stone the Kingdom has 84 + * @property {object} food - The amount of Food the Kingdom has 85 + * @property {object} luxuries - The amount of Luxuries the Kingdom has 86 + */ 87 + 88 + export interface CommodityInfo { 89 + ore: ResourceInfo; 90 + lumber: ResourceInfo; 91 + stone: ResourceInfo; 92 + food: ResourceInfo; 93 + luxuries: ResourceInfo; 94 + } 95 + 96 + /** 97 + * Information about a resource. This resource has Next, Current, and Threshold values. 98 + * @typedef {Object} ResourceLimitInfo 99 + * @property {number} next - The amount to add on the next turn. 100 + * @property {number} current - The current value of this resource. 101 + * @property {number} threshold - The maximum value of this resource. 102 + */ 103 + 104 + export interface ResourceLimitInfo { 105 + next: number; 106 + current: number; 107 + threshold: number; 108 + } 109 + 110 + /** 111 + * Information about the Kingdom's Ruin values. 112 + * @typedef {Object} RuinInfo 113 + * @property {object} corruption - The amount of Corruption a Kingdom has 114 + * @property {object} crime - The amount of Crime a Kingdom has 115 + * @property {object} decay - The amount of Decay a Kingdom has 116 + * @property {object} strife - The amount of Strife a Kingdom has 117 + */ 118 + 119 + export interface RuinInfo { 120 + corruption: ResourceLimitInfo; 121 + crime: ResourceLimitInfo; 122 + decay: ResourceLimitInfo; 123 + strife: ResourceLimitInfo; 124 + } 125 + 126 + /** 127 + * Information about a relation with another group the Kingdom has. 128 + * @typedef {Object} Relation 129 + * @property {string} name - The name of the group 130 + * @property {string} relation - The type of relation the Kingdom has with this group 131 + * @property {number} dc - The base Negotiation DC for this group 132 + * @property {boolean} atWar - Is the Kingdom at war with this group? 133 + */ 134 + 135 + export interface Relation { 136 + name: string; 137 + relation: RelationType; 138 + dc: number; 139 + atWar: boolean; 140 + } 141 + 142 + export enum RelationType { 143 + None = "none", 144 + TradeAgreement = "tradeAgreement", 145 + DiplomaticRelations = "diplomaticRelations", 146 + }
+64 -2
src/module/main.ts
··· 1 1 import { preloadTemplates } from "./preloadTemplates"; 2 2 import { KingdomHomebrew } from "./module"; 3 3 import { Game } from "@league-of-foundry-developers/foundry-vtt-types"; 4 + import { Kingdom } from "./kingdom"; 4 5 5 6 Hooks.on("init", async () => { 6 7 (game as Game)["kingdom-homebrew"] = { 7 - module: KingdomHomebrew 8 + module: KingdomHomebrew, 9 + createBlankKingdom: () => { 10 + game["kingdom-homebrew"].module.createKingdomData(new Kingdom()); 11 + } 8 12 }; 9 13 10 14 await preloadTemplates(); ··· 49 53 tab: "effects", 50 54 name: "Effects" 51 55 } 52 - ] 56 + ], 57 + krpVals: { 58 + 0: "0", 59 + 1: "1", 60 + 2: "2", 61 + 3: "3" 62 + } 53 63 }).then((template) => { 54 64 newSection.innerHTML = template; 55 65 }).catch((err) => { 56 66 console.error(err); 57 67 }); 68 + 69 + const kingdomLevel = (game as Game)["kingdom-homebrew"].module.getKingdomData().level || 0; 70 + 71 + for (var i = 0; i < kingdomLevel; i++) { 72 + document.querySelector(`div[data-kingdom-level="${i + 1}"]`)!.classList.remove("hidden"); 73 + } 58 74 }); 59 75 60 76 Handlebars.registerHelper("getKingdomTab", function (options) { 61 77 return "kingdom-homebrew/kingdom-tab/" + this.tab; 62 78 }); 79 + 80 + Handlebars.registerHelper("for-rev", function (from, to, dec, block) { 81 + var accum = ""; 82 + 83 + for (var i = from; i > to; i -= dec) { 84 + accum += block.fn(i); 85 + } 86 + 87 + return accum; 88 + }); 89 + 90 + Handlebars.registerHelper("for", function (from, to, inc, block) { 91 + var accum = ""; 92 + 93 + for (var i = 0; i < to; i+= inc) { 94 + accum += block.fn(i); 95 + } 96 + 97 + return accum; 98 + }); 99 + 100 + Handlebars.registerHelper("getKingdomLevel", function (options) { 101 + return "kingdom-homebrew/kingdom-level/level-" + this; 102 + }); 103 + 104 + Handlebars.registerHelper("genKRPSelect", function (options) { 105 + var accum = `<select onchange="game['kingdom-homebrew'].module.setKRP${this.next ? "Value" : "Next"}(event)">`; 106 + 107 + accum += Handlebars.helpers.for(0, 4, 1, {fn: (i) => { 108 + return `<option value="${i}">${i}</option>`; 109 + }}); 110 + 111 + accum += "</select>"; 112 + return accum; 113 + }); 114 + 115 + Handlebars.registerHelper("genLevelSelect", function (options) { 116 + var accum = `<select onchange="game['kingdom-homebrew'].module.setLevel(event)">`; 117 + 118 + accum += Handlebars.helpers.for(0, 21, 1, {fn: (i) => { 119 + return `<option value="${i}">${i}</option>`; 120 + }}); 121 + 122 + accum += "</select>"; 123 + return accum; 124 + });
+5 -24
src/module/module.ts
··· 1 + import type { Kingdom } from "./kingdom"; 2 + 1 3 export class KingdomHomebrew { 2 4 static ID: string = "kingdom-homebrew"; 3 5 ··· 9 11 SHEET: `${this.ID}/sheet` 10 12 } 11 13 12 - static getKingdomData() { 13 - return game.actors.get("xxxPF2ExPARTYxxx")?.getFlag(this.ID, this.FLAGS.DATA); 14 + static getKingdomData(): Kingdom { 15 + return game.actors.get("xxxPF2ExPARTYxxx")?.getFlag(this.ID, this.FLAGS.DATA) as Kingdom; 14 16 } 15 17 16 - static createKingdomData(data) { 18 + static createKingdomData(data: Kingdom) { 17 19 return game.actors.get("xxxPF2ExPARTYxxx")?.setFlag(this.ID, this.FLAGS.DATA, data); 18 20 } 19 21 ··· 22 24 document.querySelector(`div.kingdom-tab[data-tab="${event.target.dataset.tab}"]`)!.classList.add("active"); 23 25 } 24 26 } 25 - 26 - /** 27 - * A Kingdom structure. 28 - * @typedef {Object} Kingdom 29 - * @property {string} name - The name of the Kingdom 30 - * @property {string} charter - The id of the charter 31 - * @property {string} government - The id of the government 32 - * @property {string} heartland - The id of the heartland 33 - * @property {string[]} boosts - An array of free boosts for the Kingdom 34 - * @property {object} leaders - Leaders of the kingdom. 35 - * @property {string[]} feats - An array of feats for the Kingdom 36 - * @property {number} size - The size of the Kingdom 37 - * @property {object} resourceDice - The resource dice for the Kingdom 38 - * @property {object} commodities - The commodities for the Kingdom 39 - * @property {object} resourcePoints - The resource points for the Kingdom 40 - * @property {object} unrest - The unrest for the Kingdom 41 - * @property {object} ruin - The ruin for the Kingdom 42 - * @property {object[]} groups - Other groups the Kingdom has relations with 43 - * @property {object} krp - The Kingdom Reputation Points 44 - * @property {string[]} settlements - An array of Scene IDs for the Kingdom's settlements 45 - */
+8 -5
src/module/preloadTemplates.ts
··· 3 3 "kingdom-homebrew/sheet": "modules/kingdom-homebrew/templates/kingdom-sheet.hbs", 4 4 "kingdom-homebrew/kingdom-tab-link": "modules/kingdom-homebrew/templates/kingdom-tab-link.hbs", 5 5 "kingdom-homebrew/kingdom-tab": "modules/kingdom-homebrew/templates/kingdom-tab.hbs", 6 - "kingdom-homebrew/kingdom-tab/turn": "modules/kingdom-homebrew/templates/kingdom-sheet/tab-turn.hbs", 7 - "kingdom-homebrew/kingdom-tab/kingdom": "modules/kingdom-homebrew/templates/kingdom-sheet/tab-kingdom.hbs", 8 - "kingdom-homebrew/kingdom-tab/settlements": "modules/kingdom-homebrew/templates/kingdom-sheet/tab-settlements.hbs", 9 - "kingdom-homebrew/kingdom-tab/relations": "modules/kingdom-homebrew/templates/kingdom-sheet/tab-relations.hbs", 10 - "kingdom-homebrew/kingdom-tab/effects": "modules/kingdom-homebrew/templates/kingdom-sheet/tab-effects.hbs" 11 6 }; 7 + 8 + ["turn", "kingdom", "settlements", "relations", "effects"].forEach((tab) => { 9 + templatePaths["kingdom-homebrew/kingdom-tab/" + tab] = "modules/kingdom-homebrew/templates/kingdom-sheet/tab-" + tab + ".hbs"; 10 + }); 11 + 12 + for (var i = 0; i < 20; i++) { 13 + templatePaths["kingdom-homebrew/kingdom-level/level-" + (i + 1).toString()] = "modules/kingdom-homebrew/templates/kingdom-levels/level-" + (i + 1).toString() + ".hbs"; 14 + } 12 15 13 16 return loadTemplates(templatePaths); 14 17 }
+63
src/styles/kingdom-sheet.css
··· 26 26 27 27 .kingdom-tab { 28 28 display: none; 29 + padding: 10px; 29 30 } 30 31 31 32 .kingdom-tab.active { ··· 35 36 .kingdom-tabs a.active { 36 37 border-bottom: 1px solid black; 37 38 } 39 + 40 + .kingdom-tab-left { 41 + display: flex; 42 + flex-direction: column; 43 + flex: 1; 44 + padding: 0 10px; 45 + } 46 + 47 + .kingdom-tab-right { 48 + display: flex; 49 + flex-direction: column; 50 + flex: 3; 51 + } 52 + 53 + .kingdom-ability-label { 54 + font-weight: bold; 55 + display: flex; 56 + flex: 1; 57 + flex-direction: column; 58 + } 59 + 60 + .kingdom-ability { 61 + display: flex; 62 + flex-direction: column; 63 + flex: 1; 64 + } 65 + 66 + .kingdom-ability-outer { 67 + display: flex; 68 + flex-direction: row; 69 + padding: 5px 0; 70 + } 71 + 72 + .kingdom-tab-right .hidden { 73 + display: none; 74 + } 75 + 76 + .km-flex-col { 77 + flex-direction: column; 78 + } 79 + 80 + .km-flex-row { 81 + flex-direction: row; 82 + } 83 + 84 + .km-flex-1 { 85 + flex: 1; 86 + } 87 + 88 + .km-flex, .km-flex * { 89 + display: flex; 90 + } 91 + 92 + .km-flex input, .km-flex select { 93 + padding: 0 3px; 94 + } 95 + 96 + .km-label { 97 + padding: 0 3px; 98 + vertical-align: middle; 99 + line-height: 2; 100 + }
src/templates/kingdom-levels/level-1.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-10.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-11.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-12.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-13.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-14.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-15.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-16.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-17.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-18.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-19.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-2.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-20.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-3.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-4.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-5.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-6.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-7.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-8.hbs

This is a binary file and will not be displayed.

src/templates/kingdom-levels/level-9.hbs

This is a binary file and will not be displayed.

+47 -1
src/templates/kingdom-sheet/tab-kingdom.hbs
··· 1 - kingdom 1 + <div class="kingdom-tab-left"> 2 + <div class="kingdom-ability-outer"> 3 + <div class="kingdom-ability-label">Loyalty</div> 4 + <span class="kingdom-ability" data-kingdom-ability="loyalty"></span> 5 + </div> 6 + <div class="kingdom-ability-outer"> 7 + <div class="kingdom-ability-label">Culture</div> 8 + <span class="kingdom-ability" data-kingdom-ability="culture"></span> 9 + </div> 10 + <div class="kingdom-ability-outer"> 11 + <div class="kingdom-ability-label">Economy</div> 12 + <span class="kingdom-ability" data-kingdom-ability="economy"></span> 13 + </div> 14 + <div class="kingdom-ability-outer"> 15 + <div class="kingdom-ability-label">Stability</div> 16 + <span class="kingdom-ability" data-kingdom-ability="stability"></span> 17 + </div> 18 + </div> 19 + <div class="kingdom-tab-right"> 20 + <div class="km-flex-row km-flex"> 21 + <div class="km-flex-1 km-flex-row"> 22 + <div class="km-label">Name</div> 23 + <input type="text" onchange="game['kingdom-homebrew'].module.setKingdomName(event)" placeholder="Name" /> 24 + </div> 25 + <div class="km-flex-1 km-flex-row"> 26 + <div class="km-label">KRP</div> 27 + {{#genKRPSelect next=false}}{{/genKRPSelect}} 28 + </div> 29 + <div class="km-flex-1 km-flex-row"> 30 + <div class="km-label">Next</div> 31 + {{#genKRPSelect next=true}}{{/genKRPSelect}} 32 + </div> 33 + <div class="km-flex-1 km-flex-row"> 34 + <div class="km-label">Level</div> 35 + {{#genLevelSelect}}{{/genLevelSelect}} 36 + </div> 37 + <div class="km-flex-1 km-flex-row"> 38 + <div class="km-label">XP</div> 39 + <input type="text" onchange="game['kingdom-homebrew'].module.setKingdomXP(event)" placeholder="0" /> 40 + </div> 41 + </div> 42 + {{#for-rev 20 0 1}} 43 + <div data-kingdom-level="{{this}}" class="hidden"> 44 + {{> (getKingdomLevel this) }} 45 + </div> 46 + {{/for-rev}} 47 + </div>