モンハンワイルズを遊ぶ際、よくスキルシミュレータをお借りして装備組みの参考にしますが、この装備の合計会心率はいくつなんだ?というのがわからないため、計算するツールを作成しました。
要件としては
- 武器会心率を任意で入力できる
- 会心率に関わるスキル、状態を選択する
- 自身の状態により会心率が変化する場合、状態をチェックボックスで選択できるようにし、それによって会心率を変化させる
- モンスターの部位の傷口により会心率が変化する場合、合計会心とは別で追加表示
- 合計会心率は一目でわかりやすいように表示
です。
コードを書く上で苦労したところ、工夫したところを書き記していきます。
通常スキル
通常のスキルはconst skills = [
// 武器スキル
{ name: "見切り", level: 0, maxLevel: 5, category: "weapon" },
...
// スキルレベル毎の会心率
const criticalRateByLevel = {
"見切り": [0, 4, 8, 12, 16, 20],
...
上記で各スキルのスキルレベル毎の会心率を定義し、
// スキルの現在レベルから会心率を合計する
function calculateSkillRate() {
let totalSkillRate = 0;
// skillsから1つずつskillを取り出して処理
for (const skill of skills) {
const skillRate =
criticalRateByLevel[skill.name][skill.level];
totalSkillRate += skillRate;
}
return totalSkillRate;
}
-
for...ofでスキルを一つずつ取り出す - スキル名とレベルから、対応する会心率を取得する
- 取得した会心率を合計し、最後に返す
という処理を行っています。
特殊なスキル
モンハンワイルズにはプレイヤーの状態、モンスターの部位の状態によって上昇する会心率が変化するスキルがいくつかあります。
- 濡れ刃紋:水濡れ状態と泡状態で会心率が変化する
- 連携プログラム:レゾナンスⅡという別のスキルが発動している際に、会心率の上昇値が上がる
- 弱点特効:通常時と傷口攻撃時で会心率が異なる
- 無我の境地:スキル自体に特別な処理はないが、狂竜症を発症することが前提なので、狂竜症克服の会心率上昇も必要
これらのスキルは単純にスキル名とレベルだけでは値を取得できないため、別の処理を組み込む必要がありました。
濡れ刃紋
プレイヤーが水に濡れている際、あるいは泡状態の際にのみ会心率が上昇するスキルです。| Lv1 | Lv2 | Lv3 | |
|---|---|---|---|
| 水濡れ | +3 | +6 | +9 |
| 泡 | +7 | +14 | +21 |
| 両方 | +10 | +20 | +30 |
それぞれ上昇値が違うため特殊な処理が必要でした。
そこで、スキルにそれぞれの状態のチェックボックスと、判定する処理を実装しました。
const criticalRateByLevel = {
...
"濡れ刃紋": {
water: [0, 3, 6, 9],
bubble: [0, 7, 14, 21]
},
...
for (const skill of skills) {
let skillRate;
if (skill.name == "濡れ刃紋") {
skillRate = 0;
// 水濡れ状態なら会心率を加算
if (waterActive) {
skillRate =
skillRate +
criticalRateByLevel[skill.name].water[skill.level];
}
// 泡状態なら会心率を加算
if (bubbleActive) {
skillRate =
skillRate +
criticalRateByLevel[skill.name].bubble[skill.level];
}
}
}
skillRateにまず0を代入し、その後、水濡れや泡状態に応じて値を加算します。
処理の途中でskillRateに値を代入する処理なので変数letで宣言しています。
定数と変数の違いを学ぶいい題材だったと感じています。
連携プログラム
このスキルは、発動時に自身と味方の会心率を15%上昇させるスキルですが、レゾナンスⅡというスキルが発動していると25%に上昇値が変わります。レゾナンスⅡが発動しているかどうかのチェックボックスと、判定する処理を実装しました。for (const skill of skills) {
let skillRate;
if (skill.name == "連携プログラム") {
skillRate =
criticalRateByLevel[skill.name][skill.level];
if (resonance2Active && skill.level >= 1) {
skillRate = 25;
}
}
}
濡れ刃紋の時と同じように、処理の途中でskillRateに値を代入する処理なので変数letで宣言しています。
その後、レゾナンスⅡの発動の有無を判定しています。発動していれば会心率は25%になりますね。
弱点特効
有効部位への攻撃の会心率が上昇するスキルです。具体的には肉質45以上の部位が対象です。 それに加え、傷口への攻撃の会心率が上昇する効果もあります。| Lv1 | Lv2 | Lv3 | Lv4 | Lv5 | |
|---|---|---|---|---|---|
| 有効部位 | +5 | +10 | +15 | +20 | +30 |
| 傷口 | +3 | +5 | +10 | +15 | +20 |
| 有効部位かつ傷口 | +8 | +15 | +25 | +35 | +50 |
こちらも濡れ刃紋の時と同じで、それぞれ上昇値が違うため特殊な処理が必要でした。
スキルに傷口のチェックボックスと、判定する処理を実装しました。
const criticalRateByLevel = {
...
"弱点特効": {
normal: [0, 5, 10, 15, 20, 30],
wound: [0, 3, 5, 10, 15, 20]
},
...
for (const skill of skills) {
let skillRate;
if (skill.name == "弱点特効") {
skillRate =
criticalRateByLevel[skill.name].normal[skill.level];
}
}
...
// 傷口への会心率
function calculateWoundSkillRate() {
const skill = skills.find(function (skill) {
return skill.name == "弱点特効";
});
return criticalRateByLevel[skill.name].wound[skill.level];
}
find()は条件に当てはまる要素を探し、最初に見つかった要素を返すというものです。これにより傷口への会心率を反映させています。
無我の境地
狂竜ウイルスを克服した際に上昇する会心率(15%)がさらに大きくなるスキルです。狂竜ウイルスを克服しやすくなる効果もあります。| Lv1 | Lv2 | Lv3 |
|---|---|---|
| +3 | +6 | +10 |
スキル自体は会心率を+10するだけなので特殊な処理はありませんが、無我の境地が発動=狂竜症克服なので、このスキルが発動した際に自動的に狂竜症克服状態にする仕組みが必要でした。
// 状態による会心率 ここでは狂竜症
function calculateBattleStateRate() {
let totalBattleStateRate = 0;
if (frenzyCured) {
totalBattleStateRate += 15;
}
return totalBattleStateRate;
}
...
// 無我の境地Lv1以上なら狂竜症克服を発動
if (skill.name === "無我の境地" && skill.level >= 1) {
frenzyCured = true;
frenzyCuredCheckbox.checked = true;
frenzyCuredLabel.textContent = "狂竜症克服 +15%";
}
updateSkillDisplay();
frenzyCuredCheckbox.checkedとfrenzyCuredLabel.textContentは狂竜症チェックボックスに関わる処理になっています。
