---
# System prepended metadata

title: FVTT Marco 指令紀錄
tags: [Macro, FVTT]

---

# 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});
```