Skip to content

Commit

Permalink
feat(knockback): show knockback rolls and skin them
Browse files Browse the repository at this point in the history
  • Loading branch information
phBalance authored and phBalance committed Sep 15, 2024
1 parent 9b2bfee commit 7956aa9
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 82 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Releases

## Version 3.0.96 [Hero System 6e (Unofficial) v2](https://github.com/dmdorman/hero6e-foundryvtt)
## Version 3.0.97 (So far...) [Hero System 6e (Unofficial) v2](https://github.com/dmdorman/hero6e-foundryvtt)

- Fix apply knockback dialog for Firefox.
- Applying knockback now rolls knockback skinned dice.

## Version 3.0.96

- Fixes for combat tracker edge cases.

Expand Down
18 changes: 11 additions & 7 deletions module/item/item-attack.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { performAdjustment, renderAdjustmentChatCards } from "../utility/adjustm
import { getRoundedDownDistanceInSystemUnits, getSystemDisplayUnits } from "../utility/units.mjs";
import { HeroSystem6eItem, RequiresASkillRollCheck } from "../item/item.mjs";
import { ItemAttackFormApplication } from "../item/item-attack-application.mjs";
import { HeroRoller } from "../utility/dice.mjs";
import { DICE_SO_NICE_CUSTOM_SETS, HeroRoller } from "../utility/dice.mjs";
import { clamp } from "../utility/compatibility.mjs";
import { calculateVelocityInSystemUnits } from "../ruler.mjs";
import { Attack } from "../utility/attack.mjs";
Expand Down Expand Up @@ -1153,7 +1153,10 @@ export async function _onRollKnockback(event) {
async function _rollApplyKnockback(token, knockbackDice) {
const actor = token.actor;

const damageRoller = new HeroRoller().addDice(parseInt(knockbackDice), "Knockback").makeNormalRoll();
const damageRoller = new HeroRoller()
.setPurpose(DICE_SO_NICE_CUSTOM_SETS.KNOCKBACK)
.addDice(parseInt(knockbackDice), "Knockback")
.makeNormalRoll();
await damageRoller.roll();

const damageRenderedResult = await damageRoller.render();
Expand Down Expand Up @@ -1267,8 +1270,9 @@ async function _rollApplyKnockback(token, knockbackDice) {
const speaker = ChatMessage.getSpeaker({ actor: actor });

const chatData = {
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
rolls: damageRoller.rawRolls(),
user: game.user._id,

content: cardHtml,
speaker: speaker,
};
Expand Down Expand Up @@ -2225,6 +2229,8 @@ export async function _onApplyDamageToSpecificToken(event, tokenId) {
const speaker = ChatMessage.getSpeaker({ actor: item.actor });

const chatData = {
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
rolls: damageDetail.knockbackRoller?.rawRolls(),
user: game.user._id,
content: cardHtml,
speaker: speaker,
Expand Down Expand Up @@ -2801,11 +2807,9 @@ async function _calcKnockback(body, item, options, knockbackMultiplier) {
}

knockbackRoller = new HeroRoller()
.setPurpose(DICE_SO_NICE_CUSTOM_SETS.KNOCKBACK)
.makeBasicRoll()
.addNumber(
body * (knockbackMultiplier > 1 ? knockbackMultiplier : 1), // TODO: Consider supporting multiplication in HeroRoller
"Max potential knockback",
)
.addNumber(body * (knockbackMultiplier > 1 ? knockbackMultiplier : 1), "Max potential knockback")
.addNumber(-parseInt(options.knockbackResistance || 0), "Knockback resistance")
.addDice(-Math.max(0, knockbackDice));
await knockbackRoller.roll();
Expand Down
133 changes: 59 additions & 74 deletions module/utility/dice.mjs
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
import { isGameV12OrLater } from "./compatibility.mjs";

const DICE_SO_NICE_CUSTOM_SETS = {
STUNx: {
colorset: "Stun Multiplier",
foreground: "white",
background: "blue",
edge: "blue",
material: "wood",
fontScale: {
d6: 1.1,
},
visibility: "visible",
},
export const DICE_SO_NICE_CUSTOM_SETS = {
HIT_LOC: {
colorset: "Hit Location - Body Part",
foreground: "black",
Expand All @@ -34,10 +23,30 @@ const DICE_SO_NICE_CUSTOM_SETS = {
},
visibility: "visible",
},
KNOCKBACK: {
colorset: "Knockback",
foreground: "black",
background: "orange",
edge: "orange",
material: "wood",
fontScale: {
d6: 1.1,
},
visibility: "visible",
},
STUNx: {
colorset: "Stun Multiplier",
foreground: "white",
background: "blue",
edge: "blue",
material: "wood",
fontScale: {
d6: 1.1,
},
visibility: "visible",
},
};

const DICE_SO_NICE_CATEGORY_NAME = "Hero System 6e (Unofficial) V2";

// v11/v12 compatibility shim.
// TODO: Cleanup eslint file with these terms
const Die = CONFIG.Dice.terms.d;
Expand All @@ -48,46 +57,26 @@ const OperatorTerm = CONFIG.Dice.termTypes.OperatorTerm;
const RollTermClass = foundry.dice?.terms.RollTerm ? foundry.dice.terms.RollTerm : RollTerm;

/**
* Add colour sets into Dice So Nice! This allows users to see what the colour set is for each function.
* Add our custom colour sets into Dice So Nice! This allows users to see what the colour set is for each function.
* Players can then choose to use that theme for maximum confusion as to which are their rolls and which
* are the extras for hit location or stun multiplier.
* are the extras for hit location, stun multiplier, etc.
*/
Hooks.once("diceSoNiceReady", (diceSoNice) => {
diceSoNice.addColorset(
{
...{
name: "Stun Multiplier",
description: "Stun Multiplier Dice",
category: DICE_SO_NICE_CATEGORY_NAME,
},
...DICE_SO_NICE_CUSTOM_SETS.STUNx,
},
"default",
);

diceSoNice.addColorset(
{
...{
name: "Hit Location - Body Part",
description: "Hit Location - Body Part Dice",
category: DICE_SO_NICE_CATEGORY_NAME,
},
...DICE_SO_NICE_CUSTOM_SETS.HIT_LOC,
},
"default",
);

diceSoNice.addColorset(
{
...{
name: "Hit Location - Body Side",
description: "Hit Location - Body Side Dice",
category: DICE_SO_NICE_CATEGORY_NAME,
Object.keys(DICE_SO_NICE_CUSTOM_SETS).forEach((key) => {
const customSet = DICE_SO_NICE_CUSTOM_SETS[key];

diceSoNice.addColorset(
{
...{
name: customSet.colorset,
description: `${customSet.colorset} Dice`,
category: game.system.title,
},
...customSet,
},
...DICE_SO_NICE_CUSTOM_SETS.HIT_LOC_SIDE,
},
"default",
);
"default",
);
});
});

/**
Expand Down Expand Up @@ -322,6 +311,20 @@ export class HeroRoller {
return this;
}

/**
*
* @param {DICE_SO_NICE_CUSTOM_SETS} purpose
* @returns {HeroRoller}
*/
setPurpose(purpose) {
if (purpose && game.settings.get(game.system.id, "DiceSkinning")) {
if (!this._options) this._options = {};
this._options.appearance = foundry.utils.deepClone(purpose);
}

return this;
}

/**
* V11 and V12 (or later) behave differently. V11 can have a operatorTerm to start
* terms but it cannot have negative dice terms. V12, on the other hand, cannot handle
Expand Down Expand Up @@ -966,14 +969,8 @@ export class HeroRoller {
if (this._type === HeroRoller.ROLL_TYPE.KILLING && !this._useHitLocation) {
// NOTE: It appears there is no standard effect for the STUNx per APG p 53
// although there don't appear to be any mention of this in other books.
this._killingStunMultiplierHeroRoller = new HeroRoller(
game.settings.get(game.system.id, "DiceSkinning")
? {
appearance: foundry.utils.deepClone(DICE_SO_NICE_CUSTOM_SETS.STUNx),
}
: {},
this._buildRollClass,
)
this._killingStunMultiplierHeroRoller = new HeroRoller({}, this._buildRollClass)
.setPurpose(DICE_SO_NICE_CUSTOM_SETS.STUNx)
.makeBasicRoll()
.addDieMinus1Min1(this._killingStunMultiplier === "1d6-1" ? 1 : 0)
.addHalfDice(this._killingStunMultiplier === "1d3" ? 1 : 0);
Expand All @@ -997,14 +994,8 @@ export class HeroRoller {
let locationName;

if (this._alreadyHitLocation === "none") {
this._hitLocationRoller = new HeroRoller(
game.settings.get(game.system.id, "DiceSkinning")
? {
appearance: foundry.utils.deepClone(DICE_SO_NICE_CUSTOM_SETS.HIT_LOC),
}
: {},
this._buildRollClass,
)
this._hitLocationRoller = new HeroRoller({}, this._buildRollClass)
.setPurpose(DICE_SO_NICE_CUSTOM_SETS.HIT_LOC)
.makeBasicRoll()
.addDice(3);
await this._hitLocationRoller.roll();
Expand All @@ -1021,14 +1012,8 @@ export class HeroRoller {
CONFIG.HERO.sidedLocations.has(locationName) &&
this._alreadyHitLocationSide === "none"
) {
this._hitSideRoller = new HeroRoller(
game.settings.get(game.system.id, "DiceSkinning")
? {
appearance: foundry.utils.deepClone(DICE_SO_NICE_CUSTOM_SETS.HIT_LOC_SIDE),
}
: {},
this._buildRollClass,
)
this._hitSideRoller = new HeroRoller({}, this._buildRollClass)
.setPurpose(DICE_SO_NICE_CUSTOM_SETS.HIT_LOC_SIDE)
.makeBasicRoll()
.addDice(1);
await this._hitSideRoller.roll();
Expand Down

0 comments on commit 7956aa9

Please sign in to comment.