# FVTT Marco 指令紀錄
###### tags: `FVTT` `Macro`
```javascript=
//讀取特定ID的 actors 資料,get中的ID可以藉由點取內建的複製ID獲得
let Actor = game.actors.get('eQWaJFpubH0ueT27');
//開啟特定ID角色卡。
Actor.sheet.render(true);
//關閉特定ID角色卡。(只能關閉用上面方法開啟的角色表)
Actor.sheet.close();
//讓使用者主動切換遊戲場景
game.scenes.getName('場景名稱').view()
//重新更新房間內的所有縮圖(通常用於導入資料後沒有縮圖的情況)
(async () => {
for (const scene of game.scenes) {
const t = await scene.createThumbnail({img: scene.img || undefined});
if (t?.thumb) {
console.log(`Regenerated thumbnail for ${scene.name}`);
await scene.update({thumb: t.thumb});
}
}
})();
//如果有使用 Multiface Tiles 並且想用 Macro 來一次替換場景內的圖(僅限只設定一張圖的情況)
//替換成下一張圖
const tiles = canvas.scene.tiles.filter(t => t.getFlag("multiface-tiles", "altImages"));
const updates = tiles.map(t => ({_id: t.id, img: t.getFlag("multiface-tiles", "altImages")[0]}));
await canvas.scene.updateEmbeddedDocuments("Tile", updates);
//替換回原圖
const tiles = canvas.scene.tiles.filter(t => t.getFlag("multiface-tiles", "originalImage"));
const updates = tiles.map(t => ({ _id: t.id, img: t.getFlag("multiface-tiles", "originalImage")}));
await canvas.scene.updateEmbeddedDocuments("Tile", updates);
```
# Cypher System
```javascript=
//CypherSystem marco 快速設定token
for (let actor of game.actors) {
if (["pc", "community", "vehicle"].includes(actor.type)) {
actor.update({
"prototypeToken.displayName": CONST.TOKEN_DISPLAY_MODES.HOVER,
"prototypeToken.disposition": CONST.TOKEN_DISPOSITIONS.NEUTRAL,
"prototypeToken.actorLink": true
});
} else if (actor.type == "npc") {
actor.update({
"prototypeToken.bar1": {"attribute": "pools.health"},
"prototypeToken.bar2": {"attribute": "basic.level"},
"prototypeToken.displayName": CONST.TOKEN_DISPLAY_MODES.OWNER_HOVER,
"prototypeToken.displayBars": CONST.TOKEN_DISPLAY_MODES.OWNER,
"prototypeToken.disposition": CONST.TOKEN_DISPOSITIONS.NEUTRAL
});
} else if (actor.type == "companion") {
actor.update({
"prototypeToken.bar1": {"attribute": "pools.health"},
"prototypeToken.bar2": {"attribute": "basic.level"},
"prototypeToken.displayName": CONST.TOKEN_DISPLAY_MODES.OWNER_HOVER,
"prototypeToken.displayBars": CONST.TOKEN_DISPLAY_MODES.OWNER,
"prototypeToken.disposition": CONST.TOKEN_DISPOSITIONS.NEUTRAL,
"prototypeToken.actorLink": true
});
} else if (actor.type == "marker") {
actor.update({
"prototypeToken.bar1": {"attribute": "pools.quantity"},
"prototypeToken.bar2": {"attribute": "basic.level"},
"prototypeToken.displayName": CONST.TOKEN_DISPLAY_MODES.HOVER,
"prototypeToken.displayBars": CONST.TOKEN_DISPLAY_MODES.ALWAYS,
"prototypeToken.disposition": CONST.TOKEN_DISPOSITIONS.NEUTRAL
});
}
}
//運用PACK的表格來配合取物
(async () => {
const rollTablePack = game.packs.get("cyphersystem-compendium.cypher-roll-tables");
rollTablePack.getIndex();
console.log(rollTablePack);
ManifestRollTable = rollTablePack.index.find(t => t.name === 'Manifest Cyphers')._id;
FantasticRollTable = rollTablePack.index.find(t => t.name === 'Fantastic Cyphers')._id;
SubtleRollTable = rollTablePack.index.find(t => t.name === 'Subtle Cyphers')._id;
let Manifest_roll = await rollTablePack.getDocument(ManifestRollTable).then(table => table.roll());
let Fantastic_roll = await rollTablePack.getDocument(FantasticRollTable).then(table => table.roll());
let Subtle_roll = await rollTablePack.getDocument(SubtleRollTable).then(table => table.roll());
const compendiumName = Manifest_roll.results[0].documentCollection;
let results_html = `<h2>隨機秘具</h2>
<strong>有形秘具:</strong>@Compendium[${compendiumName}.${Manifest_roll.results[0].documentId}]<br>
<strong>無形秘具:</strong>@Compendium[${compendiumName}.${Fantastic_roll.results[0].documentId}]<br>
<strong>奇異秘具:</strong>@Compendium[${compendiumName}.${Subtle_roll.results[0].documentId}]<br>`;
let chatData = {
user: game.user._id,
speaker: ChatMessage.getSpeaker(),
content: results_html,
whisper: game.users.filter(u => u.isGM).map(u => u._id)
};
ChatMessage.create(chatData, {});
})();
```
# Invisible sun
用來替換 Dice so Nice! 擲骰內容的巨集
```javascript=
game.dice3d.addDicePreset({
type: 'd10',
labels: ['👁️', '1', '2', '3', '4', '5',
'6', '7', '8', '9'],
values: {min:0,max:9},
system: 'standard'
}, "d10");
```
擲骰巨集(中文化) V12
```javascript=
const content = `
<form>
<div class="form-group">
<label>骰子數</label>
<input type="number" value="1" name="rolls">
</div>
<div class="form-group">
<label>挑戰等級</label>
<input type="number" value="5" name="diff">
</div>
</form>
`;
const data = await Dialog.wait({
title: "擲骰器",
content,
buttons: {
ok: {
label: "擲骰!",
callback: ([html]) => new FormDataExtended(html.querySelector("form")).object
}
},
default: "none" // hacky way to avoid the v11 event bug passing to the button causing it to auto close.
});
let message = ``;
let results = ``;
let suxCount = 0;
let fluxCount = 0;
let numRolls=parseInt(`${data.rolls}`);
let diff=parseInt(`${data.diff}`);
if (numRolls < 1) { numRolls = 1; }
else if (numRolls > 5) { numRolls = 5; }
if (diff < 1) { diff = 1; }
else if (diff > 17) { diff = 17; }
for (let i=0; i < numRolls; i++) {
let roll = await new Roll(`1d10`).roll();
let tot = roll.total
if (roll.total === 10) {
tot = 0
}
if (i > 0 && tot === 0) {
fluxCount++;
}
results += `${tot}`
if (tot >= diff) { suxCount++; }
if (i < numRolls - 1) { results += `, ` }
if (i === 0) { game.dice3d.showForRoll(roll, game.user, true) }
if (i > 0) {
roll.dice[0].options.appearance = {
colorset: "custom",
foreground: "#59CBE8",
background: "#000000",
outline: "#000000",
edge: "#59CBE8",
material: "glass",
font: "Luminari",
emissive: "#59CBE8",
system: "standard"
};
game.dice3d.showForRoll(roll, game.user, true)
}
}
let fluxType = '';
switch(fluxCount) {
case 0: fluxType = '無影響'; break;
case 1: fluxType = '弱效'; break;
case 2: fluxType = '強效'; break;
default: fluxType = '宏大';
}
message = `難度:${diff}<br>擲骰結果:${results}<br>成功次數: ${suxCount}<br>魔法流:${fluxType}`
ChatMessage.create({
user: game.user._id,
speaker: ChatMessage.getSpeaker({token: actor}),
content: message});
```
# Cyberpunk Red
```javascript=
/*
* 其他對應形狀
types: {
circle: "Circle",
cone: "Cone",
rect: "Rectangle",
ray: "Ray"
},
*/
//創建10米方塊爆炸模板
let templateData = {
t: "rect",
user: game.user._id,
x: 500,
y: 500,
direction: 44.9,
distance: 14.1,
borderColor: "#000000",
fillColor: "#cc2865",
};
let theTemplate= await MeasuredTemplateDocument.create(templateData, {parent: canvas.scene});
//爆炸偏移macro,網格50
const content = `
<form>
<div class="form-group">
<label>異動ID</label>
<input value="" name="id">
</div>
</form>
`;
new Dialog({
title: "爆炸偏移調整",
content,
buttons: {
roll: {
label: "確定",
callback: (html) => {
let dataId = html.find("[name=id]")[0].value;
let getData = canvas.scene.getEmbeddedDocument('MeasuredTemplate',dataId);
console.log(getData,dataId);
let message = ``;
let results = ``;
let r1 = new Roll("1d10").evaluate({async: false});
let xyr1 = new Roll("1d2").evaluate({async: false});
let r2 = new Roll("1d10").evaluate({async: false});
let xyr2 = new Roll("1d2").evaluate({async: false});
let Xroll = r1.total;
let Yroll = r2.total;
let Xrollpixel = '';
let Yrollpixel = '';
let Xstr ='';
let Ystr ='';
if(xyr1.total==1){
Xrollpixel=Xroll*25;
Xstr ='向右偏移';
}else{
Xrollpixel=Xroll*-25;
Xstr ='向左偏移';
}
if(xyr2.total==1){
Yrollpixel =Yroll*25;
Ystr ='向下偏移';
}else{
Yrollpixel =Yroll*-25;
Ystr ='向上偏移';
}
const updates = [{_id: dataId, x: getData.x+Xrollpixel , y: getData.y+Yrollpixel }];
const updated = canvas.scene.updateEmbeddedDocuments('MeasuredTemplate',updates);
console.log(getData,dataId);
message = `<h2>爆炸偏移</h2>
<strong>X軸偏移:</strong>${Xstr}${Xroll}米<br>
<strong>Y軸偏移:</strong>${Ystr}${Yroll}米<br>`;
ChatMessage.create({
user: game.user._id,
speaker: ChatMessage.getSpeaker({token: actor}),
content: message});
}
},
cancel: {
label: "取消"
}
},
default: "cancel"
}).render(true);
//清除所有測量模板
canvas.scene.deleteEmbeddedDocuments('MeasuredTemplate',canvas.scene.templates.map(i=>i.id));
```
# RoleMaster Unified
```javascript=
/r {3d100kh2, 3d100kh2, 3d100kh2, 3d100kh2, 3d100kh2, 3d100kh2, 3d100kh2, 3d100kh2, 3d100kh2, 3d100kh2} # Character Ability Scores
//通用檢定擲骰介面
const content = `
<form>
<div class="form-group">
<label>檢定類型</label>
<select name="check_method">
<option>絕對檢定</option>
<option>百分比檢定</option>
<option>施法檢定</option>
</select>
</div>
<div class="form-group">
<label>難度</label>
<select name="difficulty">
<option value="+70">休閒 (+70)</option>
<option value="+50">輕鬆 (+50)</option>
<option value="+30">常規 (+30)</option>
<option value="+20">簡單 (+20)</option>
<option value="+10">還行 (+10)</option>
<option value="+0" selected>中等 (+0)</option>
<option value="-10">困難 (-10)</option>
<option value="-20">非常難 (-20)</option>
<option value="-30">極其困難 (-30)</option>
<option value="-50">異想天開 (-50)</option>
<option value="-70">難以置信 (-70)</option>
<option value="-100">幾乎不可能 (-100)</option>
</select>
</div>
<div class="form-group">
<label>修改(填上每個±)</label>
<input value="+0" type="text" name="total">
</div>
</form>
`;
new Dialog({
title: "技能擲骰 1d100 OE",
content,
buttons: {
roll: {
label: "確定",
callback: (html) => {
let r = new Roll("1d100").evaluate({async: false});
game.dice3d.showForRoll(r, game.user, true);
let Xroll = r.total;
let RExplode = new Roll("1d100>=96x").evaluate({async: false});
RExplode.dice[0].options.appearance = {
colorset: "custom",
foreground: "#59CBE8",
background: "#000000",
outline: "#000000",
edge: "#59CBE8",
material: "glass",
font: "Luminari",
emissive: "#59CBE8",
system: "standard"
};
let html_total = html.find("[name=total]")[0].value;
let html_check_method = html.find("[name=check_method]")[0].value;
let html_difficulty = html.find("[name=difficulty]")[0].value;
let total_number = 0;
let total_string = "";
let total_string_css = "";
let result_string = "";
if(html_total==="") html_total=0;
if(Xroll<=5){
game.dice3d.showForRoll(RExplode, game.user, true);
total_number = parseInt(Xroll)-parseInt(RExplode.total)+parseInt(html_difficulty)+eval(html_total);
total_string = `${Xroll}(擲骰)-${RExplode.total}(擲骰)${html_difficulty}(難度)${html_total}(修改)`;
total_string_css="color:red;";
} else if (Xroll>=96) {
game.dice3d.showForRoll(RExplode, game.user, true);
total_number = parseInt(Xroll)+parseInt(RExplode.total)+parseInt(html_difficulty)+eval(html_total);
total_string = `${Xroll}(擲骰)+${RExplode.total}(擲骰)${html_difficulty}(難度)${html_total}(修改)`;
total_string_css="color:green;";
} else{
total_number = parseInt(Xroll)+parseInt(html_difficulty)+eval(html_total);
total_string = `${Xroll}(擲骰)${html_difficulty}(難度)${html_total}(修改)`;
}
if(html_check_method!="百分比檢定"){
if(html_check_method=="施法檢定"){
if(total_number<=0){
result_string = "法術失敗";
}else {
result_string = "法術成功";
}
} else{
if(total_number<1){
result_string = "絕對失敗";
}else if (total_number <= 75){
result_string = "失敗";
}else if (total_number <= 100){
result_string = "部份成功";
}else if (total_number <= 175){
result_string = "成功";
}else if (total_number > 175){
result_string = "絕對成功";
}
if (Xroll == 66){
result_string += " (異常事件)";
} else if (Xroll == 33 || Xroll == 77){
result_string += " (檢查損壞檢定)";
}
}
}else{
if(total_number<=-100){
result_string = "E 嚴重度,查看相應重擊表";
}else if (total_number <= -80){
result_string = "D 嚴重度,查看相應重擊表";
}else if (total_number <= -60){
result_string = "C 嚴重度,查看相應重擊表";
}else if (total_number <= -40){
result_string = "B 嚴重度,查看相應重擊表";
}else if (total_number <= -20){
result_string = "A 嚴重度,查看相應重擊表";
}else if (total_number <= 0){
result_string = "行動失敗";
}else if (total_number <= 10){
result_string = "5% 進展";
}else if (total_number <= 20){
result_string = "10% 進展";
}else if (total_number <= 30){
result_string = "20% 進展";
}else if (total_number <= 40){
result_string = "30% 進展";
}else if (total_number <= 50){
result_string = "40% 進展";
}else if (total_number <= 60){
result_string = "50% 進展";
}else if (total_number <= 70){
result_string = "60% 進展";
}else if (total_number <= 80){
result_string = "70% 進展";
}else if (total_number <= 90){
result_string = "80% 進展";
}else if (total_number <= 100){
result_string = "90% 進展";
}else if (total_number <= 130){
result_string = "100% 進展";
}else if (total_number <= 160){
result_string = "110% 進展";
}else if (total_number <= 190){
result_string = "120% 進展";
}else if (total_number <= 220){
result_string = "130% 進展";
}else if (total_number <= 250){
result_string = "140% 進展";
}else if (total_number <= 280){
result_string = "150% 進展";
}else if (total_number > 280){
result_string = "卓越進展";
}
}
message = `<h2>檢定</h2>
<strong>檢定類型:${html_check_method}<br>
<strong style="${total_string_css}">過程:${total_string}</strong><br>
<strong>總計:${total_number}<br>
<hr>
<strong style="font-size:18px;">結果:${result_string}<br>`;
ChatMessage.create({
user: game.user._id,
speaker: ChatMessage.getSpeaker({token: actor}),
content: message});
}
},
cancel: {
label: "取消"
}
},
default: "cancel"
}).render(true);
//抵抗檢定
const content = `
<form>
<div class="form-group">
<label>RR DC(預設50)</label>
<input value="50" type="text" name="rr_check">
</div>
<div class="form-group">
<label>修改(填上每個±)</label>
<input value="+0" type="text" name="total">
</div>
</form>
`;
new Dialog({
title: "抵抗檢定 1d100 OE",
content,
buttons: {
roll: {
label: "確定",
callback: (html) => {
let r = new Roll("1d100").evaluate({async: false});
game.dice3d.showForRoll(r, game.user, true);
let Xroll = r.total;
let RExplode = new Roll("1d100>=96x").evaluate({async: false});
RExplode.dice[0].options.appearance = {
colorset: "custom",
foreground: "#59CBE8",
background: "#000000",
outline: "#000000",
edge: "#59CBE8",
material: "glass",
font: "Luminari",
emissive: "#59CBE8",
system: "standard"
};
let html_total = html.find("[name=total]")[0].value;
let html_rr_check = html.find("[name=rr_check]")[0].value;
let total_number = 0;
let total_string = "";
let total_string_css = "";
let result_string = "";
if(html_total==="") html_total=0;
if(Xroll<=5){
game.dice3d.showForRoll(RExplode, game.user, true);
total_number = parseInt(Xroll)-parseInt(RExplode.total)+eval(html_total);
total_string = `${Xroll}(擲骰)-${RExplode.total}(擲骰)${html_total}(修改)`;
total_string_css="color:red;";
} else if (Xroll>=96) {
game.dice3d.showForRoll(RExplode, game.user, true);
total_number = parseInt(Xroll)+parseInt(RExplode.total)+eval(html_total);
total_string = `${Xroll}(擲骰)+${RExplode.total}(擲骰)${html_total}(修改)`;
total_string_css="color:green;";
} else{
total_number = parseInt(Xroll)+eval(html_total);
total_string = `${Xroll}(擲骰)${html_total}(修改)`;
}
var compareNumber = Math.abs(total_number-parseInt(html_rr_check));
if (total_number < parseInt(html_rr_check)){
if(compareNumber > 100){
result_string = "極端失敗";
} else if(compareNumber > 50){
result_string = "嚴重失敗";
} else if(compareNumber > 25){
result_string = "中等失敗";
} else if(compareNumber > 0){
result_string = "輕微失敗";
}
}else{
result_string = "抵抗成功!"
}
message = `<h2>抵抗檢定</h2>
<strong>RR DC:${html_rr_check}<br>
<strong style="${total_string_css}">過程:${total_string}</strong><br>
<strong>差額比較:${total_number} vs. ${html_rr_check} = ${compareNumber}<br>
<hr>
<strong style="font-size:18px;">結果:${result_string}<br>`;
ChatMessage.create({
user: game.user._id,
speaker: ChatMessage.getSpeaker({token: actor}),
content: message});
}
},
cancel: {
label: "取消"
}
},
default: "cancel"
}).render(true);
//攻擊檢定
const content = `
<form>
<div class="form-group">
<label>難度</label>
<select name="difficulty">
<option value="+70">休閒 (+70)</option>
<option value="+50">輕鬆 (+50)</option>
<option value="+30">常規 (+30)</option>
<option value="+20">簡單 (+20)</option>
<option value="+10">還行 (+10)</option>
<option value="+0" selected>中等 (+0)</option>
<option value="-10">困難 (-10)</option>
<option value="-20">非常難 (-20)</option>
<option value="-30">極其困難 (-30)</option>
<option value="-50">異想天開 (-50)</option>
<option value="-70">難以置信 (-70)</option>
<option value="-100">幾乎不可能 (-100)</option>
</select>
</div>
<div class="form-group">
<label>攻擊(填上每個±)</label>
<input value="+0" type="text" name="total">
</div>
<div class="form-group">
<label>重擊(填上每個±)</label>
<input value="+0" type="text" name="cri_total">
</div>
</form>
`;
new Dialog({
title: "攻擊檢定",
content,
buttons: {
roll: {
label: "確定",
callback: (html) => {
let r = new Roll("1d100").evaluate({async: false});
game.dice3d.showForRoll(r, game.user, true);
let Xroll = r.total;
let RExplode = new Roll("1d100>=96x").evaluate({async: false});
RExplode.dice[0].options.appearance = {
colorset: "custom",
foreground: "#59CBE8",
background: "#000000",
outline: "#000000",
edge: "#59CBE8",
material: "glass",
font: "Luminari",
emissive: "#59CBE8",
system: "standard"
};
let html_total = html.find("[name=total]")[0].value;
let html_difficulty = html.find("[name=difficulty]")[0].value;
let total_number = 0;
let total_string = "";
let total_string_css = "";
let result_string = "";
if (html_total === "") html_total = 0;
if (Xroll >= 96) {
game.dice3d.showForRoll(RExplode, game.user, true);
total_number = parseInt(Xroll) + parseInt(RExplode.total) + parseInt(html_difficulty) + eval(html_total);
total_string = `${Xroll}(擲骰)+${RExplode.total}(擲骰)${html_difficulty}(難度)${html_total}(修改)`;
total_string_css = "color:green;";
} else {
total_number = parseInt(Xroll) + parseInt(html_difficulty) + eval(html_total);
total_string = `${Xroll}(擲骰)${html_difficulty}(難度)${html_total}(修改)`;
}
let cri_bouns = 0;
if (total_number >= 180) {
cri_bouns = Math.floor((total_number - 175) / 5);
}
let total_cri_string = "";
let html_cri_total = html.find("[name=cri_total]")[0].value;
if (html_cri_total === "") html_cri_total = 0;
let hitroll = new Roll("1d100").evaluate({async: false}).total;
let hitdice = hitroll + eval(html_cri_total) + cri_bouns;
total_cri_string = `${hitroll}(擲骰)${html_cri_total}(修改)+${cri_bouns}(加重攻擊)`;
const HitLocation = {
"Head": "命中頭部",
"Chest": "命中胸部",
"Abdomen": "命中腹部",
"LegLeft": "命中左腿部",
"LegRight": "命中右腿部",
"ArmLeft": "命中左手臂",
"ArmRight": "命中右手臂",
}
hitdice = (hitdice >= 100) ? 100 : hitdice;
if (
hitdice == 1 ||
(hitdice >= 16 && hitdice <= 20) ||
(hitdice >= 81 && hitdice <= 85) ||
hitdice >= 100
) {
result_string = HitLocation.Head;
} else if (
(hitdice >= 2 && hitdice <= 3) ||
(hitdice >= 21 && hitdice <= 25) ||
(hitdice >= 76 && hitdice <= 80) ||
(hitdice >= 98 && hitdice <= 99)
) {
result_string = HitLocation.Chest;
} else if (
(hitdice >= 4 && hitdice <= 5) ||
(hitdice >= 26 && hitdice <= 35) ||
(hitdice == 66) ||
(hitdice >= 96 && hitdice <= 97)
) {
result_string = HitLocation.Abdomen;
} else if (
(hitdice >= 6 && hitdice <= 10) ||
(hitdice >= 36 && hitdice <= 45) ||
(hitdice >= 67 && hitdice <= 75) ||
(hitdice >= 91 && hitdice <= 95)
) {
if (hitdice % 2 == 1) {
result_string = HitLocation.LegLeft;
} else {
result_string = HitLocation.LegRight;
}
} else if (
(hitdice >= 11 && hitdice <= 15) ||
(hitdice >= 46 && hitdice <= 55) ||
(hitdice >= 56 && hitdice <= 65) ||
(hitdice >= 86 && hitdice <= 90)
) {
if (hitdice % 2 == 1) {
result_string = HitLocation.ArmLeft;
} else {
result_string = HitLocation.ArmRight;
}
}
if (Xroll == 66) {
result_string += " (異常事件)";
} else if (Xroll == 33 || Xroll == 77) {
result_string += " (檢查損壞檢定)";
}
if(total_number <= 67){
result_string = "完全失誤/除非是範圍法術";
}
message = `<h2>攻擊</h2>
<strong style="${total_string_css}">過程:${total_string}</strong><br>
<strong>攻擊結果:${total_number}<br>
<hr>
<strong>過程:${total_cri_string}</strong><br>
<strong>重擊結果:${hitdice}<br>
<hr>
<strong style="font-size:18px;">結果:${result_string}<br>`;
ChatMessage.create({
user: game.user._id,
speaker: ChatMessage.getSpeaker({token: actor}),
content: message
});
}
}
},
cancel: {
label: "取消"
},
default: "cancel"
}).render(true);
```
暗影之痕擲骰(V12)
```javascript=
const content = `<form>
<div class="form-group">
<label>檢定骰池</label>
<div class="form-fields">
<input type="number" name="amount" value="1">
</div>
</div>
</form>`;
const data = await Dialog.wait({
title: "擲骰器",
content,
buttons: {
ok: {
label: "擲骰!",
callback: ([html]) => new FormDataExtended(html.querySelector("form")).object
}
},
default: "none" // hacky way to avoid the v11 event bug passing to the button causing it to auto close.
});
let message = ``;
let results = ``;
const formula = `${data.amount}d6`;
const r = await new Roll(formula).roll();
game.dice3d.showForRoll(r, game.user, true)
const sequence = r.dice[0].results.map(e => e.result);
const total = r.dice[0].results.reduce((total, e, i) => {
if (e.result === 6) {
total += 2;
} else if (e.result > 3) {
total += 1;
}
return total; // 直接返回累加後的總和
}, 0); // 初始值為 0
message = `擲骰結果:${sequence}<br>成功次數: ${total}`
ChatMessage.create({
user: game.user._id,
speaker: ChatMessage.getSpeaker({token: actor}),
content: message});
```