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