WIP: Treasure tables, hp rolls
parent
2acc9992f5
commit
e1319b6215
|
@ -222,6 +222,7 @@ async function clean() {
|
|||
"lang",
|
||||
"templates",
|
||||
"assets",
|
||||
"packs",
|
||||
"module",
|
||||
`${name}.js`,
|
||||
"module.json",
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
"OSE.Ok": "Ok",
|
||||
"OSE.Cancel": "Cancel",
|
||||
"OSE.Roll": "Roll",
|
||||
"OSE.Success": "Success",
|
||||
"OSE.Failure": "Failure",
|
||||
|
||||
"OSE.Formula": "Formula",
|
||||
"OSE.SitMod": "Situational Modifier",
|
||||
|
@ -20,6 +22,8 @@
|
|||
"OSE.Experience": "Experience",
|
||||
"OSE.ExperienceBonus": "Bonus Experience",
|
||||
"OSE.Treasure": "Treasure type",
|
||||
"OSE.TreasureTable": "Table",
|
||||
"OSE.TreasureTableHint": "Drop a rollable table here to roll the monster treasure",
|
||||
"OSE.Size": "Size",
|
||||
"OSE.Morale": "Morale",
|
||||
"OSE.Retainer": "Retainer",
|
||||
|
|
|
@ -125,6 +125,11 @@ export class OseActorSheet extends ActorSheet {
|
|||
actorObject.rollAttack({label: this.actor.name, type: attack}, { event: event });
|
||||
});
|
||||
|
||||
html.find(".hit-dice .attribute-name a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
actorObject.rollHitDice({ event: event });
|
||||
});
|
||||
|
||||
super.activateListeners(html);
|
||||
}
|
||||
|
||||
|
|
|
@ -146,11 +146,6 @@ export class OseActorSheetCharacter extends OseActorSheet {
|
|||
actorObject.rollCheck(score, { event: event });
|
||||
});
|
||||
|
||||
html.find(".hit-dice .attribute-name a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
actorObject.rollHitDice({ event: event });
|
||||
});
|
||||
|
||||
html.find(".exploration .attribute-name a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
let element = event.currentTarget;
|
||||
|
|
|
@ -26,22 +26,42 @@ export class OseActor extends Actor {
|
|||
/* Socket Listeners and Handlers
|
||||
/* -------------------------------------------- */
|
||||
getExperience(value, options = {}) {
|
||||
console.log(this.data);
|
||||
if (this.data.type != 'character') {
|
||||
if (this.data.type != "character") {
|
||||
return;
|
||||
}
|
||||
let modified = value + (this.data.data.details.xp.bonus * value) / 100;
|
||||
console.log(modified);
|
||||
let modified = Math.floor(
|
||||
value + (this.data.data.details.xp.bonus * value) / 100
|
||||
);
|
||||
return this.update({
|
||||
"data.details.xp.value": modified + this.data.data.details.xp.value
|
||||
"data.details.xp.value": modified + this.data.data.details.xp.value,
|
||||
}).then(() => {
|
||||
const speaker = ChatMessage.getSpeaker({actor: this});
|
||||
ChatMessage.create({content: game.i18n.format("OSE.messages.getExperience", {name: this.name, value: modified}), speaker});
|
||||
const speaker = ChatMessage.getSpeaker({ actor: this });
|
||||
ChatMessage.create({
|
||||
content: game.i18n.format("OSE.messages.getExperience", {
|
||||
name: this.name,
|
||||
value: modified,
|
||||
}),
|
||||
speaker,
|
||||
});
|
||||
});
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
/* Rolls */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
rollHP(options = {}) {
|
||||
let roll = new Roll(this.data.data.hp.hd).roll();
|
||||
console.log(roll);
|
||||
return this.update({
|
||||
data: {
|
||||
hp: {
|
||||
max: roll.total,
|
||||
value: roll.total,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
rollSave(save, options = {}) {
|
||||
const label = game.i18n.localize(`OSE.saves.${save}.long`);
|
||||
const rollParts = ["1d20"];
|
||||
|
@ -57,7 +77,7 @@ export class OseActor extends Actor {
|
|||
};
|
||||
|
||||
let skip = options.event && options.event.ctrlKey;
|
||||
|
||||
|
||||
// Roll and return
|
||||
return OseDice.Roll({
|
||||
event: options.event,
|
||||
|
@ -132,7 +152,7 @@ export class OseActor extends Actor {
|
|||
...this.data,
|
||||
...{
|
||||
rollData: {
|
||||
type: "Hit Dice"
|
||||
type: "Hit Dice",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -186,20 +206,20 @@ export class OseActor extends Actor {
|
|||
rollData: {
|
||||
type: "Damage",
|
||||
stat: attData.type,
|
||||
scores: data.scores
|
||||
scores: data.scores,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let dmgParts = [];
|
||||
if (!attData.dmg || !game.settings.get('ose', 'variableWeaponDamage')) {
|
||||
if (!attData.dmg || !game.settings.get("ose", "variableWeaponDamage")) {
|
||||
dmgParts.push("1d6");
|
||||
} else {
|
||||
dmgParts.push(attData.dmg);
|
||||
}
|
||||
|
||||
// Add Str to damage
|
||||
if (attData.type == 'melee') {
|
||||
if (attData.type == "melee") {
|
||||
dmgParts.push(data.scores.str.mod);
|
||||
}
|
||||
|
||||
|
@ -212,7 +232,7 @@ export class OseActor extends Actor {
|
|||
speaker: ChatMessage.getSpeaker({ actor: this }),
|
||||
flavor: `${attData.label} - ${game.i18n.localize("OSE.Damage")}`,
|
||||
title: `${attData.label} - ${game.i18n.localize("OSE.Damage")}`,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
rollAttack(attData, options = {}) {
|
||||
|
@ -240,7 +260,7 @@ export class OseActor extends Actor {
|
|||
rollData: {
|
||||
type: "Attack",
|
||||
stat: attData.type,
|
||||
scores: data.scores
|
||||
scores: data.scores,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -140,6 +140,11 @@ export class OseActorSheetMonster extends OseActorSheet {
|
|||
actorObject.rollMorale({ event: event });
|
||||
});
|
||||
|
||||
html.find(".hp-roll").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
actorObject.rollHP({ event: event });
|
||||
});
|
||||
|
||||
// Handle default listeners last so system listeners are triggered first
|
||||
super.activateListeners(html);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
export class OseDice {
|
||||
static digestResult(data, roll) {
|
||||
let details = "";
|
||||
let result = {
|
||||
isSuccess: false,
|
||||
isFailure: false,
|
||||
target: "",
|
||||
};
|
||||
// ATTACKS
|
||||
let die = roll.parts[0].total;
|
||||
if (data.rollData.type == "Attack") {
|
||||
|
@ -11,12 +15,12 @@ export class OseDice {
|
|||
} else if (data.rollData.stat == "missile") {
|
||||
bba += data.data.thac0.mod.missile + data.rollData.scores.dex.mod;
|
||||
}
|
||||
|
||||
details = `<div class='roll-result roll-fail'><b>Failure</b> (${bba})</div>`;
|
||||
result.target = bba;
|
||||
if (die == 1) {
|
||||
return details;
|
||||
result.isFailure = true;
|
||||
return result;
|
||||
}
|
||||
details = `<div class='roll-result'><b>Hits AC ${roll.total}</b> (${bba})</div>`;
|
||||
result.isSuccess = true;
|
||||
} else {
|
||||
// B/X Historic THAC0 Calculation
|
||||
let thac = data.data.thac0.value;
|
||||
|
@ -25,11 +29,12 @@ export class OseDice {
|
|||
} else if (data.rollData.stat == "missile") {
|
||||
thac -= data.data.thac0.mod.missile + data.rollData.scores.dex.mod;
|
||||
}
|
||||
details = `<div class='roll-result roll-fail'><b>Failure</b> (${thac})</div>`;
|
||||
result.target = thac;
|
||||
if (thac - roll.total > 9) {
|
||||
return details;
|
||||
result.isFailure = true;
|
||||
return result;
|
||||
}
|
||||
details = `<div class='roll-result'><b>Hits AC ${Math.clamped(
|
||||
result.details = `<div class='roll-result'><b>Hits AC ${Math.clamped(
|
||||
thac - roll.total,
|
||||
-3,
|
||||
9
|
||||
|
@ -38,37 +43,41 @@ export class OseDice {
|
|||
} else if (data.rollData.type == "Above") {
|
||||
// SAVING THROWS
|
||||
let sv = data.rollData.target;
|
||||
result.target = sv;
|
||||
if (roll.total >= sv) {
|
||||
details = `<div class='roll-result roll-success'><b>Success!</b> (${sv})</div>`;
|
||||
result.isSuccess = true;
|
||||
} else {
|
||||
details = `<div class='roll-result roll-fail'><b>Failure</b> (${sv})</div>`;
|
||||
result.isFailure = true;
|
||||
}
|
||||
} else if (data.rollData.type == "Below") {
|
||||
// Morale
|
||||
let m = data.rollData.target;
|
||||
result.target = m;
|
||||
if (roll.total <= m) {
|
||||
details = `<div class='roll-result roll-success'><b>Success!</b> (${m})</div>`;
|
||||
result.isSuccess = true;
|
||||
} else {
|
||||
details = `<div class='roll-result roll-fail'><b>Failure</b> (${m})</div>`;
|
||||
result.isFailure = true;
|
||||
}
|
||||
} else if (data.rollData.type == "Check") {
|
||||
// SCORE CHECKS
|
||||
let sc = data.rollData.target;
|
||||
result.target = sc;
|
||||
if (die == 1 || (roll.total <= sc && die < 20)) {
|
||||
details = `<div class='roll-result roll-success'><b>Success!</b> (${sc})</div>`;
|
||||
result.isSuccess = true;
|
||||
} else {
|
||||
details = `<div class='roll-result roll-fail'><b>Failure</b> (${sc})</div>`;
|
||||
result.isFailure = true;
|
||||
}
|
||||
} else if (data.rollData.type == "Exploration") {
|
||||
// EXPLORATION CHECKS
|
||||
let sc = data.data.exploration[data.rollData.stat];
|
||||
result.target = sc;
|
||||
if (roll.total <= sc) {
|
||||
details = `<div class='roll-result roll-success'><b>Success!</b> (${sc})</div>`;
|
||||
result.isSuccess = true;
|
||||
} else {
|
||||
details = `<div class='roll-result roll-fail'><b>Failure</b> (${sc})</div>`;
|
||||
result.isFailure = true;
|
||||
}
|
||||
}
|
||||
return details;
|
||||
return result;
|
||||
}
|
||||
|
||||
static async sendRoll({
|
||||
|
@ -91,18 +100,18 @@ export class OseDice {
|
|||
flavor: flavor,
|
||||
data: data,
|
||||
};
|
||||
|
||||
|
||||
// Optionally include a situational bonus
|
||||
if (form !== null) data["bonus"] = form.bonus.value;
|
||||
if (data["bonus"]) parts.push(data["bonus"]);
|
||||
|
||||
|
||||
const roll = new Roll(parts.join("+"), data).roll();
|
||||
|
||||
// Convert the roll to a chat message and return the roll
|
||||
let rollMode = game.settings.get("core", "rollMode");
|
||||
rollMode = form ? form.rollMode.value : rollMode;
|
||||
|
||||
templateData.details = OseDice.digestResult(data, roll);
|
||||
templateData.result = OseDice.digestResult(data, roll);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
roll.render().then((r) => {
|
||||
|
|
|
@ -14,14 +14,15 @@
|
|||
.chat-details {
|
||||
padding: 4px;
|
||||
font-size: 13px;
|
||||
.roll-result {
|
||||
text-align: center;
|
||||
&.roll-success {
|
||||
color: #18520b;
|
||||
}
|
||||
&.roll-fail {
|
||||
color: #aa0200;
|
||||
}
|
||||
}
|
||||
.roll-result {
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
&.roll-success {
|
||||
color: #18520b;
|
||||
}
|
||||
&.roll-fail {
|
||||
color: #aa0200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,21 @@
|
|||
min-width: 75px;
|
||||
}
|
||||
}
|
||||
.attributes {
|
||||
.attribute.health {
|
||||
position: relative;
|
||||
.attribute-name .hp-roll {
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
color: $colorFaint;
|
||||
&:hover {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.attribute-group {
|
||||
.attacks-description {
|
||||
margin: 2px;
|
||||
|
|
|
@ -9,7 +9,15 @@
|
|||
"author": "U~man",
|
||||
"esmodules": ["ose.js"],
|
||||
"styles": ["ose.css"],
|
||||
"packs": [],
|
||||
"packs": [
|
||||
{
|
||||
"name": "OSEMacros",
|
||||
"label": "Old School Essentials Macros",
|
||||
"system": "ose",
|
||||
"path": "./packs/macros.db",
|
||||
"entity": "Macro"
|
||||
}
|
||||
],
|
||||
"languages": [
|
||||
{
|
||||
"lang": "en",
|
||||
|
|
|
@ -141,7 +141,10 @@
|
|||
"biography": "",
|
||||
"alignment": "",
|
||||
"xp": 0,
|
||||
"treasure": "",
|
||||
"treasure": {
|
||||
"table": "",
|
||||
"type": ""
|
||||
},
|
||||
"appearing": "",
|
||||
"morale": 0
|
||||
},
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<section class="flexrow">
|
||||
<ul class="attributes flexrow">
|
||||
<li class="attribute health">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.Health'}}">{{ localize "OSE.HealthShort" }}</h4>
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.Health'}}">{{ localize "OSE.HealthShort" }} <a class="hp-roll"><i class="fas fa-dice"></i></a></h4>
|
||||
<div class="attribute-value flexrow">
|
||||
<input name="data.hp.value" type="text" value="{{data.hp.value}}" data-dtype="Number" placeholder="0" />
|
||||
<span class="sep"> / </span>
|
||||
<input name="data.hp.max" type="text" value="{{data.hp.max}}" data-dtype="Number" placeholder="0" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="attribute">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.HitDice'}}">{{ localize "OSE.HitDiceShort" }}
|
||||
<li class="attribute hit-dice">
|
||||
<h4 class="attribute-name box-title" title="{{localize 'OSE.HitDice'}}"><a>{{ localize "OSE.HitDiceShort" }}</a>
|
||||
</h4>
|
||||
<div class="attribute-value">
|
||||
<input name="data.hp.hd" type="text" value="{{data.hp.hd}}" data-dtype="String" />
|
||||
|
|
|
@ -23,13 +23,17 @@
|
|||
{{/if}}
|
||||
</ul>
|
||||
<ul class="summary flexrow">
|
||||
<li class="flex2">
|
||||
<li class="flex3">
|
||||
<input type="text" name="data.details.xp" value="{{data.details.xp}}" />
|
||||
<label>{{localize 'OSE.Experience'}}</label>
|
||||
</li>
|
||||
<li class="flex2">
|
||||
<input type="text" name="data.details.treasure" value="{{data.details.treasure}}" />
|
||||
<li class="flex3">
|
||||
<input type="text" name="data.details.treasure.type" value="{{data.details.treasure.type}}" />
|
||||
<label>{{localize 'OSE.Treasure'}}</label>
|
||||
</li>
|
||||
<li title="{{localize 'OSE.TreasureTableHint'}}">
|
||||
<div>{{data.details.treasure.table}}</div>
|
||||
<label>{{localize 'OSE.TreasureTable'}}</label>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
|
@ -1,7 +1,9 @@
|
|||
<section class="ose chat-message">
|
||||
<div class="ose chat-block">
|
||||
<h2 class="chat-title">{{title}}</h2>
|
||||
{{#if details}}<div class="chat-details">{{{details}}}</div>{{/if}}
|
||||
{{#if result.details}}<div class="chat-details">{{{result.details}}}</div>{{/if}}
|
||||
{{#if result.isFailure}}<div class='roll-result roll-fail'><b>{{localize 'OSE.Failure'}}</b> ({{result.target}})</div>{{/if}}
|
||||
{{#if result.isSuccess}}<div class='roll-result roll-success'><b>{{localize 'OSE.Success'}}</b> ({{result.target}})</div>{{/if}}
|
||||
{{#if rollOSE}}<div>{{{rollOSE}}}</div>{{/if}}
|
||||
</div>
|
||||
</section>
|
Loading…
Reference in New Issue