ENH: Chargen
							parent
							
								
									0ea0e25fba
								
							
						
					
					
						commit
						197d88eeb3
					
				
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 259 KiB After Width: | Height: | Size: 232 KiB | 
|  | @ -110,11 +110,6 @@ | |||
|               wether your monster has a survival instinct or will fight till the | ||||
|               end. | ||||
|             </li> | ||||
|             <li><strong>Variable weapon damage</strong>:By default, even if the | ||||
|               damage field is shown in the weapons sheets, the rolled damage | ||||
|               will always be a d6, except for monsters. With this enabled, the | ||||
|               damage displayed will be effectively used for characters. | ||||
|             </li> | ||||
|             <li><strong>Encumbrance</strong>:The weight a character is carrying | ||||
|               is a significant part of the players treasure hunting adventures. | ||||
|               You have three options here. | ||||
|  | @ -493,7 +488,7 @@ | |||
|               <img src="./images/treasure-toggle.png" /> | ||||
|             </p> | ||||
|             <p> | ||||
|               You can toggle between the default rollable tables and the treasure table. | ||||
|               You can toggle between the default rollable tables and the treasure table with the Chest icon right next to the table name. | ||||
|               The default tables are selecting an entry by rolling a dice and returning the matching result. Treasure tables however, have a different behavior. Each entry is rolled with 1d100 and the value is compared to the 'chance field'. So it can return multiple items. | ||||
|             </p> | ||||
|             <p> | ||||
|  |  | |||
|  | @ -15,7 +15,9 @@ | |||
|   "OSE.dialog.partysheet": "Party Overview", | ||||
|   "OSE.dialog.selectActors": "Select PCs", | ||||
|   "OSE.dialog.dealXP": "Deal XP", | ||||
|   "OSE.dialog.generator": "Character generator", | ||||
|   "OSE.dialog.generateSaves": "Generate Saves", | ||||
|   "OSE.dialog.generateScore": "Rolling {score}", | ||||
| 
 | ||||
