Upload old System
This commit is contained in:
		
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | MIT License | ||||||
|  |  | ||||||
|  | Copyright (c) 2024 Joscha Maier | ||||||
|  |  | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | of this software and associated documentation files (the "Software"), to deal | ||||||
|  | in the Software without restriction, including without limitation the rights | ||||||
|  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | copies of the Software, and to permit persons to whom the Software is | ||||||
|  | furnished to do so, subject to the following conditions: | ||||||
|  |  | ||||||
|  | The above copyright notice and this permission notice shall be included in all | ||||||
|  | copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  | SOFTWARE. | ||||||
							
								
								
									
										25
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | MIT License | ||||||
|  |  | ||||||
|  | Copyright (c) 2020 Asacolips Projects / Foundry Mods | ||||||
|  |  | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | of this software and associated documentation files (the "Software"), to deal | ||||||
|  | in the Software without restriction, including without limitation the rights | ||||||
|  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | copies of the Software, and to permit persons to whom the Software is | ||||||
|  | furnished to do so, subject to the following conditions: | ||||||
|  |  | ||||||
|  | The above copyright notice and this permission notice shall be included in all | ||||||
|  | copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  | This license does not apply to the compendium content listed in this software's | ||||||
|  | "packs" directory. See the README for licensing information for the compendium | ||||||
|  | packs. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  | SOFTWARE. | ||||||
							
								
								
									
										423
									
								
								css/kidsonbrooms.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										423
									
								
								css/kidsonbrooms.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,423 @@ | |||||||
