User:びゃっこ/すたぶ/解析物理戦闘: Difference between revisions
m (→防御力) |
(→ダメージ計算) |
||
Line 865: | Line 865: | ||
貫通ダメージ = (攻撃力 - 属性変換ダメージ) × 貫通率 | 貫通ダメージ = (攻撃力 - 属性変換ダメージ) × 貫通率 | ||
非貫通ダメージ = (攻撃力 - 属性変換ダメージ - 貫通ダメージ) × 防御割合 - 防御固定値 ※(負の値になった場合0に補正) | 非貫通ダメージ = (攻撃力 - 属性変換ダメージ - 貫通ダメージ) × 防御割合 - 防御固定値 ※(負の値になった場合0に補正) | ||
以上から、物理攻撃によるダメージは以下の通りです。 | |||
軽減後ダメージ = 属性変換ダメージ + 貫通ダメージ + 非貫通ダメージ | 軽減後ダメージ = 属性変換ダメージ + 貫通ダメージ + 非貫通ダメージ | ||
この後、[[User:びゃっこ/すたぶ/解析だめけいさん|DamageHP関数の中で属性耐性などの各種補正によって最終的なダメージは増減します]]。 | |||
==属性追加ダメージエンチャント== | ==属性追加ダメージエンチャント== |
Revision as of 16:27, 23 March 2025
近接攻撃のダメージが出るまでの処理
内部的には、AttackProcessで命中判定などが起きる > ActMelee.csで物理攻撃エンチャントの処理が行われる。 > Perform > この中でDamageHP,ApplyProtectionが呼び出される。
近接攻撃処理順
遠隔攻撃処理順
投擲攻撃処理順
攻撃能力の算出
格闘
else if (IsMartial || IsMartialWeapon)
{
weaponSkill = CC.elements.GetOrCreateElement(100);
bool flag2 = weapon != null && weapon.Evalue(482) > 0;
if (flag2)
{
weaponSkill = CC.elements.GetOrCreateElement(305);
}
attackType = ((!CC.race.meleeStyle.IsEmpty()) ? CC.race.meleeStyle.ToEnum<AttackType>() : ((EClass.rnd(2) == 0) ? AttackType.Kick : AttackType.Punch));
dBonus = CC.DMG + CC.encLV + (int)Mathf.Sqrt(Mathf.Max(0, weaponSkill.GetParent(CC).Value / 5 + weaponSkill.Value / 4));
dNum = 2 + Mathf.Min(weaponSkill.Value / 10, 4);
dDim = 5 + (int)Mathf.Sqrt(Mathf.Max(0, weaponSkill.Value / 3));
dMulti = 0.6f + (float)(weaponSkill.GetParent(CC).Value / 2 + weaponSkill.Value / 2 + CC.Evalue(flag2 ? 304 : 132) / 2) / 50f;
dMulti += 0.05f * (float)CC.Evalue(1400);
toHitBase = EClass.curve(CC.DEX / 3 + weaponSkill.GetParent(CC).Value / 3 + weaponSkill.Value, 50, 25) + 50;
toHitFix = CC.HIT;
if (attackStyle == AttackStyle.Shield)
{
toHitBase = toHitBase * 75 / 100;
}
penetration = Mathf.Clamp(weaponSkill.Value / 10 + 5, 5, 20) + CC.Evalue(92);
if (IsMartialWeapon)
{
dBonus += weapon.DMG;
dNum += weapon.source.offense[0];
dDim = Mathf.Max(dDim / 2 + weapon.c_diceDim, 1);
toHitFix += weapon.HIT;
penetration += weapon.Penetration;
if (!weapon.source.attackType.IsEmpty())
{
attackType = weapon.source.attackType.ToEnum<AttackType>();
}
}
}
キャラクターは格闘スキルを使用して格闘攻撃を繰り出します。通常はパンチないしキックですが、武器の近接戦闘スタイルやキャラクターの特性に基づいて攻撃エフェクトは変わります。
武器に理力武器のエンチャントが付いている場合、格闘スキルの代わりに魔道具スキルを、戦術スキルの代わりに詠唱スキルを使用します。
素手及び通常の格闘武器の場合:
ダメージの基礎ダイス数は「2 + 格闘 / 10」で、最大で6です。
ダメージの基礎ダイス面は「5 + √(格闘 / 3)」です。
基礎ダメージ修正は「√(筋力 / 5 + 格闘 / 4) + 防具のダメージ修正合計 + キャラ固有のダメージ修正[1]」です。
ダメージ倍率は「0.6 + ((筋力 / 2 + 格闘 / 2 + 戦術 / 2) / 50.0)」です。
貫通率は「格闘 / 10 + 5」で、最低5%、最高で20%です。[2]
基礎命中力は「(器用 / 3 + 筋力 / 3 + 格闘)」を、スタート50、ステップ25、レート75%のCURVE関数で計算した後、50を足したものです。
理力武器のエンチャントが付いた格闘武器の場合:
ダメージの基礎ダイス数は「2 + 魔道具 / 10」で、最大で6です。
ダメージの基礎ダイス面は「5 + √(魔道具 / 3)」です。
基礎ダメージ修正は「√(魔力 / 5 + 魔道具 / 4) + 防具のダメージ修正合計 + キャラ固有のダメージ修正[1]」です。
ダメージ倍率は「0.6 + ((魔力 / 2 + 魔道具 / 2 + 詠唱 / 2) / 50.0)」です。
基礎貫通率は「魔道具 / 10 + 5」で、最低5%、最高で20%です。[2]
基礎命中力は「器用 / 3 + 魔力 / 3 + 魔道具」を、スタート50、ステップ25、レート75%のCURVE関数で計算した後、50を足したものです。
プレイヤーが武器の知識フィートを持っている場合、ダメージ倍率に『0.05×(武器の知識フィートのランク)』だけ加算されます。(事実上、+0.05または+0.10)
プレイヤーが盾を装備している場合、基礎命中力は0.75倍に修正されます。
上記の後、基礎命中力に防具の命中修正が加算されます。
さらに、格闘武器を装備している場合は以下の修正を受けます。
最終的なダイス数は「基礎ダイス数 + 武器の基礎ダイス数」です。
最終的なダイス面は「基礎ダイス面 / 2 + 武器の基礎ダイス数」です。
最終的なダメージ修正は「基礎ダメージ修正 + 武器のダメージ修正」です。
最終的な命中力は「基礎命中力 + 武器の命中修正」です。
最終的な貫通率は「基礎貫通率 + 武器の貫通率」です。
投擲
if (isThrow)
{
bool flag = weapon.HasTag(CTAG.throwWeapon) || weapon.HasTag(CTAG.throwWeaponEnemy);
int num2 = (int)Mathf.Clamp(Mathf.Sqrt(weapon.SelfWeight + weapon.ChildrenWeight) * 3f + 25f + (float)(flag ? 75 : 0), 10f, 400f + Mathf.Sqrt(CC.STR) * 50f);
int num3 = Mathf.Clamp(weapon.material.hardness, flag ? 40 : 20, 200);
weaponSkill = CC.elements.GetOrCreateElement(108);
attackType = AttackType.Blunt;
dBonus = CC.DMG + (CC.IsPCParty ? 3 : 7);
dNum = 2;
dDim = (((!CC.IsPCParty) ? CC.LV : 0) + CC.STR + CC.Evalue(108)) * num2 * num3 / 10000 / 2;
dMulti = 1f;
toHitBase = EClass.curve(CC.DEX / 4 + CC.STR / 2 + weaponSkill.Value, 50, 25) + (CC.IsPCFaction ? 75 : 250);
toHitFix = CC.HIT + weapon.HIT;
penetration = 25;
}
プレイヤーの投げたアイテムは投擲武器であってもそうでなくても投擲スキルを参照します。
攻撃エフェクトは常に鈍器です。
重量値は 25 + 投擲武器限定75[3] + 3 * √ [アイテムの重量] ですが、下限10、上限400 + 50 * √(筋力)があります。
ここでいうアイテムの重量はゲーム中の〇.〇sに1000をかけたものです。
武器の材質値は素材の硬度です。上限は200で、これはダークマターの硬度と等しく、下限は投擲武器を投げている場合で40、それ以外では20として設定されています。
ダイスの数は常に「2」です。
ダイスの面は「((プレイヤーパーティー外のキャラのみLv) + 筋力 + 投擲 ) * 重量値 * 武器の材質値 / 10000 / 2」です。
ダメージボーナスは「(プレイヤーパーティー内のキャラの場合:3、それ以外の場合:7) + 武器のダメージ修正 + 防具のダメージ修正合計 + キャラ固有のダメージ修正[1]」です。
ダメージ倍率は常に「1」です。
貫通力は常に25%です。
基礎命中力は「器用 / 4 + 筋力 / 2 + 投擲」を、スタート50、ステップ25、レート75%のCURVE関数で計算した後、プレイヤーキャラクターの場合:75、それ以外の場合:250 を足したもので、
最終的な命中力は「基礎命中力 + 武器の命中修正 + 防具の命中修正合計」です。
近接&遠隔武器
else
{
if (IsRanged)
{
weaponSkill = CC.elements.GetOrCreateElement(toolRange.WeaponSkill);
}
else
{
weaponSkill = CC.elements.GetOrCreateElement(weapon.category.skill);
}
if (!weapon.source.attackType.IsEmpty())
{
attackType = weapon.source.attackType.ToEnum<AttackType>();
}
bool flag3 = IsCane || weapon.Evalue(482) > 0;
if (flag3)
{
weaponSkill = CC.elements.GetOrCreateElement(305);
}
dBonus = CC.DMG + CC.encLV + weapon.DMG;
dNum = weapon.source.offense[0];
dDim = weapon.c_diceDim;
dMulti = 0.6f + (float)(weaponSkill.GetParent(CC).Value + weaponSkill.Value / 2 + CC.Evalue(flag3 ? 304 : (IsRanged ? 133 : 132))) / 50f;
dMulti += 0.05f * (float)CC.Evalue(IsRanged ? 1404 : 1400);
toHitBase = EClass.curve((IsCane ? CC.WIL : CC.DEX) / 4 + weaponSkill.GetParent(CC).Value / 3 + weaponSkill.Value, 50, 25) + 50;
toHitFix = CC.HIT + weapon.HIT;
penetration = weapon.Penetration + CC.Evalue(92);
if (IsCane)
{
toHitBase += 50;
}
}
if (ammo != null && !(ammo.trait is TraitAmmoTalisman))
{
dNumAmmo = ((ammo.source.offense.Length != 0) ? ammo.source.offense[0] : 0);
dDimAmmo = ammo.c_diceDim;
dBonusAmmo = ammo.DMG + ammo.encLV;
if (dNumAmmo < 1)
{
dNumAmmo = 1;
}
if (dDimAmmo < 1)
{
dDimAmmo = 1;
}
toHitFix += ammo.HIT;
}
else
{
dNumAmmo = 0;
dDimAmmo = 0;
}
プレイヤーは、戦術スキルを使用して近接武器を振るうか、または射撃スキルを使用して遠距離武器を撃ちます。
武器がワンド、または理力武器のエンチャントが付いている場合、戦術スキルまたは射撃スキルの代わりに詠唱スキルを、武器スキル(長剣、短剣、斧など)の代わりに魔道具スキルを使用します。
ダメージのダイス数及びダイス面は武器に表記されているものを使用します。
基礎ダメージ修正は「攻撃中の武器のダメージ修正 + 防具のダメージ修正合計 + キャラ固有のダメージ修正[1]」です。
ダメージ倍率は「0.6 + (武器スキルに対応する主能力 + 武器スキル / 2 + (近接武器は戦術、遠距離武器は射撃、ワンドまたは理力武器の場合魔道具)) / 50.0)」です。
プレイヤーが武器の知識フィートを持っている場合、ダメージ倍率に『0.05 * (武器の知識フィートのランク)』だけ加算されます。(事実上、+0.05または+0.10)
貫通率は武器に表記されているものを使用します。[2]
基礎命中力は「(器用、ワンドなら意志) / 4 + 武器スキルに対応する主能力 / 3 + 武器スキル 」を、スタート50、ステップ25、レート75%のCURVE関数で計算した後、50を足したものです。
命中力は「基礎命中力 + 攻撃中の武器の命中修正 + 防具の命中修正合計 + (ワンドのみ:50、それ以外は0)」です。
さらに、弾薬を消費して攻撃した場合:
ダメージ修正に「弾薬のダメージダイスを振った結果 + 弾薬のダメージ修正」を加算します。
命中力に「弾薬の命中修正」を加算します。
遠隔武器の距離修正
distMod = 100;
…
if (!isThrow)
{
if (!IsRanged)
{
attackStyle = CC.body.GetAttackStyle();
}
else if (TP != null)
{
int num = CC.pos.Distance(TP);
distMod = Mathf.Max(115 - 10 * Mathf.Abs(num - toolRange.BestDist) * 100 / (100 + weapon.Evalue(605) * 10), 80);
}
}
…
dMulti = dMulti * (float)distMod / 100f;
toHit = toHitBase + toHitFix;
toHit = toHit * distMod / 100;
遠隔武器には、適正の攻撃距離があり、それによって命中力とダメージ倍率が増減します。
Evalue(605)はmod_precisionであり、遠隔武器の改造道具の精密射撃レベルにあたります。
適正攻撃距離から離れているほど、ペナルティも増えます。
精密射撃の改造道具のない場合、0(適正攻撃距離)の時は命中力、ダメージ共に115%になります、±1は105%、±2は95%、±3は85%、それ以降は80%になります。
精密射撃modの強度と適正距離差による命中力とダメージの倍率(%)は以下の表のようになっています。
精密射撃mod強度 | 適正距離差0 | 適正距離差1 | 適正距離差2 | 適正距離差3 | 適正距離差4 |
---|---|---|---|---|---|
0 | 115 | 105 | 95 | 85 | 80 |
10 | 115 | 110 | 105 | 100 | 95 |
20 | 115 | 112 | 109 | 105 | 102 |
30 | 115 | 113 | 110 | 108 | 105 |
40 | 115 | 113 | 111 | 109 | 107 |
50 | 115 | 114 | 112 | 110 | 109 |
60 | 115 | 114 | 113 | 111 | 110 |
70 | 115 | 114 | 113 | 112 | 110 |
80 | 115 | 114 | 113 | 112 | 111 |
90 | 115 | 114 | 113 | 112 | 111 |
99 | 115 | 115 | 114 | 113 | 112 |
遠隔武器の連射数修正
GameSetting.EffectData effectData = EClass.setting.effect.guns.TryGetValue(weapon.id) ?? EClass.setting.effect.guns[flag2 ? "cane" : (flag ? "gun" : "bow")];
bool hasHit = false;
int numFire = effectData.num;
int numFireWithoutDamageLoss = numFire;
...
if (IsRanged && count >= numFireWithoutDamageLoss)
{
num = num * 100 / (100 + (count - numFireWithoutDamageLoss + 1) * 30);
}
速射modや連続射撃により遠隔武器に追加の射撃が発生している場合、追加の射撃には回数に応じたダメージ減衰が発生します。
ここでの「numFireWithoutDamageLoss」とは遠隔武器の元々の発射数で、「count」は現在何発目の射撃かの変数です。「count」は0スタートで、1発目の射撃では0が代入されています。
追加の射撃のダメージ倍率は以下の式で算出されます。
ダメージ倍率 = 1 / 1 + 0.3 × (現在の発射回数 - 遠隔武器の元々の発射数) ※ここでの「現在の発射回数」とはコード上での「count + 1」です
例えば元々の発射数が3のアサルトライフルを速射modによって発射数を6にした場合、
ダメージ倍率は1発目: 100%、2発目: 100%、3発目: 100%、4発目: 76%、5発目:62%、6発目: 52% となります。
ヴォーパル
ヴォーパルのエンチャントがついた攻撃は、ヴォーパルのエンチャント強度の確率で攻撃の貫通率を100%にします。
物理攻撃エンチャント
Attackの定義を見ています。
内部名 | 日本語名 | 簡易説明 |
---|---|---|
drill | 突貫 | 当たった相手を突き抜けて後方にも当たる。 |
scatter | 拡散 | 範囲攻撃、ウィンチェスタープレミアムなどにしか付いていない |
splash | 衝撃波 | 最初の攻撃対象の周りにも当たる衝撃波を発する |
chaser | 追尾 | 回避された際に追撃する |
flurry | 連撃 | 複数回攻撃する |
旋風 | 攻撃が最初の相手から伝播する | |
feint | 牽制 | 制圧の状態異常を付与する |
frustration | 逆襲 | 回避された際に確率で確定命中クリティカル攻撃をする |
neckhunt | 首狩り | 条件を満たしたら即死させる。 |
突貫
int num2 = GetWeaponEnc(606, addSelfEnc: false); List<Point> list2 = EClass._map.ListPointsInLine(Act.CC.pos, Act.TC.pos, num2 / 10 + ((num2 % 10 > EClass.rnd(10)) ? 1 : 0) + 1); if (num2 > 0) { foreach (Point item in list2) { if (!item.Equals(orgPos)) { Chara firstChara = item.FirstChara; if (firstChara != null && firstChara.IsHostile(Act.CC)) { AttackWithFlurry(firstChara, item, 1f, subAttack: false); } } } }
拡散
int num3 = GetWeaponEnc(622, addSelfEnc: true); else if (num3 > 0) { List<Point> list2 = new List<Point>(); Act.TP.ForeachNeighbor(delegate(Point p) { list2.Add(p.Copy()); }); list2.Shuffle(); int num4 = 0; for (int i = 0; i < 9 && num3 > EClass.rnd(10 + (int)Mathf.Pow(3f, i + 2)); i++) { num4++; } foreach (Point item2 in list2) { foreach (Card item3 in item2.ListCards().Copy()) { if (num4 <= 0 | | !Act.CC.IsAliveInCurrentZone) { break; } if (item3.trait.CanBeAttacked | | (item3.isChara && item3.Chara.IsHostile(Act.CC))) { AttackWithFlurry(item3, item2, 1f, subAttack: true); num4--; } } }
衝撃波
if (splash > 0) { Act.TP.ForeachNeighbor(delegate(Point p) { if (p.Equals(Act.TP) || p.Equals(Act.CC.pos)) { return; } if (!p.IsBlocked) { p.PlayEffect("smoke_shockwave"); p.Copy().Animate(AnimeID.QuakeMini, animeBlock: true); } foreach (Card item4 in p.ListCards()) { if (item4.trait.CanBeAttacked || (item4.isChara && item4.Chara.IsHostile(Act.CC))) { int rawDamage = AttackProcess.Current.GetRawDamage(0.1f + 0.05f * Mathf.Sqrt(splash), crit: false, maxRoll: false); rawDamage = item4.ApplyProtection(rawDamage); item4.DamageHP(rawDamage, 0, 100, AttackSource.Shockwave, Act.CC); } } });
追尾
if (chaser > 0) { for (int j = 0; j < 10; j++) { if (chaser > EClass.rnd(4 + (int)Mathf.Pow(4f, j + 2))) { num5++; } } } bool flag = false; for (int k = 0; k < num5; k++) { if (k > 0) { Act.CC.Say("attack_chaser"); } flag = AttackProcess.Current.Perform(count, hasHit, dmgMulti * mtp, maxRoll, subAttack); if (!flag && frustration > 0 && 10f + 2f * Mathf.Sqrt(frustration) > (float)EClass.rnd(100)) { AttackProcess.Current.critFury = true; flag = AttackProcess.Current.Perform(count, hasHit, dmgMulti * mtp, maxRoll, subAttack); AttackProcess.Current.critFury = false; } if (flag || !Act.CC.IsAliveInCurrentZone || !Act.TC.IsAliveInCurrentZone) { break; } }
逆襲の記述も含めて切り抜いています。
連撃
void AttackWithFlurry(Card _tc, Point _tp, float mtp, bool subAttack) { int num6 = 1; if (flurry > 0) { for (int l = 0; l < 10 && flurry > EClass.rnd(25 + (int)Mathf.Pow(5f, l + 2)); l++) { num6++; } } for (int m = 0; m < num6; m++) { if (!Act.CC.IsAliveInCurrentZone) { break; } if (!_tc.IsAliveInCurrentZone) { break; } if (m > 0) { Act.CC.Say("attack_flurry"); } Attack(_tc, _tp, mtp, subAttack); } }
旋風
牽制
if (Act.TC.IsAliveInCurrentZone && Act.TC.isChara) { Act.CC.DoHostileAction(Act.TC); if (feint > 0 && 10f + 4f * Mathf.Sqrt(feint) > (float)EClass.rnd(100)) { Act.TC.Chara.AddCondition<ConSupress>(100 + 5 * (int)Mathf.Sqrt(feint)); } }
牽制が正の値で、10 + 4*√牽制 が乱数0~99を上回った時、相手に牽制を付与する。
逆襲
flag = AttackProcess.Current.Perform(count, hasHit, dmgMulti * mtp, maxRoll, subAttack); if (!flag && frustration > 0 && 10f + 2f * Mathf.Sqrt(frustration) > (float)EClass.rnd(100)) { AttackProcess.Current.critFury = true; flag = AttackProcess.Current.Perform(count, hasHit, dmgMulti * mtp, maxRoll, subAttack); AttackProcess.Current.critFury = false; }
回避されたときに、逆襲のエンチャント値が正で、10 + 2* √逆襲が乱数0~99を上回っているとき、逆襲が発動します。
命中判定
命中力の算出
基礎の命中力は以下の表の式で算出されます。
武器の種類 | 計算式 |
---|---|
投擲 | CURVE([攻撃者の器用] / 4 + [攻撃者の筋力] / 2 + [攻撃者の武器スキル], 50, 25, 75) + 75(PCのファクション以外の場合250) |
格闘 (盾なし) | CURVE([攻撃者の器用] / 3 + [攻撃者の武器の主能力] / 3 + [攻撃者の武器スキル], 50, 25, 75) + 50 |
格闘 (盾あり) | CURVE([攻撃者の器用] / 3 + [攻撃者の武器の主能力] / 3 + [攻撃者の武器スキル], 50, 25, 75) + 50 の結果に0.75をかけたもの |
ワンド | CURVE([攻撃者の意志] / 4 + [攻撃者の武器の主能力] / 3 + [攻撃者の武器スキル], 50, 25, 75) + 100 |
その他すべての武器 | CURVE([攻撃者の器用or意志] / 4 + [攻撃者の武器の主能力] / 3 + [攻撃者の武器スキル], 50, 25, 75) + 50 |
上記の式で算出した値に装備と武器による命中修正が足し算され、その後遠距離武器には距離による修正が適用されたものが「命中力」となります。
回避力の算出
「回避力」は以下の式で算出されます。
回避力 = CURVE ([攻撃対象の感覚] / 3 + [攻撃対象の回避スキル], 50, 10, 75) + [攻撃対象のDV] + 25
命中力・回避力への補正
命中力・回避力に影響を与える以下の要素は、複合して作用しながら次の表の上から順で適用されます。[4]
条件 | 効果 |
---|---|
攻撃者の慧眼のエンチャント | 命中力 = 命中力 * (1 + 慧眼エンチャント強度 * 0.01) |
攻撃者が災い状態 | 命中力 = 命中力 * 0.75 |
攻撃者が高所にいる | 命中力 = 命中力 * 1.2 |
攻撃者が乗馬している | 命中力 = 命中力 * 100 / (100 + 500 / (5 or 10 + [攻撃者の乗馬スキル] の高い方)) |
攻撃者がペットを寄生させている | 命中力 = 命中力 * 100 / (100 + 1000 / (5 or 10 + [攻撃者の共存スキル] の高い方)) |
騎乗されているペットによる攻撃 | 命中力 = 命中力 * 100 / (100 + 1000 / (5 or 10 + [攻撃者の筋力] の高い方)) |
寄生しているペットによる攻撃 | 命中力 = 命中力 * 100 / (100 + 1000 / (5 または 10 + [攻撃者の器用] の高い方)) |
攻撃者が両手持ち | 命中力 = 命中力 + 25 + sqrt([攻撃者の両手持ちスキル] * 2) |
攻撃者が二刀流 | 命中力 = 命中力 * 100 / (115 + 手の番号 * 15 + 手の番号 *(2000 / (20 + [攻撃者の二刀流スキル])[0-100でクランプ[5]]) |
攻撃者が盲目 | 命中力 = 命中力 * 0.333 (または、遠距離/投擲の場合は0.1) |
対象が盲目 | 回避力 = 回避力 * 0.5 |
対象が混乱もしくは朦朧 | 回避力 = 回避力 * 0.5 |
対象が高所にいる | 回避力 = 回避力 * 1.2 |
二刀流の補足説明:
ここでいう、「手の番号」は利き手・もう片方の手と、カオスシェイプなどが持つ2本目以降の手を表します。
1-100の間でクランプされるのは(2000 / (20 + [攻撃者の二刀流スキル])だけです。つまり、二刀流のペナルティを無効化するには、二刀流スキルが1980必要です。
命中成否判定
命中成否判定では攻撃が命中するか、外れるか、クリティカルになるかするまで、上から順に判定します。
苛立エンチャントの効果による攻撃の場合、確定クリティカル。
対象が朦朧状態の場合、25%の確率でクリティカル
対象が死亡または睡眠状態の場合、確定でクリティカル
[対象の見切りスキル] * 10 > 命中力の場合、見切り成否判定を行う。 見切り力 = 回避力 * 100 / 命中力 とし、以下3つの式を上から順に処理する。[6] 見切り力 > 300 かつ、 random 0 - ([対象の見切りスキル] + 250) > 100 のとき、攻撃は外れる 見切り力 > 200 かつ、 random 0 - ([対象の見切りスキル] + 250) > 150 のとき、攻撃は外れる 見切り力 > 150 かつ、 random 0 - ([対象の見切りスキル] + 250) > 200 のとき、攻撃は外れる
[対象の完全回避] > random 0 - 99 のとき、攻撃は外れる (random X-Yは等確率でXからYまでの乱数を生成する関数。0から99までの値が等確率で選ばれる。完全回避分の確率で回避する。)
random 0 - 19 が 0 のとき、攻撃は命中 (5%で対象の回避を無視して命中する)[7]
random 0 - 19 が 0 のとき、攻撃は外れる (5%で攻撃者の命中を無視して外れる)
命中力 < 1 のとき、攻撃は外れる
回避力 < 1 のとき、攻撃は命中[7]
random 0 - 命中力 < random 0 - (回避力 * 125 (遠距離攻撃なら150) / 100) のとき、攻撃は外れる
random 0 - 5000 < [攻撃者の感覚] + 50 のとき、攻撃はクリティカル
[攻撃者のクリティカルエンチャント合計] + sqrt([攻撃者の心眼スキル]) > random 0 - 200のとき、攻撃はクリティカル
攻撃者が[死の真髄]フィートを所持している場合、以下の判定を行う HP減少率 = 100 - [攻撃者の現在HP] * 100 / [攻撃者の最大HP] HP減少率 >= 50 かつ、 (HP減少率 ^ 4 / 3) > random 0 - 100000000 のとき、攻撃はクリティカル (HPが5割以上減っている状態で、減少率に応じて最小2%~最大33%の確率でクリティカル)
攻撃は命中
補正前ダメージ算出
攻撃力
攻撃者の攻撃力は攻撃のダイス数・ダイス面数・ダメージ修正を使ってダイスロールをした後、戦禍の炎状態によるダメージ修正を追加し、
その後攻撃倍率と距離修正、連射数修正をかけたものです。
(「攻撃能力の算出」の節を参照してください。)
クリティカルだった場合、ダイスロールの結果は最大値になり、格闘攻撃のみ攻撃力が1.25倍になります。
※Elonaと違い、武器の重量によるダメージ倍率は存在しません。
種族特攻エンチャント
void AddBane(bool valid, int idEle, int mod)
{
if (valid)
{
bane += (CC.Evalue(idEle) + ((weapon != null) ? weapon.Evalue(idEle, ignoreGlobalElement: true) : 0)) * mod / 100;
}
}
特攻のエンチャントがついた武器で特攻が有効な種族を攻撃した場合、以下の式の通り攻撃力にボーナスを得ます。
攻撃力 = 攻撃力 × (1 + 0.03 × (有効な種族特攻エンチャント強度の合計) + 0.015 × (全特攻エンチャント強度))
防御力
public virtual int ApplyProtection(int dmg, int mod = 100)
{
int armorSkill = GetArmorSkill();
Element orCreateElement = elements.GetOrCreateElement(armorSkill);
int num = PV + orCreateElement.Value + DEX / 10;
int num2 = 1;
int sides = 1;
int bonus = 0;
if (num > 0)
{
int num3 = num / 4;
num2 = num3 / 10 + 1;
sides = num3 / num2 + 1;
bonus = 0;
dmg = dmg * 100 / (100 + num);
}
int num4 = Dice.Roll(num2, sides, bonus, this);
dmg -= num4 * mod / 100;
if (dmg < 0)
{
dmg = 0;
}
return dmg;
}
攻撃対象の防御力は「防御固定値」と「防御割合」の2つに分かれています。
防御固定値は、ダイス数が「(PV + 軽装or重装スキル + 器用 / 10) / 40 + 1」、ダイス面が「(PV + 軽装or重装スキル + 器用 / 10) / (ダイス数 × 4) + 1」でダイスロールをしたものです。
防御割合は以下の式で算出されます。
防御割合 = 1 / (1 + 0.01 × (PV + 軽装or重装スキル + 器用 / 10))
属性強度・属性変換率
if (weapon != null)
{
foreach (Element value2 in weapon.elements.dict.Values)
{
if (value2.source.categorySub == "eleConvert")
{
num4 = EClass.sources.elements.alias[value2.source.aliasRef].id;
num5 = 50 + value2.Value * 2;
num6 = Mathf.Min(value2.Value, 100);
break;
}
}
}
if (num4 == 0)
{
if (CC.HasCondition<ConWeapon>())
{
conWeapon = CC.GetCondition<ConWeapon>();
num4 = conWeapon.sourceElement.id;
num5 = conWeapon.power / 2;
num6 = (int)Mathf.Min(40f + MathF.Sqrt(conWeapon.power), 80f);
}
if (conWeapon == null && weapon == null && (CC.MainElement != Element.Void || CC.HasElement(1565)))
{
num4 = (CC.HasElement(1565) ? 915 : CC.MainElement.id);
num5 = CC.Power / 3 + EClass.rnd(CC.Power / 2);
if (CC.MainElement != Element.Void)
{
num5 += CC.MainElement.Value;
}
showEffect = false;
num6 = 50;
}
if (conWeapon == null && weapon != null && weapon.trait is TraitToolRangeCane)
{
IEnumerable<Element> enumerable = weapon.elements.dict.Values.Where((Element e) => e.source.categorySub == "eleAttack");
if (enumerable.Count() > 0)
{
num4 = enumerable.RandomItem().id;
num5 = num4 switch
{
920 => 30,
914 => 50,
918 => 50,
_ => 100,
};
}
num6 = 50;
}
}
属性変換エンチャントがついた武器か、唄魔法が有効な攻撃か、ワンドでの攻撃か、属性格闘をもつかエーテル病のエーテルの滴る手にかかったキャラクターの素手による攻撃の場合、物理攻撃は「属性強度」と「属性変換率」をもちます。
条件を複数満たす場合、属性変換エンチャント>唄魔法>属性格闘>ワンド の順で優先されます。
属性強度
属性強度とは、状態異常を付与する際に使用される強度です。値が大きい程状態異常にしやすく、状態異常の強度が上がります。
属性変換エンチャントのついた武器の属性強度は「50 + 属性変換エンチャント強度 × 2」です。
唄魔法が有効な攻撃の属性強度は「唄魔法のパワー / 2」です。
属性格闘の属性強度はキャラクターのLvと構成素材に依存(キャラクター毎に素材が異なり複雑過ぎるため計算式は省略)します。
ワンドの属性強度は混沌属性は「20」、幻惑と神経属性は「50」、それ以外は「100」で固定です。
属性変換率
属性変換率とは、攻撃対象の防御力を無視する割合です。
属性変換エンチャントのついた武器の属性変換率は「属性変換エンチャント強度」%で、最大100%です。
唄魔法が有効な攻撃の属性変換率は「40 + √(唄魔法のパワー)」%で、最小40%、最大80%です。
属性格闘の属性変換率は「50」%で固定です。
ワンドの属性変換率は「50」%で固定です。
ダメージ計算
これまで求めてきた攻撃力、貫通率、防御力、属性変換率を使用してダメージ計算を行います。
int num7 = num;
int num8 = num * num6 / 100;
num -= num8;
int num9 = num * penetration / 100;
num -= num9;
num = TC.ApplyProtection(num) + num9 + num8;
TC.DamageHP(num, num4, num5, (!IsRanged && !isThrow) ? AttackSource.Melee : AttackSource.Range, CC, showEffect, weapon);
まず、属性変換によるダメージと貫通によるダメージ、防御力による軽減を計算します。
属性変換ダメージ = 攻撃力 × 属性変換率 貫通ダメージ = (攻撃力 - 属性変換ダメージ) × 貫通率 非貫通ダメージ = (攻撃力 - 属性変換ダメージ - 貫通ダメージ) × 防御割合 - 防御固定値 ※(負の値になった場合0に補正)
以上から、物理攻撃によるダメージは以下の通りです。
軽減後ダメージ = 属性変換ダメージ + 貫通ダメージ + 非貫通ダメージ
この後、DamageHP関数の中で属性耐性などの各種補正によって最終的なダメージは増減します。
属性追加ダメージエンチャント
foreach (Element item in list2)
{
if (!TC.IsAliveInCurrentZone)
{
break;
}
if (item.IsActive(weapon) && item.source.categorySub == "eleAttack")
{
int num10 = 25;
int dmg = EClass.rnd(num * (100 + item.Value * 10) / 500 + 5);
if (conWeapon == null && weapon != null && weapon.trait is TraitToolRangeCane)
{
num10 = 0;
}
if (num10 > EClass.rnd(100))
{
TC.DamageHP(dmg, item.id, isThrow ? (100 + item.Value * 5) : (30 + item.Value), AttackSource.WeaponEnchant, CC);
}
}
}
Proc(list2);
属性追加ダメージエンチャントの付与されたワンド以外の武器か弾の攻撃が命中した場合、付与された属性追加ダメージエンチャントそれぞれについて追加の属性攻撃を行います。
それぞれの属性追加ダメージの最大値は以下の式で算出されます。
属性追加最大ダメージ = 5 + 軽減後ダメージ × (0.2 + エンチャント強度 × 0.02)
0~属性追加最大ダメージまでの範囲の内のランダムな値が属性ダメージとなります。
追加の属性攻撃の発動率はそれぞれ「25」%で固定です。
属性攻撃の属性強度は投擲武器のみ「100 + エンチャント強度 × 5」、それ以外は「30 + エンチャント強度」です。
シールドバッシュ
if (!IsRanged && attackStyle == AttackStyle.Shield)
{
int num11 = CC.Evalue(123);
if (CC.elements.ValueWithoutLink(123) >= 10 && Mathf.Clamp(Mathf.Sqrt(num11) - 2f, 8f, 12f) > (float)EClass.rnd(100))
{
num = num7 * Mathf.Min(50 + num11, 200) / 100;
num = TC.ApplyProtection(num);
Debug.Log("Bash:" + num + "/" + num7);
CC.PlaySound("shield_bash");
CC.Say("shield_bash", CC, TC);
TC.DamageHP(num, AttackSource.None, CC);
if (TC.IsAliveInCurrentZone && TC.isChara)
{
if (EClass.rnd(2) == 0)
{
TC.Chara.AddCondition<ConDim>(50 + (int)Mathf.Sqrt(num11) * 10);
}
TC.Chara.AddCondition<ConParalyze>(EClass.rnd(2), force: true);
}
}
}
盾スキルが10以上の盾を持つキャラクターの近接攻撃が命中した場合、シールドバッシュの判定が行われます。
シールドバッシュの発生確率は「√(攻撃者の盾スキル) - 2」%で、最小で8%、最大で12%になるよう補正されます。
シールドバッシュのダメージは以下の式で算出されます。ただし、このダメージは攻撃対象の物理防御力によって軽減されます。
シールドバッシュのダメージ = 軽減後ダメージ × MIN((0.5 + 攻撃者の盾スキル × 0.01), 2)
シールドバッシュは唄魔法や属性変換エンチャントなどに関わらず無属性ダメージとなります。
50%の確率で、1ターンの麻痺を攻撃対象に耐性や無効化エンチャントを無視して強制的に付与します。
50%の確率で、状態異常強度が「50 + 10 × √(攻撃者の盾スキル)」の朦朧を攻撃対象に付与します。
- ↑ Jump up to: 1.0 1.1 1.2 1.3 エーテル病の殺戮への飢えが該当する。
- ↑ Jump up to: 2.0 2.1 2.2 固有の貫通率を持っているキャラクターであればその値も加算される。
- ↑ 投擲武器でないときは0
- ↑ プログラムでは、X=X+1のように、同じ文字が一つの式に複数回登場して右辺にあるものが調整前の数字、左辺にあるものが調整後の数字になる記法があります。
- ↑ クランプとは値に上限と下限を適用するという意味です。この場合、確率なので0から100%に設定されています
- ↑ 見切り力が301以上であれば、見切りによる回避判定は3回行われる
- ↑ Jump up to: 7.0 7.1 この場合、クリティカルにはならない。