|   "OSE.Formula": "Formula", | ||||
|   "OSE.SitMod": "Situational Modifier", | ||||
|  | @ -162,8 +164,6 @@ | |||
|   "OSE.Setting.AscendingACHint": "The more the better", | ||||
|   "OSE.Setting.Morale": "Enable monsters Morale Rating", | ||||
|   "OSE.Setting.MoraleHint": "Morale Rating is shown on monster sheets", | ||||
|   "OSE.Setting.VariableWeaponDamage": "Variable Weapon Damage", | ||||
|   "OSE.Setting.VariableWeaponDamageHint": "Weapons have different damage dice", | ||||
|   "OSE.Setting.Encumbrance": "Encumbrance", | ||||
|   "OSE.Setting.EncumbranceHint": "Choose the way encumbrance is calculated", | ||||
|   "OSE.Setting.EncumbranceDisabled": "Disabled", | ||||
|  |  | |||
|  | @ -147,8 +147,6 @@ | |||
|   "OSE.Setting.AscendingACHint": "En cuanto más mejor", | ||||
|   "OSE.Setting.Morale": "Activar puntuación de Moral para monstruos", | ||||
|   "OSE.Setting.MoraleHint": "La puntuación de moral se ve en las hojas de monstruo", | ||||
|   "OSE.Setting.VariableWeaponDamage": "Daño de arma variable", | ||||
|   "OSE.Setting.VariableWeaponDamageHint": "Las armas tienen diferente dado de daño", | ||||
|   "OSE.Setting.Encumbrance": "Carga", | ||||
|   "OSE.Setting.EncumbranceHint": "Elige como se calcula la Carga", | ||||
|   "OSE.Setting.EncumbranceDisabled": "Disabled", | ||||
|  |  | |||
|  | @ -161,8 +161,6 @@ | |||
|   "OSE.Setting.AscendingACHint": "Le plus est le mieux", | ||||
|   "OSE.Setting.Morale": "Activer le Score de Moral", | ||||
|   "OSE.Setting.MoraleHint": "Le Score de Moral est affiché sur la fiche de Monstre", | ||||
|   "OSE.Setting.VariableWeaponDamage": "Dégâts d'Arme Variables", | ||||
|   "OSE.Setting.VariableWeaponDamageHint": "Les Armes peuvent avoir des dégâts d'arme différents", | ||||
|   "OSE.Setting.Encumbrance": "Encombrement", | ||||
|   "OSE.Setting.EncumbranceHint": "Choisissez comment l'encombrement est calculé", | ||||
|   "OSE.Setting.EncumbranceDisabled": "Désactivé", | ||||
|  |  | |||
|  | @ -57,11 +57,6 @@ export class OseActorSheetCharacter extends OseActorSheet { | |||
|   getData() { | ||||
|     const data = super.getData(); | ||||
| 
 | ||||
|     // Settings
 | ||||
|     data.config.variableWeaponDamage = game.settings.get( | ||||
|       "ose", | ||||
|       "variableWeaponDamage" | ||||
|     ); | ||||
|     data.config.ascendingAC = game.settings.get("ose", "ascendingAC"); | ||||
|     data.config.individualInit = game.settings.get("ose", "individualInit"); | ||||
|     data.config.encumbrance = game.settings.get("ose", "encumbranceOption"); | ||||
|  |  | |||
|  | @ -69,7 +69,7 @@ export class OseActor extends Actor { | |||
|   } | ||||
| 
 | ||||
|   generator() { | ||||
|      | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   generateSave(hd) { | ||||
|  | @ -274,6 +274,9 @@ export class OseActor extends Actor { | |||
|   rollHitDice(options = {}) { | ||||
|     const label = game.i18n.localize(`OSE.roll.hd`); | ||||
|     const rollParts = [this.data.data.hp.hd]; | ||||
|     if (this.data.type == 'character') { | ||||
|       rollParts.push(this.data.data.scores.con.mod); | ||||
|     } | ||||
| 
 | ||||
|     const data = { | ||||
|       ...this.data, | ||||
|  | @ -373,10 +376,7 @@ export class OseActor extends Actor { | |||
|     }; | ||||
| 
 | ||||
|     let dmgParts = []; | ||||
|     if ( | ||||
|       (!attData.dmg || !game.settings.get("ose", "variableWeaponDamage")) && | ||||
|       this.type == "character" | ||||
|     ) { | ||||
|     if (!attData.dmg) { | ||||
|       dmgParts.push("1d6"); | ||||
|     } else { | ||||
|       dmgParts.push(attData.dmg); | ||||
|  | @ -404,11 +404,7 @@ export class OseActor extends Actor { | |||
|     const rollParts = ["1d20"]; | ||||
|     const dmgParts = []; | ||||
|     let label = game.i18n.format("OSE.roll.attacks", { name: this.data.name }); | ||||
|     if ( | ||||
|       !attData.dmg || | ||||
|       (!game.settings.get("ose", "variableWeaponDamage") && | ||||
|         this.data.type == "character") | ||||
|     ) { | ||||
|     if (!attData.dmg) { | ||||
|       dmgParts.push("1d6"); | ||||
|     } else { | ||||
|       label = game.i18n.format("OSE.roll.attacksWith", { name: attData.label }); | ||||
|  |  | |||
|  | @ -1,13 +1,14 @@ | |||
| // eslint-disable-next-line no-unused-vars
 | ||||
| import { OseActor } from '../actor/entity.js'; | ||||
| import { OseDice } from "../dice.js"; | ||||
| 
 | ||||
| export class OseCharacterCreator extends FormApplication { | ||||
|   static get defaultOptions() { | ||||
|     const options = super.defaultOptions; | ||||
|     options.classes = ["ose", "dialog", "creator"], | ||||
|     options.id = 'character-creator'; | ||||
|     options.template = | ||||
|       'systems/ose/templates/actors/dialogs/character-creation.html'; | ||||
|     options.width = 380; | ||||
|     options.width = 235; | ||||
|     return options; | ||||
|   } | ||||
| 
 | ||||
|  | @ -18,7 +19,7 @@ export class OseCharacterCreator extends FormApplication { | |||
|    * @type {String} | ||||
|    */ | ||||
|   get title() { | ||||
|     return `${this.object.name}: ${game.i18n.localize('OSE.dialog.tweaks')}`; | ||||
|     return `${this.object.name}: ${game.i18n.localize('OSE.dialog.generator')}`; | ||||
|   } | ||||
| 
 | ||||
|   /* -------------------------------------------- */ | ||||
|  | @ -36,9 +37,66 @@ export class OseCharacterCreator extends FormApplication { | |||
| 
 | ||||
|   /* -------------------------------------------- */ | ||||
| 
 | ||||
|   doStats(ev) { | ||||
|     let list = $(ev.currentTarget).closest('.attribute-list'); | ||||
|     let values = []; | ||||
|     list.find('.score-value').each((i, s) => { | ||||
|       if (s.value != 0) { | ||||
|         values.push(parseInt(s.value)); | ||||
|       } | ||||
|     }) | ||||
| 
 | ||||
|     let n = values.length; | ||||
|     let sum = values.reduce((a,b) => a+b); | ||||
|     let mean = parseFloat(sum) / n; | ||||
|     let std = Math.sqrt(values.map(x => Math.pow(x-mean,2)).reduce((a,b) => a+b)/n); | ||||
| 
 | ||||
|     let stats = list.siblings('.roll-stats'); | ||||
|     stats.find('.sum').text(sum); | ||||
|     stats.find('.avg').text(Math.round(10 * sum / n) / 10); | ||||
|     stats.find('.std').text(Math.round(100 * std) / 100); | ||||
|     if (n >= 6) { | ||||
|       $(ev.currentTarget).closest('form').find('button[type="submit"]').removeAttr('disabled'); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   rollScore(score, options={}) { | ||||
|     const label = game.i18n.localize(`OSE.scores.${score}.long`); | ||||
|     const rollParts = ["3d6"]; | ||||
|     const data = { | ||||
|       ...this.object.data, | ||||
|       ...{ | ||||
|         rollData: { | ||||
|           type: "result" | ||||
|         }, | ||||
|       }, | ||||
|     }; | ||||
|     // Roll and return
 | ||||
|     return OseDice.Roll({ | ||||
|       event: options.event, | ||||
|       parts: rollParts, | ||||
|       data: data, | ||||
|       skipDialog: true, | ||||
|       speaker: ChatMessage.getSpeaker({ actor: this }), | ||||
|       flavor: game.i18n.format('OSE.dialog.generateScore', {score: label}), | ||||
|       title: game.i18n.format('OSE.dialog.generateScore', {score: label}), | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   /** @override */ | ||||
|   activateListeners(html) { | ||||
|     super.activateListeners(html); | ||||
|     html.find('a.score-roll').click((ev) => { | ||||
|       let el = ev.currentTarget.parentElement.parentElement; | ||||
|       let score = el.dataset.score; | ||||
|       this.rollScore(score, {event: ev}).then(r => { | ||||
|         $(el).find('input').val(r.total).trigger('change'); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     html.find('input.score-value').change(ev => { | ||||
|       this.doStats(ev); | ||||
|     }) | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  |  | |||
|  | @ -103,12 +103,12 @@ export class OseDice { | |||
|               ) | ||||
|               .then((displayed) => { | ||||
|                 ChatMessage.create(chatData); | ||||
|                 resolve(); | ||||
|                 resolve(roll); | ||||
|               }); | ||||
|           } else { | ||||
|             chatData.sound = CONFIG.sounds.dice; | ||||
|             ChatMessage.create(chatData); | ||||
|             resolve(); | ||||
|             resolve(roll); | ||||
|           } | ||||
|         }); | ||||
|       }); | ||||
|  | @ -215,17 +215,17 @@ export class OseDice { | |||
|                       ) | ||||
|                       .then(() => { | ||||
|                         ChatMessage.create(chatData); | ||||
|                         resolve(); | ||||
|                         resolve(roll); | ||||
|                       }); | ||||
|                   } else { | ||||
|                     ChatMessage.create(chatData); | ||||
|                     resolve(); | ||||
|                     resolve(roll); | ||||
|                   } | ||||
|                 }); | ||||
|             } else { | ||||
|               chatData.sound = CONFIG.sounds.dice; | ||||
|               ChatMessage.create(chatData); | ||||
|               resolve(); | ||||
|               resolve(roll); | ||||
|             } | ||||
|           }); | ||||
|         }); | ||||
|  |  | |||
|  | @ -28,15 +28,6 @@ export const registerSettings = function () { | |||
|     config: true, | ||||
|   }); | ||||
| 
 | ||||
|   game.settings.register("ose", "variableWeaponDamage", { | ||||
|     name: game.i18n.localize("OSE.Setting.VariableWeaponDamage"), | ||||
|     hint: game.i18n.localize("OSE.Setting.VariableWeaponDamageHint"), | ||||
|     default: false, | ||||
|     scope: "world", | ||||
|     type: Boolean, | ||||
|     config: true, | ||||
|   }); | ||||
| 
 | ||||
|   game.settings.register("ose", "encumbranceOption", { | ||||
|     name: game.i18n.localize("OSE.Setting.Encumbrance"), | ||||
|     hint: game.i18n.localize("OSE.Setting.EncumbranceHint"), | ||||
|  |  | |||
|  | @ -5,6 +5,33 @@ | |||
|   } | ||||
| } | ||||
| 
 | ||||
| .ose.dialog.creator { | ||||
|   .attribute-list { | ||||
|     .form-fields { | ||||
|       flex: 0 0 50px; | ||||
|       input { | ||||
|         text-align: center; | ||||
|         font-weight: bold; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   .roll-stats { | ||||
|     flex: 0 0 65px; | ||||
|     padding: 5px; | ||||
|     margin-left: 4px; | ||||
|     border-left: 1px solid $colorTan; | ||||
|     .form-group { | ||||
|       .form-fields { | ||||
|         span { | ||||
|           text-align: center; | ||||
|           line-height: 24px; | ||||
|           flex: 0; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .ose.dialog.party-sheet { | ||||
|   min-width: 250px; | ||||
|   min-height: 250px; | ||||
|  | @ -45,7 +72,7 @@ | |||
|       margin-bottom: 2px; | ||||
|       font-size: 12px; | ||||
|       text-align: center; | ||||
|       .fields .field-row{ | ||||
|       .fields .field-row { | ||||
|         &:nth-child(odd) { | ||||
|           background-color: rgba(0, 0, 0, 0.1); | ||||
|         } | ||||
|  | @ -95,7 +122,7 @@ | |||
| #sidebar #actors .directory-header .header-search { | ||||
|   .ose-party-sheet { | ||||
|     width: 32px; | ||||
|     text-align: center;  | ||||
|     text-align: center; | ||||
|     line-height: 20px; | ||||
|   } | ||||
|   input { | ||||
|  | @ -120,7 +147,7 @@ | |||
|       flex: 0 0 30px; | ||||
|       font-size: 26px; | ||||
|       line-height: 25px; | ||||
|       color:white; | ||||
|       color: white; | ||||
|       margin: 0 2px 5px 8px; | ||||
|       border-radius: 8px; | ||||
|       background: url("/systems/ose/assets/chest.png") no-repeat center; | ||||
|  | @ -128,7 +155,8 @@ | |||
|       padding: 5px 8px; | ||||
|       cursor: pointer; | ||||
|       filter: grayscale(1) opacity(0.5); | ||||
|       &.active,&:hover { | ||||
|       &.active, | ||||
|       &:hover { | ||||
|         filter: none; | ||||
|       } | ||||
|     } | ||||
|  | @ -172,12 +200,15 @@ | |||
|     box-shadow: 0 0 2px #fff inset; | ||||
|     .chat-title { | ||||
|       margin: 4px 0; | ||||
|       height: 30px; | ||||
|       overflow: hidden; | ||||
|       h2 { | ||||
|         border: none; | ||||
|         line-height: 34px; | ||||
|         margin: 0; | ||||
|         text-indent: 10px; | ||||
|         font-size: 16px; | ||||
|         word-break: break-all; | ||||
|       } | ||||
|     } | ||||
|     .chat-img { | ||||
|  |  | |||
|  | @ -1,7 +1,39 @@ | |||
| <form autocomplete="off" onsubmit="event.preventDefault();"> | ||||
|     <ol class="attribute-list"> | ||||
|         {{#each config.scores as |score id| }} | ||||
|         <li data-score="{{id}}">{{score}}</li> | ||||
|         {{/each}} | ||||
|     </ol> | ||||
|     <div class="flexrow"> | ||||
|         <div class="attribute-list"> | ||||
|             {{#each config.scores as |score id| }} | ||||
|             <div data-score="{{id}}" class="form-group"> | ||||
|                 <label><a class="score-roll"><i class="fas fa-dice"></i></a> {{score}}</label> | ||||
|                 <div class="form-fields"> | ||||
|                     <input class="score-value" name="data.scores.{{id}}.value" type="text" value="0" data-dtype="Number"/> | ||||
|                 </div> | ||||
|             </div> | ||||
|             {{/each}} | ||||
|         </div> | ||||
|         <div class="roll-stats"> | ||||
|             <div class="form-group"> | ||||
|                 <label>Sum</label> | ||||
|                 <div class="form-fields"> | ||||
|                     <span class="sum">0</span> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="form-group"> | ||||
|                 <label>Avg</label> | ||||
|                 <div class="form-fields"> | ||||
|                     <span class="avg">0</span> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="form-group"> | ||||
|                 <label>σ</label> | ||||
|                 <div class="form-fields"> | ||||
|                     <span class="std">0</span> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|     <footer class="sheet-footer"> | ||||
|       <button type="submit" disabled> | ||||
|         <i class="fas fa-save"></i>{{localize "Save Changes"}} | ||||
|       </button> | ||||
|     </footer> | ||||
| </form> | ||||
		Loading…
	
		Reference in New Issue