百年
术士魔力泉涌的改进版
关于术士魔力泉涌的改进版——涌在伟大的BBXC老大和伟大的ai大人的帮助下完成。
这是物品宏,如果有itemmacro的话直接放在物品里就行。4.x的dnd系统应该自带物品宏,就不需要itemmacro之类的模组。
你需要有一个叫做术法点Sorcery Points的特性物品存放术法点的资源数(其实现在classpack会有术法点,你名字里加上Sorcery Points就行)
// 只需修改这个值即可调整恢复量(数值为正数)
const FIXED_RESTORATION = 1;
// 资源恢复法术位的消耗映射
const resourceToSpellSlotCostMap = {
1: 2, // 2点资源恢复1环
2: 3, // 3点资源恢复2环
3: 5, // 5点资源恢复3环
4: 6, // 6点资源恢复4环
5: 7, // 7点资源恢复5环
6: 9 // 9点资源恢复6环
};
// 法术位恢复资源的映射
const spellSlotToResourceMap = {
1: 1, // 1环法术位恢复1点资源
2: 2, // 2环法术位恢复2点资源
3: 3, // 3环法术位恢复3点资源
4: 4, // 4环法术位恢复4点资源
5: 5, // 5环法术位恢复5点资源
6: 6 // 6环法术位恢复6点资源
};
// ======= 配置部分到此为止 =======
// 查找“术法点Sorcery Points”物品
const spItem = actor.items.find(i => === "术法点Sorcery Points");
if (!spItem) return ui.notifications.warn("角色卡内没有‘术法点Sorcery Points’物品!");
const sorceryPoints = ?? 0;
const sorceryPointsMax = ?? 0;
// 只查找max>0的法术位,并记录下来用于生成选项和后续判定
let availableSlots = [];
for (let lvl = 1; lvl <= 5; lvl++) {
const slotData = getProperty(actor.system, `spells.spell${lvl}`);
if (slotData?.max > 0) availableSlots.push(lvl);
}
if (!availableSlots.length) return ui.notifications.warn("你没有任何可用的法术位可供兑换。");
// 下拉框只给实际有法术位的环数
const slotOptions = availableSlots.map(lvl => `<option value="${lvl}">${lvl} 环法术位</option>`).join("");
const maxSpellSlotLevel = Math.max(...availableSlots);
new Dialog({
title: "魔力泉涌--你与生俱来的能力在魔网里引发一阵激涌",
content: `
<form>
<div class="form-group">
<label>选择操作:</label>
<select id="actionSelect">
<option value="restoreSpellSlot">用术法点换法术位</option>
<option value="restoreResource">用法术位换术法点</option>
</select>
</div>
<div class="form-group">
<label>选择法术位环数:</label>
<select id="spellSlotSelect">${slotOptions}</select>
</div>
<div class="form-group">
<label>最大可恢复量:${maxSpellSlotLevel} 环法术位</label>
</div>
<div style="font-size:0.95em;color:#999;">法术位和术法点兑换比率见不全书或SRD灵活施法规则</div>
</form>
`,
buttons: {
confirm: {
icon: '<i class="fas fa-check"></i>',
label: "确认",
callback: async (html) => {
const selectedAction = html.find('#actionSelect').val();
const lvl = parseInt(html.find('#spellSlotSelect').val());
const slotData = getProperty(actor.system, `spells.spell${lvl}`);
const slotCur = slotData?.value ?? 0;
const slotMax = slotData?.max ?? 0;
// debug行可删
// console.log(`DEBUG: ${lvl}环 value=${slotCur}, max=${slotMax}`);
if (selectedAction === "restoreSpellSlot") {
// 用术法点换法术位
const cost = resourceToSpellSlotCostMap[lvl];
if (!cost) return ui.notifications.warn("只可兑换1~5环法术位!");
if (sorceryPoints < cost * FIXED_RESTORATION)
return ui.notifications.warn(`术法点不足,需${cost * FIXED_RESTORATION}点才能兑换${FIXED_RESTORATION}个${lvl}环法术位!`);
if (slotCur >= slotMax)
return ui.notifications.warn(`${lvl}环法术位已满,无法继续恢复!`);
await actor.update({[`system.spells.spell${lvl}.value`]: slotCur + FIXED_RESTORATION});
await spItem.update({ "": sorceryPoints - cost * FIXED_RESTORATION });
ChatMessage.create({
speaker: ChatMessage.getSpeaker({ actor: actor }),
content: `${} 消耗${cost * FIXED_RESTORATION}点术法点,恢复了${FIXED_RESTORATION}个${lvl}环法术位。`
});
} else if (selectedAction === "restoreResource") {
// 用法术位换术法点
if (slotCur < FIXED_RESTORATION)
return ui.notifications.warn(`${lvl}环法术位不足,无法兑换术法点!`);
const gain = spellSlotToResourceMap[lvl] ?? 0;
if (gain < 1)
return ui.notifications.warn("只可用1~5环法术位兑换术法点!");
if (sorceryPoints + gain * FIXED_RESTORATION > sorceryPointsMax)
return ui.notifications.warn(`兑换后会超出最大术法点(${sorceryPointsMax})!`);
await actor.update({[`system.spells.spell${lvl}.value`]: slotCur - FIXED_RESTORATION});
await spItem.update({ "": sorceryPoints + gain * FIXED_RESTORATION });
ChatMessage.create({
speaker: ChatMessage.getSpeaker({ actor: actor }),
content: `${} 消耗${FIXED_RESTORATION}个${lvl}环法术位,恢复了${gain * FIXED_RESTORATION}点术法点。`
});
}
}
},
cancel: { icon: '<i class="fas fa-times"></i>', label: "取消" }
},
default: "confirm"
}).render(true);
——————————————————————分割线————————————————————————————
如果你想要LAW的方式看待术士的灵活施法功能,即,如果你认为契约法术位也可以和术法点互相转化(上面的宏是不会识别契约法术位的),你可以换成下面这个
// ======= 配置部分到此为止 =======
// 查找“术法点Sorcery Points”物品
const spItem = actor.items.find(i => === "术法点Sorcery Points");
if (!spItem) return ui.notifications.warn("角色卡内没有‘术法点Sorcery Points’物品!");
const sorceryPoints = ?? 0;
const sorceryPointsMax = ?? 0;
// 收集可用普通法术位
let availableSlots = [];
for (let lvl = 1; lvl <= 5; lvl++) {
const slotData = getProperty(actor.system, `spells.spell${lvl}`);
if (slotData?.max > 0) availableSlots.push(lvl);
}
// 加入契约法术位
const pactSlot = getProperty(actor.system, "");
const pactValid = pactSlot?.max > 0 && pactSlot?.level > 0;
if (pactValid) availableSlots.push("pact");
if (!availableSlots.length) return ui.notifications.warn("你没有任何可用的法术位可供兑换。");
const maxSpellSlotLevel = Math.max(...availableSlots.map(x=>x==="pact"?pactSlot.level:x));
const slotOptions = availableSlots.map(lvl => {
if (lvl === "pact") {
return `<option value="pact">契约法术位(${}环)</option>`;
} else {
return `<option value="${lvl}">${lvl} 环法术位</option>`;
}
}).join("");
new Dialog({
title: "魔力泉涌 - 灵活施法(含契约法术位房规)",
content: `
<form>
<div class="form-group">
<label>选择操作:</label>
<select id="actionSelect">
<option value="restoreSpellSlot">用术法点换法术位</option>
<option value="restoreResource">用法术位换术法点</option>
</select>
</div>
<div class="form-group">
<label>选择法术位类型/环数:</label>
<select id="spellSlotSelect">${slotOptions}</select>
</div>
<div class="form-group">
<label>最大可恢复量:${maxSpellSlotLevel} 环法术位</label>
</div>
<div style="font-size:0.95em;color:#999;">法术位和术法点兑换比率见SRD灵活施法规则</div>
</form>
`,
buttons: {
confirm: {
icon: '<i class="fas fa-check"></i>',
label: "确认",
callback: async (html) => {
const selectedAction = html.find('#actionSelect').val();
const slotKey = html.find('#spellSlotSelect').val();
let slotCur, slotMax, slotLvl;
if (slotKey === "pact") {
slotCur = pactSlot?.value ?? 0;
slotMax = pactSlot?.max ?? 0;
slotLvl = pactSlot?.level ?? 1;
} else {
const slotData = getProperty(actor.system, `spells.spell${slotKey}`);
slotCur = slotData?.value ?? 0;
slotMax = slotData?.max ?? 0;
slotLvl = parseInt(slotKey);
}
if (selectedAction === "restoreSpellSlot") {
// 用术法点换法术位
const cost = resourceToSpellSlotCostMap[slotLvl];
if (!cost) return ui.notifications.warn("只可兑换1~5环法术位(契约法术位按自身环数计)!");
if (sorceryPoints < cost * FIXED_RESTORATION)
return ui.notifications.warn(`术法点不足,需${cost * FIXED_RESTORATION}点才能兑换${FIXED_RESTORATION}个${slotKey==="pact"?"契约":slotLvl+"环"}法术位!`);
if (slotCur >= slotMax)
return ui.notifications.warn(`${slotKey==="pact"?"契约":slotLvl+"环"}法术位已满,无法继续恢复!`);
if (slotKey === "pact") {
await actor.update({[""]: slotCur + FIXED_RESTORATION});
} else {
await actor.update({[`system.spells.spell${slotLvl}.value`]: slotCur + FIXED_RESTORATION});
}
await spItem.update({ "": sorceryPoints - cost * FIXED_RESTORATION });
ChatMessage.create({
speaker: ChatMessage.getSpeaker({ actor: actor }),
content: `${} 消耗${cost * FIXED_RESTORATION}点术法点,恢复了${FIXED_RESTORATION}个${slotKey==="pact"?"契约":slotLvl+"环"}法术位。`
});
} else if (selectedAction === "restoreResource") {
// 用法术位换术法点
const gain = spellSlotToResourceMap[slotLvl] ?? 0;
if (gain < 1)
return ui.notifications.warn("只可用1~5环法术位或契约法术位兑换术法点!");
if (slotCur < FIXED_RESTORATION)
return ui.notifications.warn(`${slotKey==="pact"?"契约":slotLvl+"环"}法术位不足,无法兑换术法点!`);
if (sorceryPoints + gain * FIXED_RESTORATION > sorceryPointsMax)
return ui.notifications.warn(`兑换后会超出最大术法点(${sorceryPointsMax})!`);
if (slotKey === "pact") {
await actor.update({[""]: slotCur - FIXED_RESTORATION});
} else {
await actor.update({[`system.spells.spell${slotLvl}.value`]: slotCur - FIXED_RESTORATION});
}
await spItem.update({ "": sorceryPoints + gain * FIXED_RESTORATION });
ChatMessage.create({
speaker: ChatMessage.getSpeaker({ actor: actor }),
content: `${} 消耗${FIXED_RESTORATION}个${slotKey==="pact"?"契约":slotLvl+"环"}法术位,恢复了${gain * FIXED_RESTORATION}点术法点。`
});
}
}
},
cancel: { icon: '<i class="fas fa-times"></i>', label: "取消" }
},
default: "confirm"
}).render(true);
- 下载图片
- 复制图片
2025-05-29
浏览192
🖥️宏相关
登录后评论
3
评论
分享