|  | @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap"); | ||||||
|  | /* Global styles */ | ||||||
|  | @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap"); | ||||||
|  | .window-app { | ||||||
|  |   font-family: "Roboto", sans-serif; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .rollable:hover, .rollable:focus { | ||||||
|  |   color: #000; | ||||||
|  |   text-shadow: 0 0 10px rgb(146, 0, 225); | ||||||
|  |   cursor: pointer; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid { | ||||||
|  |   display: grid; | ||||||
|  |   gap: 10px; | ||||||
|  |   margin: 10px 0; | ||||||
|  |   padding: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-start-2 { | ||||||
|  |   grid-column-start: 2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-span-2 { | ||||||
|  |   grid-column-end: span 2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-2col { | ||||||
|  |   grid-column: span 2/span 2; | ||||||
|  |   grid-template-columns: repeat(2, minmax(0, 1fr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-start-3 { | ||||||
|  |   grid-column-start: 3; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-span-3 { | ||||||
|  |   grid-column-end: span 3; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-3col { | ||||||
|  |   grid-column: span 3/span 3; | ||||||
|  |   grid-template-columns: repeat(3, minmax(0, 1fr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-start-4 { | ||||||
|  |   grid-column-start: 4; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-span-4 { | ||||||
|  |   grid-column-end: span 4; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-4col { | ||||||
|  |   grid-column: span 4/span 4; | ||||||
|  |   grid-template-columns: repeat(4, minmax(0, 1fr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-start-5 { | ||||||
|  |   grid-column-start: 5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-span-5 { | ||||||
|  |   grid-column-end: span 5; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-5col { | ||||||
|  |   grid-column: span 5/span 5; | ||||||
|  |   grid-template-columns: repeat(5, minmax(0, 1fr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-start-6 { | ||||||
|  |   grid-column-start: 6; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-span-6 { | ||||||
|  |   grid-column-end: span 6; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-6col { | ||||||
|  |   grid-column: span 6/span 6; | ||||||
|  |   grid-template-columns: repeat(6, minmax(0, 1fr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-start-7 { | ||||||
|  |   grid-column-start: 7; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-span-7 { | ||||||
|  |   grid-column-end: span 7; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-7col { | ||||||
|  |   grid-column: span 7/span 7; | ||||||
|  |   grid-template-columns: repeat(7, minmax(0, 1fr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-start-8 { | ||||||
|  |   grid-column-start: 8; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-span-8 { | ||||||
|  |   grid-column-end: span 8; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-8col { | ||||||
|  |   grid-column: span 8/span 8; | ||||||
|  |   grid-template-columns: repeat(8, minmax(0, 1fr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-start-9 { | ||||||
|  |   grid-column-start: 9; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-span-9 { | ||||||
|  |   grid-column-end: span 9; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-9col { | ||||||
|  |   grid-column: span 9/span 9; | ||||||
|  |   grid-template-columns: repeat(9, minmax(0, 1fr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-start-10 { | ||||||
|  |   grid-column-start: 10; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-span-10 { | ||||||
|  |   grid-column-end: span 10; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-10col { | ||||||
|  |   grid-column: span 10/span 10; | ||||||
|  |   grid-template-columns: repeat(10, minmax(0, 1fr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-start-11 { | ||||||
|  |   grid-column-start: 11; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-span-11 { | ||||||
|  |   grid-column-end: span 11; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-11col { | ||||||
|  |   grid-column: span 11/span 11; | ||||||
|  |   grid-template-columns: repeat(11, minmax(0, 1fr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-start-12 { | ||||||
|  |   grid-column-start: 12; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-span-12 { | ||||||
|  |   grid-column-end: span 12; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid-12col { | ||||||
|  |   grid-column: span 12/span 12; | ||||||
|  |   grid-template-columns: repeat(12, minmax(0, 1fr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flex-group-center { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: center; | ||||||
|  |   flex-wrap: center; | ||||||
|  |   justify-content: flex-start; | ||||||
|  |   align-items: stretch; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flex-group-left { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: flex-start; | ||||||
|  |   flex-wrap: center; | ||||||
|  |   justify-content: flex-start; | ||||||
|  |   align-items: stretch; | ||||||
|  |   text-align: left; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flex-group-right { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: flex-end; | ||||||
|  |   flex-wrap: center; | ||||||
|  |   justify-content: flex-start; | ||||||
|  |   align-items: stretch; | ||||||
|  |   text-align: right; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flexshrink { | ||||||
|  |   flex: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flex-between { | ||||||
|  |   justify-content: space-between; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flexlarge { | ||||||
|  |   flex: 2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .align-left { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: flex-start; | ||||||
|  |   flex-wrap: center; | ||||||
|  |   justify-content: flex-start; | ||||||
|  |   align-items: stretch; | ||||||
|  |   text-align: left; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .align-right { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: flex-end; | ||||||
|  |   flex-wrap: center; | ||||||
|  |   justify-content: flex-start; | ||||||
|  |   align-items: stretch; | ||||||
|  |   text-align: right; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .align-center { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: center; | ||||||
|  |   flex-wrap: center; | ||||||
|  |   justify-content: flex-start; | ||||||
|  |   align-items: stretch; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .right-align-input { | ||||||
|  |   flex: 1; | ||||||
|  |   margin-left: auto; | ||||||
|  |   max-width: 260px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .window-app { | ||||||
|  |   font-family: "Roboto", sans-serif; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .rollable:hover, .rollable:focus { | ||||||
|  |   color: #000; | ||||||
|  |   text-shadow: 0 0 10px rgb(179, 7, 217); | ||||||
|  |   cursor: pointer; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Styles limited to kidsonbrooms sheets */ | ||||||
|  | .kids-on-brooms .item-form { | ||||||
|  |   font-family: "Roboto", sans-serif; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .sheet-header { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: row; | ||||||
|  |   flex-wrap: wrap; | ||||||
|  |   justify-content: flex-start; | ||||||
|  |   align-items: stretch; | ||||||
|  |   flex: 0 auto; | ||||||
|  |   overflow: hidden; | ||||||
|  |   margin-bottom: 10px; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .sheet-header .profile-img { | ||||||
|  |   flex: 0 0 100px; | ||||||
|  |   height: 100px; | ||||||
|  |   margin-right: 10px; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .sheet-header .header-fields { | ||||||
|  |   flex: 1; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .sheet-header h1.charname { | ||||||
|  |   height: 50px; | ||||||
|  |   padding: 0; | ||||||
|  |   margin: 5px 0; | ||||||
|  |   border-bottom: 0; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .sheet-header h1.charname input { | ||||||
|  |   width: 100%; | ||||||
|  |   height: 100%; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  | .kids-on-brooms div.editor-border { | ||||||
|  |   border: 2px solid rgb(81, 81, 81); | ||||||
|  |   border-radius: 10px; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .sheet-tabs { | ||||||
|  |   flex: 0; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .sheet-body, | ||||||
|  | .kids-on-brooms .sheet-body .tab, | ||||||
|  | .kids-on-brooms .sheet-body .tab .editor { | ||||||
|  |   height: 100%; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .tox .tox-editor-container { | ||||||
|  |   background: #fff; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .tox .tox-edit-area { | ||||||
|  |   padding: 0 8px; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .selection-row { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   margin-bottom: 10px; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .resource-label { | ||||||
|  |   font-weight: bold; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-header { | ||||||
|  |   height: 28px; | ||||||
|  |   margin: 2px 0; | ||||||
|  |   padding: 0; | ||||||
|  |   align-items: center; | ||||||
|  |   background: rgba(0, 0, 0, 0.05); | ||||||
|  |   border: 2px groove #eeede0; | ||||||
|  |   font-weight: bold; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-header > * { | ||||||
|  |   font-size: 14px; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-header .item-name { | ||||||
|  |   font-weight: bold; | ||||||
|  |   padding-left: 5px; | ||||||
|  |   text-align: left; | ||||||
|  |   display: flex; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list { | ||||||
|  |   list-style: none; | ||||||
|  |   margin: 0; | ||||||
|  |   padding: 0; | ||||||
|  |   overflow-y: auto; | ||||||
|  |   scrollbar-width: thin; | ||||||
|  |   color: #444; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .item-list { | ||||||
|  |   list-style: none; | ||||||
|  |   margin: 0; | ||||||
|  |   padding: 0; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .item { | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   padding: 0 2px; | ||||||
|  |   border-bottom: 1px solid #c9c7b8; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .item:last-child { | ||||||
|  |   border-bottom: none; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .item .item-name { | ||||||
|  |   flex: 2; | ||||||
|  |   margin: 0; | ||||||
|  |   overflow: hidden; | ||||||
|  |   font-size: 13px; | ||||||
|  |   text-align: left; | ||||||
|  |   display: flex; | ||||||
|  |   color: #191813; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .item .item-name h3, .kids-on-brooms .items-list .item .item-name h4 { | ||||||
|  |   margin: 0; | ||||||
|  |   white-space: nowrap; | ||||||
|  |   overflow-x: hidden; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .item .item-name .item-image { | ||||||
|  |   flex: 0 0 30px; | ||||||
|  |   height: 30px; | ||||||
|  |   background-size: 30px; | ||||||
|  |   border: none; | ||||||
|  |   margin-right: 5px; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .item-controls { | ||||||
|  |   display: flex; | ||||||
|  |   flex: 0 0 100px; | ||||||
|  |   justify-content: flex-end; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .item-controls a { | ||||||
|  |   font-size: 12px; | ||||||
|  |   text-align: center; | ||||||
|  |   margin: 0 6px; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .item-prop { | ||||||
|  |   text-align: center; | ||||||
|  |   border-left: 1px solid #c9c7b8; | ||||||
|  |   border-right: 1px solid #c9c7b8; | ||||||
|  |   font-size: 12px; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .items-header { | ||||||
|  |   height: 28px; | ||||||
|  |   margin: 2px 0; | ||||||
|  |   padding: 0; | ||||||
|  |   align-items: center; | ||||||
|  |   background: rgba(0, 0, 0, 0.05); | ||||||
|  |   border: 2px groove #eeede0; | ||||||
|  |   font-weight: bold; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .items-header > * { | ||||||
|  |   font-size: 12px; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .items-list .items-header .item-name { | ||||||
|  |   padding-left: 5px; | ||||||
|  |   text-align: left; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .item-formula { | ||||||
|  |   flex: 0 0 200px; | ||||||
|  |   padding: 0 8px; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .effects .item .effect-source, | ||||||
|  | .kids-on-brooms .effects .item .effect-duration, | ||||||
|  | .kids-on-brooms .effects .item .effect-controls { | ||||||
|  |   text-align: center; | ||||||
|  |   border-left: 1px solid #c9c7b8; | ||||||
|  |   border-right: 1px solid #c9c7b8; | ||||||
|  |   font-size: 12px; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .effects .item .effect-controls { | ||||||
|  |   border: none; | ||||||
|  | } | ||||||
|  | .kids-on-brooms .kids-on-brooms input:focus, | ||||||
|  | .kids-on-brooms .kids-on-brooms textarea:focus, | ||||||
|  | .kids-on-brooms .kids-on-brooms select:focus { | ||||||
|  |   outline: none; | ||||||
|  |   border-color: #8102dd; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*# sourceMappingURL=kidsonbrooms.css.map */ | ||||||
							
								
								
									
										1
									
								
								css/kidsonbrooms.css.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								css/kidsonbrooms.css.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | {"version":3,"sourceRoot":"","sources":["../scss/kidsonbrooms.scss","../scss/global/_base.scss","../scss/global/_window.scss","../scss/utils/_typography.scss","../scss/global/_grid.scss","../scss/global/_flex.scss","../scss/utils/_mixins.scss","../scss/utils/_variables.scss","../scss/components/_forms.scss","../scss/utils/_colors.scss","../scss/components/_resource.scss","../scss/components/_items.scss","../scss/components/_effects.scss"],"names":[],"mappings":"AACQ;AASR;ACTQ;ACDR;EACE,aCDa;;;ADKb;EAEE;EACA;EACA;;;AERJ;EACE;EACA;EACA;EACA;;;AAKA;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;ACrBJ;ECkBE;EACA,gBDlBiB;ECmBjB,WDnByB;ECoBzB,iBAJkD;EAKlD,aALsE;EDftE;;;AAGF;ECaE;EACA,gBDbiB;ECcjB,WDd6B;ECe7B,iBAJkD;EAKlD,aALsE;EDVtE;;;AAGF;ECQE;EACA,gBDRiB;ECSjB,WDT2B;ECU3B,iBAJkD;EAKlD,aALsE;EDLtE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAIF;ECVE;EACA,gBDUiB;ECTjB,WDS6B;ECR7B,iBAJkD;EAKlD,aALsE;EDatE;;;AAGF;ECfE;EACA,gBDeiB;ECdjB,WDc2B;ECb3B,iBAJkD;EAKlD,aALsE;EDkBtE;;;AAGF;ECpBE;EACA,gBDoBiB;ECnBjB,WDmByB;EClBzB,iBAJkD;EAKlD,aALsE;EDuBtE;;;AAIF;EACE;EACA;EACA;;;AJ7CF;EACE,aMEW;;;ANEX;EAEE;EACA;EACA;;;ADIJ;AQhBA;EACE,aLDa;;AKIf;EFeE;EACA,gBEfiB;EFgBjB,WEhBsB;EFiBtB,iBEjB4B;EFkB5B,aALsE;EEZtE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAKN;EACE;EACA;;AAGF;EACE;;AAGF;AAAA;AAAA;EAGE;;AAIA;EACE,YCnDM;;ADsDR;EACE;;AAKJ;EACE;EACA;EACA;EACA;;AEhEF;EACE;;ACAF;EACE;EACA;EACA;EACA;EACA;EACA,QJHc;EIId;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;EACA;EACA,OFxBM;;AE2BN;EACE;EACA;EACA;;AAIF;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAIF;EACE;EACA;EACA;EACA;EACA;EACA;EACA,OFvDG;;AEyDH;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAMN;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;EACA;EACA,QJrGc;EIsGd;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAKJ;EACE;EACA;;ACzHA;AAAA;AAAA;EAGE;EACA;EACA;EACA;;AAGF;EACE;;AAKJ;AAAA;AAAA;EAGE;EACA,cHVmB","file":"kidsonbrooms.css"} | ||||||
							
								
								
									
										1
									
								
								css/test.css.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								css/test.css.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | {"version":3,"sourceRoot":"","sources":["../scss/kidsonbrooms.scss","../scss/global/_base.scss","../scss/global/_window.scss","../scss/utils/_typography.scss","../scss/global/_grid.scss","../scss/global/_flex.scss","../scss/utils/_mixins.scss","../scss/utils/_variables.scss","../scss/components/_forms.scss","../scss/utils/_colors.scss","../scss/components/_resource.scss","../scss/components/_items.scss","../scss/components/_effects.scss"],"names":[],"mappings":"AACQ;AASR;ACTQ;ACDR;EACE,aCDa;;;ADKb;EAEE;EACA;EACA;;;AERJ;EACE;EACA;EACA;EACA;;;AAKA;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;AAZF;EACE;;;AAIF;EACE;;;AAIF;EACE;EACA;;;ACrBJ;ECkBE;EACA,gBDlBiB;ECmBjB,WDnByB;ECoBzB,iBAJkD;EAKlD,aALsE;EDftE;;;AAGF;ECaE;EACA,gBDbiB;ECcjB,WDd6B;ECe7B,iBAJkD;EAKlD,aALsE;EDVtE;;;AAGF;ECQE;EACA,gBDRiB;ECSjB,WDT2B;ECU3B,iBAJkD;EAKlD,aALsE;EDLtE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAIF;ECVE;EACA,gBDUiB;ECTjB,WDS6B;ECR7B,iBAJkD;EAKlD,aALsE;EDatE;;;AAGF;ECfE;EACA,gBDeiB;ECdjB,WDc2B;ECb3B,iBAJkD;EAKlD,aALsE;EDkBtE;;;AAGF;ECpBE;EACA,gBDoBiB;ECnBjB,WDmByB;EClBzB,iBAJkD;EAKlD,aALsE;EDuBtE;;;AJtCF;EACE,aMEW;;;ANEX;EAEE;EACA;EACA;;;ADIJ;AQhBA;EACE,aLDa;;AKIf;EFeE;EACA,gBEfiB;EFgBjB,WEhBsB;EFiBtB,iBEjB4B;EFkB5B,aALsE;EEZtE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAKN;EACE;EACA;;AAGF;EACE;;AAGF;AAAA;AAAA;EAGE;;AAIA;EACE,YCnDM;;ADsDR;EACE;;AEvDJ;EACE;;ACAF;EACE;EACA;EACA;EACA;EACA;EACA,QJHc;EIId;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;EACA;EACA,OFxBM;;AE2BN;EACE;EACA;EACA;;AAIF;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAIF;EACE;EACA;EACA;EACA;EACA;EACA;EACA,OFvDG;;AEyDH;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAMN;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;EACA;EACA,QJrGc;EIsGd;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAKJ;EACE;EACA;;ACzHA;AAAA;AAAA;EAGE;EACA;EACA;EACA;;AAGF;EACE;;AAKJ;AAAA;AAAA;EAGE;EACA,cHVmB","file":"test.css"} | ||||||
							
								
								
									
										9
									
								
								lang/en.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								lang/en.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | { | ||||||
|  |  | ||||||
|  |   "KIDSONBROOMS.EffectCreate": "Create Effect", | ||||||
|  |   "KIDSONBROOMS.EffectToggle": "Toggle Effect", | ||||||
|  |   "KIDSONBROOMS.EffectEdit": "Edit Effect", | ||||||
|  |   "KIDSONBROOMS.EffectDelete": "Delete Effect", | ||||||
|  |  | ||||||
|  |   "KIDSONBROOMS.Add": "Add" | ||||||
|  | } | ||||||
							
								
								
									
										0
									
								
								lib/some-lib/some-lib.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								lib/some-lib/some-lib.css
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								lib/some-lib/some-lib.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								lib/some-lib/some-lib.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										59
									
								
								module/documents/actor.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								module/documents/actor.mjs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | /** | ||||||
|  |  * Extend the base Actor document by defining a custom roll data structure which is ideal for the Simple system. | ||||||
|  |  * @extends {Actor} | ||||||
|  |  */ | ||||||
|  | export class KidsOnBroomsActor extends Actor { | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Override getRollData() that's supplied to rolls. | ||||||
|  |    */ | ||||||
|  |   getRollData() { | ||||||
|  |     let data = { ...this.system }; | ||||||
|  |    | ||||||
|  |     // Wand bonuses | ||||||
|  |     data.wandBonus = { | ||||||
|  |       wood: this._getWandBonus(this.system.wand.wood), | ||||||
|  |       core: this._getWandBonus(this.system.wand.core) | ||||||
|  |     }; | ||||||
|  |    | ||||||
|  |     return data; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   _getWandBonus(type) { | ||||||
|  |     const bonuses = { | ||||||
|  |       "Wisteria": { stat: "brains", bonus: 1 }, | ||||||
|  |       "Hawthorn": { stat: "brains", bonus: 1 }, | ||||||
|  |       "Pine": { stat: "brawn", bonus: 1 }, | ||||||
|  |       "Oak": { stat: "brawn", bonus: 1 }, | ||||||
|  |       "Crabapple": { stat: "fight", bonus: 1 }, | ||||||
|  |       "Dogwood": { stat: "fight", bonus: 1 }, | ||||||
|  |       "Birch": { stat: "flight", bonus: 1 }, | ||||||
|  |       "Bamboo": { stat: "flight", bonus: 1 }, | ||||||
|  |       "Ironwood": { stat: "grit", bonus: 1 }, | ||||||
|  |       "Maple": { stat: "grit", bonus: 1 }, | ||||||
|  |       "Lilac": { stat: "charm", bonus: 1 }, | ||||||
|  |       "Cherry": { stat: "charm", bonus: 1 }, | ||||||
|  |       "Parchment": { stat: "brains", bonus: 1 }, | ||||||
|  |       "Phoenix Feather": { stat: "brains", bonus: 1 }, | ||||||
|  |       "Owl Feather": { stat: "brains", bonus: 1 }, | ||||||
|  |       "Gorilla Fur": { stat: "brawn", bonus: 1 }, | ||||||
|  |       "Ogre’s Fingernail": { stat: "brawn", bonus: 1 }, | ||||||
|  |       "Hippo’s Tooth": { stat: "brawn", bonus: 1 }, | ||||||
|  |       "Dragon’s Heartstring": { stat: "fight", bonus: 1 }, | ||||||
|  |       "Wolf’s Tooth": { stat: "fight", bonus: 1 }, | ||||||
|  |       "Elk’s Antler": { stat: "fight", bonus: 1 }, | ||||||
|  |       "Hawk’s Feather": { stat: "flight", bonus: 1 }, | ||||||
|  |       "Bat’s Bone": { stat: "flight", bonus: 1 }, | ||||||
|  |       "Changeling’s Hair": { stat: "charm", bonus: 1 }, | ||||||
|  |       "Gold": { stat: "charm", bonus: 1 }, | ||||||
|  |       "Mirror": { stat: "charm", bonus: 1 }, | ||||||
|  |       "Steel": { stat: "grit", bonus: 1 }, | ||||||
|  |       "Diamond": { stat: "grit", bonus: 1 }, | ||||||
|  |       "Lion’s Mane": { stat: "grit", bonus: 1 } | ||||||
|  |     }; | ||||||
|  |    | ||||||
|  |     return bonuses[type] || { stat: "", bonus: 0 }; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								module/helpers/config.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								module/helpers/config.mjs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | export const KIDSONBROOMS = {}; | ||||||
|  |  | ||||||
|  | // Define constants here, such as: | ||||||
|  | KIDSONBROOMS.foobar = { | ||||||
|  |   'bas': 'KIDSONBROOMS.bas', | ||||||
|  |   'bar': 'KIDSONBROOMS.bar' | ||||||
|  | }; | ||||||
							
								
								
									
										15
									
								
								module/helpers/templates.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								module/helpers/templates.mjs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | /** | ||||||
|  |  * Define a set of template paths to pre-load | ||||||
|  |  * Pre-loaded templates are compiled and cached for fast access when rendering | ||||||
|  |  * @return {Promise} | ||||||
|  |  */ | ||||||
|  |  export const preloadHandlebarsTemplates = async function() { | ||||||
|  |   return loadTemplates([ | ||||||
|  |  | ||||||
|  |     // Actor partials. | ||||||
|  |     "systems/kids-on-brooms/templates/actor/parts/actor-features.html", | ||||||
|  |     "systems/kids-on-brooms/templates/actor/parts/actor-adversity.html", | ||||||
|  |     "systems/kids-on-brooms/templates/actor/parts/actor-stats.html", | ||||||
|  |     "systems/kids-on-brooms/templates/actor/parts/actor-npc-stats.html", | ||||||
|  |   ]); | ||||||
|  | }; | ||||||
							
								
								
									
										333
									
								
								module/kidsonbrooms.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								module/kidsonbrooms.mjs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,333 @@ | |||||||
|  | // Import document classes. | ||||||
|  | import { KidsOnBroomsActor } from "./documents/actor.mjs"; | ||||||
|  |  | ||||||
|  | // Import sheet classes. | ||||||
|  | import { KidsOnBroomsActorSheet } from "./sheets/actor-sheet.mjs"; | ||||||
|  |  | ||||||
|  | // Import helper/utility classes and constants. | ||||||
|  | import { preloadHandlebarsTemplates } from "./helpers/templates.mjs"; | ||||||
|  | import { KIDSONBROOMS } from "./helpers/config.mjs"; | ||||||
|  |  | ||||||
|  | /* -------------------------------------------- */ | ||||||
|  | /*  Init Hook                                   */ | ||||||
|  | /* -------------------------------------------- */ | ||||||
|  |  | ||||||
|  | Hooks.once('init', async function() { | ||||||
|  |  | ||||||
|  |   // Register the helper | ||||||
|  |   Handlebars.registerHelper('capitalizeFirst', function(string) { | ||||||
|  |     if (typeof string === 'string') { | ||||||
|  |       return string.charAt(0).toUpperCase() + string.slice(1); | ||||||
|  |     } | ||||||
|  |     return ''; | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   // Add utility classes and functions to the global game object so that they're more easily | ||||||
|  |   // accessible in global contexts. | ||||||
|  |   game.kidsonbrooms = { | ||||||
|  |     KidsOnBroomsActor, | ||||||
|  |     _onTakeAdversityToken: _onTakeAdversityToken,  // Add the function to the global object | ||||||
|  |     _onSpendAdversityTokens: _onSpendAdversityTokens  // Add the function to the global object | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   // Add custom constants for configuration. | ||||||
|  |   CONFIG.KIDSONBROOMS = KIDSONBROOMS; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Set an initiative formula for the system | ||||||
|  |    * @type {String} | ||||||
|  |    */ | ||||||
|  |   CONFIG.Combat.initiative = { | ||||||
|  |     formula: "1d20", | ||||||
|  |     decimals: 2 | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   // Define custom Document classes | ||||||
|  |   CONFIG.Actor.documentClass = KidsOnBroomsActor; | ||||||
|  |  | ||||||
|  |   // Register sheet application classes | ||||||
|  |   Actors.unregisterSheet("core", ActorSheet); | ||||||
|  |   Actors.registerSheet("kids-on-brooms", KidsOnBroomsActorSheet, { makeDefault: true }); | ||||||
|  |  | ||||||
|  |   //If there is a new chat message that is a roll we add the adversity token controls | ||||||
|  |   Hooks.on("renderChatMessage", (message, html, messageData) => { | ||||||
|  |     const adversityControls = html.find('.adversity-controls'); | ||||||
|  |     if (adversityControls.length > 0) { | ||||||
|  |       const messageToEdit = adversityControls.data("roll-id"); | ||||||
|  |       // Bind event listeners for the controls | ||||||
|  |       adversityControls.find(".take-adversity").off("click").click((event) => { | ||||||
|  |  | ||||||
|  |         const actorId = event.currentTarget.dataset.actorId; | ||||||
|  |         const actor = game.actors.get(actorId); | ||||||
|  |        | ||||||
|  |         // Check if the current user owns the actor - They can not claim if they are not | ||||||
|  |         if (!actor.testUserPermission(game.user, "owner")) { | ||||||
|  |           ui.notifications.warn("You don't own this character and cannot take adversity tokens."); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Check if the token has already been claimed -- Contigency if the button somehow activates again | ||||||
|  |         if (message.getFlag("kids-on-brooms", "tokenClaimed")) { | ||||||
|  |           ui.notifications.warn("This adversity token has already been claimed."); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         _onTakeAdversityToken(event, actor); | ||||||
|  |         if (game.user.isGM) { | ||||||
|  |           let tokenControls = game.messages.get(message.id); | ||||||
|  |           console.log(tokenControls); | ||||||
|  |           // Update the chat message content with the button disabled and text changed | ||||||
|  |           const updatedContent = tokenControls.content.replace( | ||||||
|  |             `<button class="take-adversity" data-actor-id="${actor.id}">Take Adversity Token</button>`, | ||||||
|  |             `<button class="take-adversity" data-actor-id="${actor.id}" disabled>Token claimed</button>` | ||||||
|  |           ); | ||||||
|  |           console.log("Removing Button"); | ||||||
|  |           // Update the message content | ||||||
|  |           tokenControls.update({ content: updatedContent }); | ||||||
|  |           // Set the flag on the chat message to indicate that the token has been claimed | ||||||
|  |           tokenControls.setFlag("kids-on-brooms", "tokenClaimed", true); | ||||||
|  |         } else { | ||||||
|  |           // Emit a socket request to update the message to show that the token has been claimed | ||||||
|  |           game.socket.emit('system.kids-on-brooms', { | ||||||
|  |             action: "takeToken", | ||||||
|  |             messageID: message.id, | ||||||
|  |             actorID: actor.id, | ||||||
|  |           }); | ||||||
|  |         } | ||||||
|  |         console.log("Send socket message for taking a token"); | ||||||
|  |       }); | ||||||
|  |    | ||||||
|  |       adversityControls.find(".spend-adversity").off("click").click((event) => { | ||||||
|  |         //This entails a lot more, so I offloaded it to a new function | ||||||
|  |         _onSpendAdversityTokens(event, messageToEdit); | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |  | ||||||
|  |    | ||||||
|  |    | ||||||
|  |  | ||||||
|  |   // Preload Handlebars templates. | ||||||
|  |   return preloadHandlebarsTemplates(); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | /*** | ||||||
|  |  * This handles the incoming socket requests.  | ||||||
|  |  * If a player wants to spend tokens on another players roll the gm has to approve first | ||||||
|  |  * if a player wants to claim a token we will update the message since they do not have the permissions | ||||||
|  |  */ | ||||||
|  | Hooks.once('ready', function() { | ||||||
|  |   game.socket.on('system.kids-on-brooms', async (data) => { | ||||||
|  |     console.log("Socket data received:", data); | ||||||
|  |  | ||||||
|  |     if (data.action === "spendTokens") { | ||||||
|  |       console.log(`Request to spend tokens: ${data.tokensToSpend} tokens for ${data.rollActorId} by ${data.spendingActorId}`); | ||||||
|  |  | ||||||
|  |       // Only handle the request if the GM is logged in | ||||||
|  |       if (!game.user.isGM) { | ||||||
|  |         console.log("Not GM, ignoring the token spend request."); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // The actor who made the roll | ||||||
|  |       const rollActor = game.actors.get(data.rollActorId);   | ||||||
|  |       // The actor who is spending tokens | ||||||
|  |       const spendingActor = game.actors.get(data.spendingActorId);   | ||||||
|  |  | ||||||
|  |       //If these for some reason do not exist | ||||||
|  |       if (!rollActor || !spendingActor) { | ||||||
|  |         console.warn("Actor not found:", data.rollActorId, data.spendingActorId); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // Create a confirmation dialog for the GM | ||||||
|  |       new Dialog({ | ||||||
|  |         title: "Approve Adversity Token Spending?", | ||||||
|  |         content: `<p>${spendingActor.name} wants to spend ${data.tokenCost} adversity tokens on ${rollActor.name}'s roll to increase it by ${data.tokensToSpend}. Approve?</p>`, | ||||||
|  |         buttons: { | ||||||
|  |           yes: { | ||||||
|  |             label: "Yes", | ||||||
|  |             callback: async () => { | ||||||
|  |  | ||||||
|  |                | ||||||
|  |               const currentTokens = spendingActor.system.adversityTokens || 0; | ||||||
|  |  | ||||||
|  |               // Update the spending actor's adversity token count | ||||||
|  |               await spendingActor.update({ "system.adversityTokens": currentTokens - data.tokenCost }); | ||||||
|  |  | ||||||
|  |                | ||||||
|  |               // Modify the roll message with the new total | ||||||
|  |               await _updateRollMessage(data.rollMessageId, data.tokensToSpend, false); | ||||||
|  |  | ||||||
|  |               console.log(`${spendingActor.name} spent ${data.tokensToSpend} tokens, updated roll total to ${roll.cumulativeTotal}`); | ||||||
|  |               ui.notifications.info(`${spendingActor.name} successfully spent ${data.tokensToSpend} tokens.`); | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           no: { | ||||||
|  |             label: "No", | ||||||
|  |             callback: () => { | ||||||
|  |               ui.notifications.info(`The GM denied ${spendingActor.name}'s request to spend tokens.`); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         default: "yes" | ||||||
|  |       }).render(true); | ||||||
|  |     } else if (data.action === "takeToken") { | ||||||
|  |       // Only handle the request if the GM is logged in | ||||||
|  |       if (!game.user.isGM) { | ||||||
|  |         console.log("Not GM, ignoring the token spend request."); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       let tokenControls = game.messages.get(data.messageID); | ||||||
|  |       console.log(tokenControls); | ||||||
|  |       // Update the chat message content with the button disabled and text changed | ||||||
|  |       const updatedContent = tokenControls.content.replace( | ||||||
|  |         `<button class="take-adversity" data-actor-id="${data.actorID}">Take Adversity Token</button>`, | ||||||
|  |         `<button class="take-adversity" data-actor-id="${data.actorID}" disabled>Token claimed</button>` | ||||||
|  |       ); | ||||||
|  |       console.log("Removing Button"); | ||||||
|  |       // Update the message content | ||||||
|  |       tokenControls.update({ content: updatedContent }); | ||||||
|  |       // Set the flag on the chat message to indicate that the token has been claimed | ||||||
|  |       tokenControls.setFlag("kids-on-brooms", "tokenClaimed", true); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | /*** | ||||||
|  |  * This function adds the adversity token to the actor that made the roll and logs it | ||||||
|  |  *  | ||||||
|  |  * @param {Event} e - The button click event | ||||||
|  |  * @param {Actor} actor - The actor object that made the roll   | ||||||
|  |  */ | ||||||
|  | async function _onTakeAdversityToken(e, actor) { | ||||||
|  |   e.preventDefault(); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   // Get the chat message ID (assuming it's stored in the dataset) | ||||||
|  |   const messageId = e.currentTarget.closest('.message').dataset.messageId; | ||||||
|  |   const message = game.messages.get(messageId); | ||||||
|  |  | ||||||
|  |   // Add an adversity token to the actor | ||||||
|  |   const currentTokens = actor.system.adversityTokens || 0; | ||||||
|  |   await actor.update({ "system.adversityTokens": currentTokens + 1 }); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   // Notify the user | ||||||
|  |   ui.notifications.info(`You gained 1 adversity token.`); | ||||||
|  |   console.log(`Gave one adversity token to ${actor.id}`) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /*** | ||||||
|  |  * This function allows players to spend tokens to change a roll. This will automatically be calculated in their sheet | ||||||
|  |  *  | ||||||
|  |  */ | ||||||
|  | async function _onSpendAdversityTokens(e, rollMessageId) { | ||||||
|  |   e.preventDefault(); | ||||||
|  |    | ||||||
|  |    // The actor who made the roll | ||||||
|  |   const rollActorId = e.currentTarget.dataset.actorId; | ||||||
|  |   const rollActor = game.actors.get(rollActorId); //technically redundant since it is also done in the main hook, but perfomance is good enuff | ||||||
|  |  | ||||||
|  |   // Get the actor of the player who is spending tokens | ||||||
|  |   const spendingPlayerActor = game.actors.get(game.user.character?.id || game.actors.filter(actor => actor.testUserPermission(game.user, "owner"))[0]?.id); | ||||||
|  |  | ||||||
|  |   if (!spendingPlayerActor) { | ||||||
|  |     ui.notifications.warn("You don't control any actors."); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   //Get the tokens to be spend from the input field | ||||||
|  |   const tokenInput = $(e.currentTarget).closest('.adversity-controls').find('.token-input').val(); | ||||||
|  |   const tokensToSpend = parseInt(tokenInput, 10); | ||||||
|  |  | ||||||
|  |   if (isNaN(tokensToSpend) || tokensToSpend <= 0) { | ||||||
|  |     ui.notifications.warn("Please enter a valid number of tokens."); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   let tokenCost = tokensToSpend; | ||||||
|  |  | ||||||
|  |   // If the player spending tokens is not the owner of the actor who rolled, they spend double  | ||||||
|  |   //(note, this is a rule of mine, I have disabled it by default) | ||||||
|  |   if ((!spendingPlayerActor.testUserPermission(game.user, "owner") || spendingPlayerActor.id !== rollActorId) && false) { | ||||||
|  |     tokenCost = tokensToSpend * 2; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Ensure the spending actor has enough adversity tokens  | ||||||
|  |   if (spendingPlayerActor.system.adversityTokens < tokenCost) { | ||||||
|  |     ui.notifications.warn(`You do not have enough adversity tokens.`); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Check if the player owns the actor who made the roll | ||||||
|  |   if (spendingPlayerActor.id === rollActorId) { | ||||||
|  |     // The player owns the actor, so they can spend tokens directly without GM approval | ||||||
|  |     const currentTokens = spendingPlayerActor.system.adversityTokens || 0; | ||||||
|  |  | ||||||
|  |     // Deduct the tokens from the player | ||||||
|  |     await spendingPlayerActor.update({ "system.adversityTokens": currentTokens - tokenCost }); | ||||||
|  |  | ||||||
|  |     // Modify the roll message with the new total | ||||||
|  |     await _updateRollMessage(rollMessageId, tokensToSpend, true); | ||||||
|  |  | ||||||
|  |   } else { | ||||||
|  |     // The player does not own the actor, so request GM approval to spend the tokens | ||||||
|  |     console.log(`Requesting to spend ${tokensToSpend} tokens for ${rollActor.name} by ${spendingPlayerActor.name} (cost: ${tokenCost})`); | ||||||
|  |  | ||||||
|  |     // Emit a socket request to spend tokens | ||||||
|  |     game.socket.emit('system.kids-on-brooms', { | ||||||
|  |       action: "spendTokens", | ||||||
|  |       rollActorId: rollActorId, | ||||||
|  |       spendingActorId: spendingPlayerActor.id,  // Send the player's actor who is spending the tokens | ||||||
|  |       tokensToSpend: tokensToSpend, | ||||||
|  |       tokenCost: tokenCost, | ||||||
|  |       rollMessageId: rollMessageId  // Pass message ID to update the roll result | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     ui.notifications.info(`Requested to spend ${tokenCost} tokens for ${rollActor.name}`); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Helper function to send a new message with the updated roll result | ||||||
|  | async function _updateRollMessage(rollMessageId, tokensToSpend, isPlayerOfActor) { | ||||||
|  |   const message = game.messages.get(rollMessageId); | ||||||
|  |  | ||||||
|  |   if (!message) { | ||||||
|  |     console.error("Message not found with ID:", rollMessageId); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   // Retrieve current tokens spent from flags, or initialize to 0 if not found | ||||||
|  |   let cumulativeTokensSpent = message.getFlag("kids-on-brooms", "tokensSpent") || 0; | ||||||
|  |   let newTotal = message.getFlag("kids-on-brooms", "newRollTotal") || message.rolls[0].total; | ||||||
|  |  | ||||||
|  |   /*if(isPlayerOfActor) | ||||||
|  |   { | ||||||
|  |     // Add the new tokens to the cumulative total | ||||||
|  |     cumulativeTokensSpent += tokensToSpend; | ||||||
|  |   } else { | ||||||
|  |     cumulativeTokensSpent += 2*tokensToSpend; | ||||||
|  |   }*/ | ||||||
|  |   cumulativeTokensSpent += tokensToSpend; | ||||||
|  |   newTotal += tokensToSpend; | ||||||
|  |   await message.setFlag("kids-on-brooms", "newRollTotal", newTotal); | ||||||
|  |  | ||||||
|  |   // Update the message's flags to store the cumulative tokens spent | ||||||
|  |   await message.setFlag("kids-on-brooms", "tokensSpent", cumulativeTokensSpent); | ||||||
|  |   let newContent = ""; | ||||||
|  |   if(cumulativeTokensSpent === 1) | ||||||
|  |   { | ||||||
|  |     newContent = `You have now spent ${cumulativeTokensSpent} token. The new roll total is ${newTotal}.`; | ||||||
|  |   } else { | ||||||
|  |     newContent = `You have now spent ${cumulativeTokensSpent} tokens. The new roll total is ${newTotal}.`; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Create a new chat message to display the updated total | ||||||
|  |   await ChatMessage.create({ | ||||||
|  |     speaker: ChatMessage.getSpeaker({ actor: message.speaker.actor }), | ||||||
|  |     content: newContent, | ||||||
|  |     type: CONST.CHAT_MESSAGE_STYLES.OTHER, | ||||||
|  |   }); | ||||||
|  | } | ||||||
							
								
								
									
										147
									
								
								module/sheets/actor-sheet.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								module/sheets/actor-sheet.mjs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | |||||||
|  | /** | ||||||
|  |  * Extend the basic ActorSheet with some very simple modifications | ||||||
|  |  * @extends {ActorSheet} | ||||||
|  |  */ | ||||||
|  | export class KidsOnBroomsActorSheet extends ActorSheet { | ||||||
|  |  | ||||||
|  |   /** @override */ | ||||||
|  |   static get defaultOptions()  | ||||||
|  |   { | ||||||
|  |     return foundry.utils.mergeObject(super.defaultOptions, { | ||||||
|  |       classes: ["kids-on-brooms", "sheet", "actor"], | ||||||
|  |       width: 800, | ||||||
|  |       height: 800, | ||||||
|  |       tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "features" }] | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** @override */ | ||||||
|  |   get template()  | ||||||
|  |   { | ||||||
|  |     console.log("template", this.actor) | ||||||
|  |     return `systems/kids-on-brooms/templates/actor/actor-${this.actor.type}-sheet.html`; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /* -------------------------------------------- */ | ||||||
|  |  | ||||||
|  |   /** @override */ | ||||||
|  |   /** @override */ | ||||||
|  | async getData()  | ||||||
|  | { | ||||||
|  |   // Retrieve the data structure from the base sheet. | ||||||
|  |   const context = super.getData(); | ||||||
|  |  | ||||||
|  |   // Use a safe clone of the actor data for further operations. | ||||||
|  |   const actorData = this.document.toObject(false); | ||||||
|  |  | ||||||
|  |   // Add the actor's data to context.data for easier access, as well as flags. | ||||||
|  |   context.system = actorData.system; | ||||||
|  |   context.flags = actorData.flags; | ||||||
|  |  | ||||||
|  |   // Add roll data for TinyMCE editors. | ||||||
|  |   context.rollData = context.actor.getRollData(); | ||||||
|  |   // Add roll data for TinyMCE editors. | ||||||
|  |   context.rollData = context.actor.getRollData(); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   console.log(context); | ||||||
|  |   return context; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |   /* -------------------------------------------- */ | ||||||
|  |  | ||||||
|  |   /** @override */ | ||||||
|  |   activateListeners(html)  | ||||||
|  |   { | ||||||
|  |     super.activateListeners(html); | ||||||
|  |     // ------------------------------------------------------------- | ||||||
|  |     // Everything below here is only needed if the sheet is editable | ||||||
|  |     if (!this.isEditable) return; | ||||||
|  |  | ||||||
|  |     // Rollable abilities. | ||||||
|  |     html.find('.rollable').click(this._onRoll.bind(this)); | ||||||
|  |  | ||||||
|  |     //If the user changes their wand material save that | ||||||
|  |     html.find('select[name="system.wand.wood"]').change(event => { | ||||||
|  |       const value = event.target.value; | ||||||
|  |       this.actor.update({ "system.wand.wood": value }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |   html.find('select[name="system.wand.core"]').change(event => { | ||||||
|  |     const value = event.target.value; | ||||||
|  |     this.actor.update({ "system.wand.core": value }); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Handle clickable rolls. | ||||||
|  |    * @param {Event} event   The originating click event | ||||||
|  |    * @private | ||||||
|  |    */ | ||||||
|  |   async _onRoll(e) { | ||||||
|  |     e.preventDefault(); | ||||||
|  |       const element = e.currentTarget; | ||||||
|  |       const dataset = element.dataset; | ||||||
|  |    | ||||||
|  |       // Handle rolls that supply the formula directly | ||||||
|  |       if (dataset.roll) { | ||||||
|  |       let label = dataset.label ? `${dataset.label}` : ''; | ||||||
|  |       // Get the roll data and include wand bonuses | ||||||
|  |       let rollData = this.actor.getRollData(); | ||||||
|  |       let totalBonus = 0; | ||||||
|  |       console.log(dataset.roll); | ||||||
|  |       // Apply wood bonus if it matches the stat being rolled for | ||||||
|  |       if (rollData.wandBonus.wood.stat === dataset.key) { | ||||||
|  |         totalBonus += rollData.wandBonus.wood.bonus; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // Apply core bonus if it matches the stat being rolled for AND it's different from the wood bonus | ||||||
|  |       if (rollData.wandBonus.core.stat === dataset.key && rollData.wandBonus.core.stat !== rollData.wandBonus.wood.stat) { | ||||||
|  |         totalBonus += rollData.wandBonus.core.bonus; | ||||||
|  |       } | ||||||
|  |       let rollFormula = dataset.roll + `+${totalBonus}`; | ||||||
|  |       let roll = new Roll(rollFormula, rollData); | ||||||
|  |       console.log(rollFormula); | ||||||
|  |       console.log(rollData); | ||||||
|  |    | ||||||
|  |       // Send the roll message to chat | ||||||
|  |       const rollMessage = await roll.toMessage({ | ||||||
|  |         speaker: ChatMessage.getSpeaker({ actor: this.actor }), | ||||||
|  |         flavor: label, | ||||||
|  |         rollMode: game.settings.get('core', 'rollMode'), | ||||||
|  |       }) | ||||||
|  |    | ||||||
|  |       // Now send the follow-up message with the adversity controls | ||||||
|  |       await this._sendAdversityControlsMessage(this.actor.id, rollMessage.id); | ||||||
|  |    | ||||||
|  |       return roll; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   //This just sends the buttons for the adversity token system | ||||||
|  |   async _sendAdversityControlsMessage(actorId, rollMessageId) { | ||||||
|  |     // Create the content for the adversity controls | ||||||
|  |     const adversityControlsHtml = this._createAdversityControls(actorId, rollMessageId); | ||||||
|  |    | ||||||
|  |     // Send the adversity controls as a follow-up message | ||||||
|  |     const controlMessage = await ChatMessage.create({ | ||||||
|  |       speaker: ChatMessage.getSpeaker({ actor: this.actor }), | ||||||
|  |       content: adversityControlsHtml, | ||||||
|  |     }); | ||||||
|  |    | ||||||
|  |     return controlMessage; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   // Create HTML content for adversity controls | ||||||
|  |   _createAdversityControls(actorId, rollMessageId) { | ||||||
|  |     return ` | ||||||
|  |       <div class="adversity-controls" data-roll-id="${rollMessageId}"> | ||||||
|  |         <button class="take-adversity" data-actor-id="${actorId}">Take Adversity Token</button> | ||||||
|  |         <input type="number" class="token-input" value="1" min="1" /> | ||||||
|  |         <button class="spend-adversity" data-actor-id="${actorId}">Spend Adversity Tokens</button> | ||||||
|  |       </div> | ||||||
|  |     `; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | { | ||||||
|  |   "name": "kids-on-brooms", | ||||||
|  |   "version": "2.0.0", | ||||||
|  |   "description": "CSS compiler for the Kids On Brooms system", | ||||||
|  |   "scripts": { | ||||||
|  |     "build": "gulp build", | ||||||
|  |     "compile": "gulp css", | ||||||
|  |     "watch": "gulp", | ||||||
|  |     "gulp": "gulp" | ||||||
|  |   }, | ||||||
|  |   "browserslist": [ | ||||||
|  |     "last 5 versions" | ||||||
|  |   ], | ||||||
|  |   "author": "Josiah Bradbury, Joscha Maier", | ||||||
|  |   "license": "MIT", | ||||||
|  |   "private": true, | ||||||
|  |   "dependencies": { | ||||||
|  |     "gulp": "^5", | ||||||
|  |     "gulp-autoprefixer": "^8", | ||||||
|  |     "gulp-sass": "^5", | ||||||
|  |     "gulp-sourcemaps": "^3", | ||||||
|  |     "kids-on-brooms": "file:" | ||||||
|  |   }, | ||||||
|  |   "devDependencies": { | ||||||
|  |     "sass": "^1.77.8" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								readme.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | The Kids On Brooms System Implemented in FoundryVTT, reupload from https://github.com/Singularity-Lathe-VTT/kids-on-brooms | ||||||
							
								
								
									
										22
									
								
								scss/components/_effects.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								scss/components/_effects.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | .effects .item { | ||||||
|  |   .effect-source, | ||||||
|  |   .effect-duration, | ||||||
|  |   .effect-controls { | ||||||
|  |     text-align: center; | ||||||
|  |     border-left: 1px solid #c9c7b8; | ||||||
|  |     border-right: 1px solid #c9c7b8; | ||||||
|  |     font-size: 12px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .effect-controls { | ||||||
|  |     border: none; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // _effects.scss | ||||||
|  | .kids-on-brooms input:focus, | ||||||
|  | .kids-on-brooms textarea:focus, | ||||||
|  | .kids-on-brooms select:focus { | ||||||
|  |   outline: none; | ||||||
|  |   border-color: $focus-border-color; | ||||||
|  | } | ||||||
							
								
								
									
										66
									
								
								scss/components/_forms.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								scss/components/_forms.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | .item-form { | ||||||
|  |   font-family: $font-primary; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .sheet-header { | ||||||
|  |   @include flexbox(row, wrap, flex-start); // Use a mixin for flexbox | ||||||
|  |   flex: 0 auto; | ||||||
|  |   overflow: hidden; | ||||||
|  |   margin-bottom: 10px; | ||||||
|  |  | ||||||
|  |   .profile-img { | ||||||
|  |     flex: 0 0 100px; | ||||||
|  |     height: 100px; | ||||||
|  |     margin-right: 10px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .header-fields { | ||||||
|  |     flex: 1; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   h1.charname { | ||||||
|  |     height: 50px; | ||||||
|  |     padding: 0; | ||||||
|  |     margin: 5px 0; | ||||||
|  |     border-bottom: 0; | ||||||
|  |  | ||||||
|  |     input { | ||||||
|  |       width: 100%; | ||||||
|  |       height: 100%; | ||||||
|  |       margin: 0; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | div.editor-border { | ||||||
|  |   border: 2px solid $primary-border-color; // Replace the hardcoded color with a variable | ||||||
|  |   border-radius: 10px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .sheet-tabs { | ||||||
|  |   flex: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .sheet-body, | ||||||
|  | .sheet-body .tab, | ||||||
|  | .sheet-body .tab .editor { | ||||||
|  |   height: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tox { | ||||||
|  |   .tox-editor-container { | ||||||
|  |     background: $c-white; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .tox-edit-area { | ||||||
|  |     padding: 0 8px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Flexbox container for each row | ||||||
|  | .selection-row { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; // Ensures label stays left and input moves to the right | ||||||
|  |   align-items: center; // Vertically center the label and input | ||||||
|  |   margin-bottom: 10px; // Optional: Add some space between rows | ||||||
|  | } | ||||||
							
								
								
									
										124
									
								
								scss/components/_items.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								scss/components/_items.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | |||||||
|  | // Section Header | ||||||
|  | .items-header { | ||||||
|  |   height: 28px; | ||||||
|  |   margin: 2px 0; | ||||||
|  |   padding: 0; | ||||||
|  |   align-items: center; | ||||||
|  |   background: rgba(0, 0, 0, 0.05); | ||||||
|  |   border: $border-groove; | ||||||
|  |   font-weight: bold; | ||||||
|  |    | ||||||
|  |   > * { | ||||||
|  |     font-size: 14px; | ||||||
|  |     text-align: center; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .item-name { | ||||||
|  |     font-weight: bold; | ||||||
|  |     padding-left: 5px; | ||||||
|  |     text-align: left; | ||||||
|  |     display: flex; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Items Lists | ||||||
|  | .items-list { | ||||||
|  |   list-style: none; | ||||||
|  |   margin: 0; | ||||||
|  |   padding: 0; | ||||||
|  |   overflow-y: auto; | ||||||
|  |   scrollbar-width: thin; | ||||||
|  |   color: $c-tan; | ||||||
|  |  | ||||||
|  |   // Child lists | ||||||
|  |   .item-list { | ||||||
|  |     list-style: none; | ||||||
|  |     margin: 0; | ||||||
|  |     padding: 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Individual Item | ||||||
|  |   .item { | ||||||
|  |     display: flex; | ||||||
|  |     align-items: center; | ||||||
|  |     padding: 0 2px; // Align with the header border | ||||||
|  |     border-bottom: 1px solid $c-faint; | ||||||
|  |  | ||||||
|  |     &:last-child { | ||||||
|  |       border-bottom: none; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Item name and image | ||||||
|  |     .item-name { | ||||||
|  |       flex: 2; | ||||||
|  |       margin: 0; | ||||||
|  |       overflow: hidden; | ||||||
|  |       font-size: 13px; | ||||||
|  |       text-align: left; | ||||||
|  |       display: flex; | ||||||
|  |       color: $c-dark; | ||||||
|  |  | ||||||
|  |       h3, h4 { | ||||||
|  |         margin: 0; | ||||||
|  |         white-space: nowrap; | ||||||
|  |         overflow-x: hidden; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       .item-image { | ||||||
|  |         flex: 0 0 30px; | ||||||
|  |         height: 30px; | ||||||
|  |         background-size: 30px; | ||||||
|  |         border: none; | ||||||
|  |         margin-right: 5px; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Control Buttons | ||||||
|  |   .item-controls { | ||||||
|  |     display: flex; | ||||||
|  |     flex: 0 0 100px; | ||||||
|  |     justify-content: flex-end; | ||||||
|  |  | ||||||
|  |     a { | ||||||
|  |       font-size: 12px; | ||||||
|  |       text-align: center; | ||||||
|  |       margin: 0 6px; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Item Properties (like stats or details) | ||||||
|  |   .item-prop { | ||||||
|  |     text-align: center; | ||||||
|  |     border-left: 1px solid $c-faint; | ||||||
|  |     border-right: 1px solid $c-faint; | ||||||
|  |     font-size: 12px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Section Header inside Items List | ||||||
|  | .items-list .items-header { | ||||||
|  |   height: 28px; | ||||||
|  |   margin: 2px 0; | ||||||
|  |   padding: 0; | ||||||
|  |   align-items: center; | ||||||
|  |   background: rgba(0, 0, 0, 0.05); | ||||||
|  |   border: $border-groove; | ||||||
|  |   font-weight: bold; | ||||||
|  |  | ||||||
|  |   > * { | ||||||
|  |     font-size: 12px; | ||||||
|  |     text-align: center; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .item-name { | ||||||
|  |     padding-left: 5px; | ||||||
|  |     text-align: left; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Optional item formula block | ||||||
|  | .item-formula { | ||||||
|  |   flex: 0 0 200px; | ||||||
|  |   padding: 0 8px; | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								scss/components/_resource.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								scss/components/_resource.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | .resource-label { | ||||||
|  |   font-weight: bold; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								scss/global/_base.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								scss/global/_base.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | // _base.scss | ||||||
|  | @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap"); | ||||||
|  |  | ||||||
|  | .window-app { | ||||||
|  |   font-family: $font-stack; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .rollable { | ||||||
|  |   &:hover, | ||||||
|  |   &:focus { | ||||||
|  |     color: #000; | ||||||
|  |     text-shadow: $hover-text-shadow; | ||||||
|  |     cursor: pointer; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										50
									
								
								scss/global/_flex.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								scss/global/_flex.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | // Flexbox Utility Classes | ||||||
|  | .flex-group-center { | ||||||
|  |   @include flexbox(center, center); | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flex-group-left { | ||||||
|  |   @include flexbox(flex-start, center); | ||||||
|  |   text-align: left; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flex-group-right { | ||||||
|  |   @include flexbox(flex-end, center); | ||||||
|  |   text-align: right; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flexshrink { | ||||||
|  |   flex: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flex-between { | ||||||
|  |   justify-content: space-between; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flexlarge { | ||||||
|  |   flex: 2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Alignment Utility Classes | ||||||
|  | .align-left { | ||||||
|  |   @include flexbox(flex-start, center); | ||||||
|  |   text-align: left; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .align-right { | ||||||
|  |   @include flexbox(flex-end, center); | ||||||
|  |   text-align: right; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .align-center { | ||||||
|  |   @include flexbox(center, center); | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Only apply the right alignment to specific inputs with this class | ||||||
|  | .right-align-input { | ||||||
|  |   flex: 1; | ||||||
|  |   margin-left: auto; // Push the input to the far right | ||||||
|  |   max-width: 260px; // Optional: Control the width of the input field | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								scss/global/_grid.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								scss/global/_grid.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | // _grid.scss | ||||||
|  | .grid { | ||||||
|  |   display: grid; | ||||||
|  |   gap: 10px; | ||||||
|  |   margin: 10px 0; | ||||||
|  |   padding: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @for $i from 2 through 12 { | ||||||
|  |   // Create grid-start-* classes for offsets | ||||||
|  |   .grid-start-#{$i} { | ||||||
|  |     grid-column-start: #{$i}; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Create grid-span-* classes for column spans | ||||||
|  |   .grid-span-#{$i} { | ||||||
|  |     grid-column-end: span #{$i}; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Create grid-*col classes for grid columns | ||||||
|  |   .grid-#{$i}col { | ||||||
|  |     grid-column: span #{$i} / span #{$i}; | ||||||
|  |     grid-template-columns: repeat(#{$i}, minmax(0, 1fr)); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								scss/global/_window.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								scss/global/_window.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | .window-app { | ||||||
|  |   font-family: $font-primary; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .rollable { | ||||||
|  |   &:hover, | ||||||
|  |   &:focus { | ||||||
|  |     color: #000; | ||||||
|  |     text-shadow: 0 0 10px rgb(146, 0, 225); | ||||||
|  |     cursor: pointer; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								scss/kidsonbrooms.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								scss/kidsonbrooms.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | // Add custom fonts by visiting and search https://fonts.google.com | ||||||
|  | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap'); | ||||||
|  | // This is the font used for the book, will not buy it but for refrence https://www.myfonts.com/collections/dreadful-font-aiyari?queryId=undefined&index=universal_search_data&objectIDs=5368854002 | ||||||
|  | // This is the font used for text https://www.myfonts.com/products/lapidary-333-lapidary-333-434881?queryId=undefined&index=universal_search_data&objectIDs=5468003002 | ||||||
|  | // Import utilities. | ||||||
|  | @import 'utils/variables'; | ||||||
|  | @import 'utils/typography'; | ||||||
|  | @import 'utils/colors'; | ||||||
|  | @import 'utils/mixins'; | ||||||
|  |  | ||||||
|  | /* Global styles */ | ||||||
|  | @import 'global/window'; | ||||||
|  | @import 'global/grid'; | ||||||
|  | @import 'global/flex'; | ||||||
|  | @import 'global/base'; | ||||||
|  |  | ||||||
|  | /* Styles limited to kidsonbrooms sheets */ | ||||||
|  | .kids-on-brooms { | ||||||
|  |   @import 'components/forms'; | ||||||
|  |   @import 'components/resource'; | ||||||
|  |   @import 'components/items'; | ||||||
|  |   @import 'components/effects'; | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								scss/utils/_colors.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								scss/utils/_colors.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | $c-white: #fff; | ||||||
|  | $c-black: #000; | ||||||
|  |  | ||||||
|  | $c-dark: #191813; | ||||||
|  | $c-faint: #c9c7b8; | ||||||
|  | $c-beige: #b5b3a4; | ||||||
|  | $c-tan: #444; | ||||||
|  |  | ||||||
|  | $primary-border-color: rgb(81, 81, 81); | ||||||
|  |  | ||||||
|  | $focus-border-color: #8102dd; | ||||||
|  | $hover-text-shadow: 0 0 10px rgb(179, 7, 217); | ||||||
|  | $border-color: #ccc; | ||||||
							
								
								
									
										25
									
								
								scss/utils/_mixins.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								scss/utils/_mixins.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | @mixin element-invisible { | ||||||
|  |   position: absolute; | ||||||
|  |  | ||||||
|  |   width: 1px; | ||||||
|  |   height: 1px; | ||||||
|  |   margin: -1px; | ||||||
|  |   border: 0; | ||||||
|  |   padding: 0; | ||||||
|  |  | ||||||
|  |   clip: rect(0 0 0 0); | ||||||
|  |   overflow: hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @mixin hide { | ||||||
|  |   display: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Update the mixin to accept 3 arguments: direction, wrap, and justify | ||||||
|  | @mixin flexbox($direction, $wrap: nowrap, $justify: flex-start, $align: stretch) { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: $direction; | ||||||
|  |   flex-wrap: $wrap; | ||||||
|  |   justify-content: $justify; | ||||||
|  |   align-items: $align; | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								scss/utils/_typography.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								scss/utils/_typography.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | $font-primary: 'Roboto', sans-serif; | ||||||
|  | $font-secondary: 'Roboto', sans-serif; | ||||||
							
								
								
									
										10
									
								
								scss/utils/_variables.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								scss/utils/_variables.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | $padding-sm: 5px; | ||||||
|  | $padding-md: 10px; | ||||||
|  | $padding-lg: 20px; | ||||||
|  |  | ||||||
|  | $border-groove: 2px groove #eeede0; | ||||||
|  |  | ||||||
|  | $font-stack: "Roboto", sans-serif; | ||||||
|  | $padding: 10px; | ||||||
|  | $border-radius: 5px; | ||||||
|  | $flex-align: center; | ||||||
							
								
								
									
										24
									
								
								system.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								system.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | { | ||||||
|  |   "id": "kids-on-brooms", | ||||||
|  |   "title": "Kids on Brooms System", | ||||||
|  |   "description": "The Kids on Brooms system for FoundryVTT! - Deprecated", | ||||||
|  |   "version": "0.0.1", | ||||||
|  |   "compatibility": { | ||||||
|  |     "minimum": 12, | ||||||
|  |     "verified": 12 | ||||||
|  |   }, | ||||||
|  |   "authors": [{ | ||||||
|  |     "name": "Josiah Bradbury, Joscha Maier" | ||||||
|  |   }], | ||||||
|  |   "esmodules": ["module/kidsonbrooms.mjs"], | ||||||
|  |   "styles": ["css/kidsonbrooms.css"], | ||||||
|  |   "socket": true, | ||||||
|  |   "grid": { | ||||||
|  |     "distance": 5, | ||||||
|  |     "units": "ft" | ||||||
|  |   }, | ||||||
|  |   "primaryTokenAttribute": "system.adversityTokens", | ||||||
|  |   "url": "https://github.com/josmaier/KidsOnBroomsFoundryVTT", | ||||||
|  |   "manifest": "https://github.com/josmaier/KidsOnBroomsFoundryVTT/blob/2fb5d0a11d1c9d78945c2508d5aa2cc7daf297e0/system.json", | ||||||
|  |   "download": "https://github.com/josmaier/KidsOnBroomsFoundryVTT/blob/2fb5d0a11d1c9d78945c2508d5aa2cc7daf297e0/kids-on-brooms.zip" | ||||||
|  | } | ||||||
							
								
								
									
										68
									
								
								template.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								template.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | { | ||||||
|  |   "Actor": { | ||||||
|  |     "types": ["character", "npc"], | ||||||
|  |     "templates": { | ||||||
|  |       "base": { | ||||||
|  |         "stats": { | ||||||
|  |           "fight": { | ||||||
|  |             "value": "d4", | ||||||
|  |             "stat": 0, | ||||||
|  |             "magic": 0 | ||||||
|  |           }, | ||||||
|  |           "flight": { | ||||||
|  |             "value": "d4", | ||||||
|  |             "stat": 0, | ||||||
|  |             "magic": 0 | ||||||
|  |           }, | ||||||
|  |           "brains": { | ||||||
|  |             "value": "d4", | ||||||
|  |             "stat": 0, | ||||||
|  |             "magic": 0 | ||||||
|  |           }, | ||||||
|  |           "brawn": { | ||||||
|  |             "value": "d4", | ||||||
|  |             "stat": 0, | ||||||
|  |             "magic": 0 | ||||||
|  |           }, | ||||||
|  |           "charm": { | ||||||
|  |             "value": "d4", | ||||||
|  |             "stat": 0, | ||||||
|  |             "magic": 0 | ||||||
|  |           }, | ||||||
|  |           "grit": { | ||||||
|  |             "value": "d4", | ||||||
|  |             "stat": 0, | ||||||
|  |             "magic": 0 | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "description": "" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "character": { | ||||||
|  |       "templates": ["base"], | ||||||
|  |       "trope": "", | ||||||
|  |       "age": "", | ||||||
|  |       "pronouns": "", | ||||||
|  |       "fear": "", | ||||||
|  |       "motivation": "", | ||||||
|  |       "grade":"", | ||||||
|  |       "broom": { | ||||||
|  |         "name": "", | ||||||
|  |         "look": "", | ||||||
|  |         "mechanicalbenifit": "" | ||||||
|  |       }, | ||||||
|  |       "wand": { | ||||||
|  |         "wood": "", | ||||||
|  |         "core": "" | ||||||
|  |       }, | ||||||
|  |       "animalfamiliar":"", | ||||||
|  |       "schoolbag": "", | ||||||
|  |       "adversityTokens": 0, | ||||||
|  |       "tropequestions": "", | ||||||
|  |       "strengths": "" | ||||||
|  |     }, | ||||||
|  |     "npc": { | ||||||
|  |       "templates": ["base"] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										63
									
								
								templates/actor/actor-character-sheet.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								templates/actor/actor-character-sheet.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | <form class="{{cssClass}} {{actor.type}} flexcol" autocomplete="off"> | ||||||
|  |   {{!-- Sheet Header --}} | ||||||
|  |   <header class="sheet-header"> | ||||||
|  |     <img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="100" width="100"/> | ||||||
|  |     <div class="header-fields"> | ||||||
|  |       <h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name"/></h1> | ||||||
|  |  | ||||||
|  |       <div class="resources grid"> | ||||||
|  |         <div class="resource flex-group-center"> | ||||||
|  |           <label for="system.trope" class="resource-label">Trope</label> | ||||||
|  |           <div class="resource-content flexrow flex-center flex-between"> | ||||||
|  |           <input type="text" name="system.trope" value="{{system.trope}}" data-dtype="String"/> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </header> | ||||||
|  |  | ||||||
|  |   {{!-- Sheet Tab Navigation --}} | ||||||
|  |   <nav class="sheet-tabs tabs" data-group="primary"> | ||||||
|  |     {{!-- Default tab is specified in actor-sheet.mjs --}} | ||||||
|  |     <a class="item" data-tab="features">Features</a> | ||||||
|  |     <a class="item" data-tab="schoolbag">School Bag</a> | ||||||
|  |     <a class="item" data-tab="strengths">Strengths</a> | ||||||
|  |     <a class="item" data-tab="trope">Trope Questions</a> | ||||||
|  |   </nav> | ||||||
|  |  | ||||||
|  |   {{!-- Sheet Body --}} | ||||||
|  |   <section class="sheet-body"> | ||||||
|  |  | ||||||
|  |     {{!-- Owned Features Tab --}} | ||||||
|  |     <div class="tab features" data-group="primary" data-tab="features"> | ||||||
|  |       <section class="grid grid-3col"> | ||||||
|  |         <section class="main grid-span-2"> | ||||||
|  |           {{> "systems/kids-on-brooms/templates/actor/parts/actor-features.html"}} | ||||||
|  |           {{> "systems/kids-on-brooms/templates/actor/parts/actor-adversity.html"}} | ||||||
|  |         </section> | ||||||
|  |  | ||||||
|  |         <aside class="sidebar"> | ||||||
|  |           {{> "systems/kids-on-brooms/templates/actor/parts/actor-stats.html"}} | ||||||
|  |            | ||||||
|  |         </aside> | ||||||
|  |  | ||||||
|  |       </section> | ||||||
|  |     </div> | ||||||
|  |     {{!-- Schoolbag Tab --}} | ||||||
|  |     <div class="tab features editor-border" data-group="primary" data-tab="schoolbag"> | ||||||
|  |       {{editor schoolbag target="system.schoolbag" engine="prosemirror" button=false collaborate=false editable=true}} | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     {{!-- Strengths Tab --}} | ||||||
|  |     <div class="tab features editor-border" data-group="primary" data-tab="strengths"> | ||||||
|  |       {{editor strengths target="system.strengths" engine="prosemirror" button=false collaborate=false editable=true}} | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     {{!-- Trope Questions Tab --}} | ||||||
|  |     <div class="tab features editor-border" data-group="primary" data-tab="trope"> | ||||||
|  |       {{editor tropequestions target="system.tropequestions" engine="prosemirror" button=false collaborate=false editable=true}} | ||||||
|  |     </div> | ||||||
|  |      | ||||||
|  |   </section> | ||||||
|  | </form> | ||||||
|  |  | ||||||
							
								
								
									
										35
									
								
								templates/actor/actor-npc-sheet.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								templates/actor/actor-npc-sheet.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | <form class="{{cssClass}} {{actor.type}} flexcol" autocomplete="off"> | ||||||
|  |  | ||||||
|  |   {{!-- Sheet Header --}} | ||||||
|  |   <header class="sheet-header"> | ||||||
|  |     <img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="100" width="100"/> | ||||||
|  |     <div class="header-fields"> | ||||||
|  |       <h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name"/></h1> | ||||||
|  |  | ||||||
|  |       <div class="resources grid"> | ||||||
|  |         <div class="resource flex-group-center"> | ||||||
|  |           <label for="system.trope" class="resource-label">Trope</label> | ||||||
|  |           <div class="resource-content flexrow flex-center flex-between"> | ||||||
|  |           <input type="text" name="system.trope" value="{{system.trope}}" data-dtype="String"/> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </header> | ||||||
|  |  | ||||||
|  |   {{!-- Sheet Tab Navigation --}} | ||||||
|  |   <nav class="sheet-tabs tabs" data-group="primary"> | ||||||
|  |     {{!-- Default tab is specified in actor-sheet.mjs --}} | ||||||
|  |     <a class="item" data-tab="features">Features</a> | ||||||
|  |   </nav> | ||||||
|  |  | ||||||
|  |   {{!-- Sheet Body --}} | ||||||
|  |   <section class="sheet-body"> | ||||||
|  |  | ||||||
|  |     {{!-- Owned Features Tab --}} | ||||||
|  |     <div class="tab features" data-group="primary" data-tab="features"> | ||||||
|  |       {{> "systems/kids-on-brooms/templates/actor/parts/actor-npc-stats.html"}} | ||||||
|  |     </div> | ||||||
|  |   </section> | ||||||
|  | </form> | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								templates/actor/parts/actor-adversity.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								templates/actor/parts/actor-adversity.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | <fieldset> | ||||||
|  |   <legend>Adversity Tokens</legend> | ||||||
|  |   <div class="resource flexcol" > | ||||||
|  |     <label for="system.adversity" class="resource-label"> | ||||||
|  |       Begin the game with 3 | ||||||
|  |       adversity tokens. Add 1 | ||||||
|  |       each time you fail a roll. | ||||||
|  |     </label> | ||||||
|  |     <input type="number" name="system.adversityTokens" value="{{system.adversityTokens}}" data-dtype="Number"/> | ||||||
|  |   </div> | ||||||
|  | </fieldset> | ||||||
							
								
								
									
										156
									
								
								templates/actor/parts/actor-features.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								templates/actor/parts/actor-features.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | |||||||
|  | <section class="grid grid-3col"> | ||||||
|  |    | ||||||
|  |   <fieldset class="resource grid-span-3 flexcol"> | ||||||
|  |   <div class="resource flexrow"> | ||||||
|  |     <label for="system.age" class="resource-label">Age</label> | ||||||
|  |     <input type="text" name="system.age" value="{{system.age}}" data-dtype="String"/> | ||||||
|  |   </div> | ||||||
|  |   <div class="resource grid-span-2 flexrow"> | ||||||
|  |     <label for="system.pronouns" class="resource-label">Pronouns</label> | ||||||
|  |     <input type="text" name="system.pronouns" value="{{system.pronouns}}" data-dtype="String"/> | ||||||
|  |   </div> | ||||||
|  |   <div class="resource grid-span-3 flexrow"> | ||||||
|  |     <label for="system.fear" class="resource-label">Fear</label> | ||||||
|  |     <input type="text" name="system.fear" value="{{system.fear}}" data-dtype="String"/> | ||||||
|  |   </div> | ||||||
|  |   <div class="resource grid-span-3 flexrow" > | ||||||
|  |     <label for="system.motivation" class="resource-label">Motivation</label> | ||||||
|  |     <input type="text" name="system.motivation" value="{{system.motivation}}" data-dtype="String"/> | ||||||
|  |   </div> | ||||||
|  |   <div class="resource grid-span-3 flexrow" > | ||||||
|  |     <label for="system.description" class="resource-label">Description</label> | ||||||
|  |     <input type="text" name="system.description" value="{{system.description}}" data-dtype="String"/> | ||||||
|  |   </div> | ||||||
|  |   <div class="resource grid-span-3 flexrow"> | ||||||
|  |     <label for="system.grade" class="resource-label">Grade</label> | ||||||
|  |     <input type="text" name="system.grade" value="{{system.grade}}" data-dtype="String"/> | ||||||
|  |   </div> | ||||||
|  | </fieldset> | ||||||
|  |   <fieldset class="resource grid-span-3 flexcol"> | ||||||
|  |     <legend>Your Broom</legend> | ||||||
|  |    | ||||||
|  |     <!-- Broom Name Input with Dropdown --> | ||||||
|  |     <div class="resource flexrow"> | ||||||
|  |       <label for="broom-name" class="resource-label">Name</label> | ||||||
|  |       <input list="broomOptions" id="broom-name" name="system.broom.name"  | ||||||
|  |              value="{{system.broom.name}}" data-dtype="String" placeholder="Select or Enter Broom Name" | ||||||
|  |              oninput="updateBroomDetails()" onblur="updateBroomDetails()"> | ||||||
|  |       <datalist id="broomOptions"> | ||||||
|  |         <option value="The Blocker's Broom" data-look="Defensive" data-mechanical="Gain the Guardian Strength"></option> | ||||||
|  |         <option value="Bolting 4000" data-look="Fast" data-mechanical="+1 to Flight checks"></option> | ||||||
|  |         <option value="The Bruiser" data-look="Intense" data-mechanical="+1 to Fight checks"></option> | ||||||
|  |         <option value="Cunning Captain’s Cruiser" data-look="Natural Leader" data-mechanical="Treat Snap Decisions as Planned Actions unless facing fear"></option> | ||||||
|  |         <option value="Daredevil’s Duster" data-look="Flashy" data-mechanical="+3 to Charm checks when performing a stunt"></option> | ||||||
|  |         <option value="The Daring Dodger 3000" data-look="Ambitious" data-mechanical="Each Adversity Token adds +2 to your roll instead of +1"></option> | ||||||
|  |         <option value="Heartwood’s Helper" data-look="Outgoing" data-mechanical="Each successful check grants an ally one Adversity Token"></option> | ||||||
|  |         <option value="Mapmaker’s Friend" data-look="Level-Headed" data-mechanical="Cannot get lost if you know the area"></option> | ||||||
|  |         <option value="The Mastermind’s Sweeper" data-look="Confident" data-mechanical="+1 to Brains checks"></option> | ||||||
|  |         <option value="The Strong Sweep 2500" data-look="Strong" data-mechanical="+1 to Brawn checks"></option> | ||||||
|  |         <option value="The Suave Sweeper" data-look="Trustworthy" data-mechanical="+1 to Charm checks"></option> | ||||||
|  |         <option value="The Tough Break" data-look="Tough" data-mechanical="+1 to Grit checks"></option> | ||||||
|  |         <option value="Valiance 2400" data-look="Brave" data-mechanical="May ignore your fears"></option> | ||||||
|  |         <option value="Weasel’s Whisk" data-look="Sneaky" data-mechanical="Gain the Unassuming Strength"></option> | ||||||
|  |       </datalist> | ||||||
|  |     </div> | ||||||
|  |    | ||||||
|  |     <!-- Broom Look --> | ||||||
|  |     <div class="resource flexrow"> | ||||||
|  |       <label for="broom-look" class="resource-label">Look</label> | ||||||
|  |       <input type="text" id="broom-look" name="system.broom.look"  | ||||||
|  |              value="{{system.broom.look}}" data-dtype="String"/> | ||||||
|  |     </div> | ||||||
|  |    | ||||||
|  |     <!-- Mechanical Benefit as Textarea --> | ||||||
|  |     <div class="resource flexrow"> | ||||||
|  |       <label for="broom-mechanical" class="resource-label">Mechanical Benefit</label> | ||||||
|  |       <textarea id="broom-mechanical" name="system.broom.mechanicalbenefit"  | ||||||
|  |                 data-dtype="String" rows="3" style="resize:none;"></textarea> | ||||||
|  |     </div> | ||||||
|  |    | ||||||
|  |   </fieldset> | ||||||
|  |    | ||||||
|  |   <script> | ||||||
|  |   function updateBroomDetails() { | ||||||
|  |     // Use a short delay to allow browser to properly handle the datalist input | ||||||
|  |     setTimeout(function() { | ||||||
|  |       const broomNameInput = document.getElementById("broom-name").value.trim(); | ||||||
|  |       const broomOptions = document.querySelectorAll("#broomOptions option"); | ||||||
|  |  | ||||||
|  |       let selectedLook = ""; | ||||||
|  |       let selectedMechanical = ""; | ||||||
|  |  | ||||||
|  |       // Loop through the datalist options to find a matching broom name | ||||||
|  |       broomOptions.forEach(option => { | ||||||
|  |         if (option.value.toLowerCase() === broomNameInput.toLowerCase()) { | ||||||
|  |           selectedLook = option.getAttribute("data-look"); | ||||||
|  |           selectedMechanical = option.getAttribute("data-mechanical"); | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |       // Update the look and mechanical benefit fields if a predefined broom is selected | ||||||
|  |       document.getElementById("broom-look").value = selectedLook || ""; | ||||||
|  |       document.getElementById("broom-mechanical").value = selectedMechanical || ""; | ||||||
|  |     }, 100); // Delay of 100 milliseconds | ||||||
|  |   } | ||||||
|  |   </script> | ||||||
|  |     <fieldset class="resource grid-span-3 flexcol"> | ||||||
|  |       <legend>Wand Selection</legend> | ||||||
|  |    | ||||||
|  |         <!-- Wood Selection --> | ||||||
|  |         <div class="resource-flexrow"> | ||||||
|  |         <label for="system.wand.wood" class="resource-label">Wood Type</label> | ||||||
|  |         <input list="WoodOptions" id="wandWoodChoice" name="system.wand.wood" value="{{system.wand.wood}}" placeholder="Select Wood type" | ||||||
|  |         oninput="updateWandWoodDetails()" onblur="updateWandWoodDetails()"> | ||||||
|  |         <datalist id="WoodOptions"> | ||||||
|  |           <option value="">Select Wood</option> | ||||||
|  |             <option value="Wisteria">(Brains)</option> | ||||||
|  |             <option value="Hawthorn">(Brains)</option> | ||||||
|  |             <option value="Pine">(Brawn)</option> | ||||||
|  |             <option value="Oak">(Brawn)</option> | ||||||
|  |             <option value="Crabapple">(Fight)</option> | ||||||
|  |             <option value="Dogwood">(Fight)</option> | ||||||
|  |             <option value="Birch">(Flight)</option> | ||||||
|  |             <option value="Bamboo">(Flight)</option> | ||||||
|  |             <option value="Ironwood">(Grit)</option> | ||||||
|  |             <option value="Maple">(Grit)</option> | ||||||
|  |             <option value="Lilac">(Charm)</option> | ||||||
|  |             <option value="Cherry">(Charm)</option> | ||||||
|  |         </datalist> | ||||||
|  |         </div> | ||||||
|  |    | ||||||
|  |         <!-- Core Selection --> | ||||||
|  |         <div class="resource-flexrow"> | ||||||
|  |           <label for="system.wand.core"  class="resource-label">Core Type</label> | ||||||
|  |           <input list="CoreOptions" id="wandCoreChoice" name="system.wand.core" value="{{system.wand.core}}" placeholder="Select Core type" | ||||||
|  |           oninput="updateWandCoreDetails()" onblur="updateWandCoreDetails()"> | ||||||
|  |           <datalist id="CoreOptions"> | ||||||
|  |             <option value="">Select Core</option> | ||||||
|  |             <option value="Parchment">(Brains)</option> | ||||||
|  |             <option value="Phoenix Feather">(Brains)</option> | ||||||
|  |             <option value="Owl Feather">(Brains)</option> | ||||||
|  |             <option value="Gorilla Fur">(Brawn)</option> | ||||||
|  |             <option value="Ogre’s Fingernail">(Brawn)</option> | ||||||
|  |             <option value="Hippo’s Tooth">(Brawn)</option> | ||||||
|  |             <option value="Dragon’s Heartstring">(Fight)</option> | ||||||
|  |             <option value="Wolf’s Tooth">(Fight)</option> | ||||||
|  |             <option value="Elk’s Antler">(Fight)</option> | ||||||
|  |             <option value="Hawk’s Feather">(Flight)</option> | ||||||
|  |             <option value="Bat’s Bone">(Flight)</option> | ||||||
|  |             <option value="Changeling’s Hair">(Charm)</option> | ||||||
|  |             <option value="Gold">(Charm)</option> | ||||||
|  |             <option value="Mirror">(Charm)</option> | ||||||
|  |             <option value="Steel">(Grit)</option> | ||||||
|  |             <option value="Diamond">(Grit)</option> | ||||||
|  |             <option value="Lion’s Mane">(Grit)</option> | ||||||
|  |           </datalist> | ||||||
|  |         </div>   | ||||||
|  |   </fieldset> | ||||||
|  |   <fieldset class="resource grid-span-3 flexcol"> | ||||||
|  |     <legend>Animal Familiar</legend> | ||||||
|  |     <div class="resource grid-span-3 flexrow"> | ||||||
|  |       <label for="system.animalfamiliar" class="resource-label">Animal Familiar</label> | ||||||
|  |       <input type="text" name="system.animalfamiliar" value="{{system.animalfamiliar}}" data-dtype="String"/> | ||||||
|  |     </div> | ||||||
|  |   </fieldset> | ||||||
|  |    | ||||||
|  | </section> | ||||||
							
								
								
									
										29
									
								
								templates/actor/parts/actor-npc-stats.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								templates/actor/parts/actor-npc-stats.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | <section class="flexcol"> | ||||||
|  |   {{#each system.stats as |stat key|}} | ||||||
|  |     <Fieldset class="grid grid-5col"> | ||||||
|  |       <legend>{{key}}</legend> | ||||||
|  |       <select name="system.stats.{{key}}.value"> | ||||||
|  |         {{#select stat.value}} | ||||||
|  |         <option value="d20">d20</option> | ||||||
|  |         <option value="d12">d12</option> | ||||||
|  |         <option value="d10">d10</option> | ||||||
|  |         <option value="d8">d8</option> | ||||||
|  |         <option value="d6">d6</option> | ||||||
|  |         <option value="d4">d4</option> | ||||||
|  |         {{/select}} | ||||||
|  |       </select> | ||||||
|  |       <div class="flexrow grid-span-4"> | ||||||
|  |         <Fieldset class="flexrow"> | ||||||
|  |         <legend>Stat</legend> | ||||||
|  |         <span class="ability-mod rollable" data-roll="{{stat.value}}+{{stat.stat}}" data-label="Stat Roll for {{key}}"><i class="fas fa-dice-d20"></i></span> | ||||||
|  |         <input type="text" name="system.stats.{{key}}.stat" value="{{stat.stat}}" data-dtype="String"/> | ||||||
|  |       </Fieldset> | ||||||
|  |       <Fieldset class="flexrow"> | ||||||
|  |         <legend>Magic</legend> | ||||||
|  |         <span class="ability-mod rollable" data-roll="{{stat.value}}+{{stat.magic}}" data-label="Magic Roll for {{key}}"><i class="fas fa-dice-d20"></i></span> | ||||||
|  |         <input type="text" name="system.stats.{{key}}.magic" value="{{stat.magic}}" data-dtype="String"/> | ||||||
|  |       </Fieldset> | ||||||
|  |       </div> | ||||||
|  |     </Fieldset> | ||||||
|  |   {{/each}} | ||||||
|  | </section> | ||||||
							
								
								
									
										37
									
								
								templates/actor/parts/actor-stats.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								templates/actor/parts/actor-stats.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | <section class="flexcol"> | ||||||
|  |   {{#each system.stats as |stat key|}} | ||||||
|  |     <Fieldset class="flexrow"> | ||||||
|  |       <legend>{{capitalizeFirst key}}</legend> | ||||||
|  |       <div class="flexrow flex-group-center"> | ||||||
|  |         <!-- Die type dropdown --> | ||||||
|  |         <select name="system.stats.{{key}}.value"> | ||||||
|  |           <option value="d20" {{#if (eq stat.value 'd20')}}selected{{/if}}>Superb</option> | ||||||
|  |           <option value="d12" {{#if (eq stat.value 'd12')}}selected{{/if}}>Impressive</option> | ||||||
|  |           <option value="d10" {{#if (eq stat.value 'd10')}}selected{{/if}}>Above Average</option> | ||||||
|  |           <option value="d8" {{#if (eq stat.value 'd8')}}selected{{/if}}>Below Average</option> | ||||||
|  |           <option value="d6" {{#if (eq stat.value 'd6')}}selected{{/if}}>Bad</option> | ||||||
|  |           <option value="d4" {{#if (eq stat.value 'd4')}}selected{{/if}}>Terrible</option> | ||||||
|  |         </select> | ||||||
|  |  | ||||||
|  |         <!-- Stat rolling and input --> | ||||||
|  |         <Fieldset class="flexrow flex-group-center"> | ||||||
|  |           <legend>Stat</legend> | ||||||
|  |           <span class="ability-mod rollable" data-roll="1{{stat.value}}x+{{stat.stat}}" data-label="Stat Roll for {{key}}" data-key="{{key}}"> | ||||||
|  |             <i class="fas fa-dice-d20"></i> | ||||||
|  |           </span> | ||||||
|  |           <input type="number" name="system.stats.{{key}}.stat" value="{{stat.stat}}" data-dtype="Number"/> | ||||||
|  |         </Fieldset> | ||||||
|  |  | ||||||
|  |         <!-- Magic rolling and input --> | ||||||
|  |         <Fieldset class="flexrow flex-group-center"> | ||||||
|  |           <legend>Magic</legend> | ||||||
|  |           <span class="ability-mod rollable" data-roll="1{{stat.value}}x+1d4+{{stat.stat}}" data-label="Magic Roll for {{key}}" data-key="{{key}}"> | ||||||
|  |             <i class="fas fa-dice-d20"></i> | ||||||
|  |           </span> | ||||||
|  |         </Fieldset> | ||||||
|  |  | ||||||
|  |       </div> | ||||||
|  |  | ||||||
|  |     </Fieldset> | ||||||
|  |   {{/each}} | ||||||
|  | </section> | ||||||
		Reference in New Issue
	
	Block a user