戦闘中に使う計算式を説明をします。
行動順
// 行動順を決定する1~10までの値を取得します。
// この値が低いほど、先に行動できます。
function getActionOrder(agi) Number
{
// すばやさが 0 の場合 Enemy と判断し、その場合はランダムで値を決めます
if (agi == 0) {
return 1 + Dice.Cast(1, 8);
}
var agiBonus = 3;
if (agi >= 15) agiBonus = 14 - agi;
else if (agi >= 8) agiBonus = 0;
else if (agi >= 6) agiBonus = 1;
else if (agi >= 4) agiBonus = 2;
var order = Dice.Cast(1, 10) + agiBonus;
if (order < 1) order = 1;
if (order > 10) order = 10;
return order;
}
function getFightLevel(Level, STR, WeaponSTR): Number
{
// ちからが 0 の場合は Enemy と判断して、レベルを使います。
if (STR == 0)
return Level;
var strBonus = 0;
if (str > 15)
strBonus = str - 15;
else if (str < 6)
strBonus = str - 6;
var levelBonus = Level/3;
return strBonus + levelBonus + WeaponSTR;
}
function getHitRate(targetAC, targetGroupNo, targetIsMovable, Level, STR, WeaponSTR): Number
{
// 命中率 = 5 * (AC + A - (3 * グループ番号))
var A = getFightLevel(Level, STR, WeaponSTR);
var hitRate = 10 + targetAC + A - (3 * targetGroupNo);
hitRate *= 5;
if (targetIsMovable == false)
hitRate += 20;
if (hitRate > 95) hitRate = 95;
if (hitRate < 5) hitRate = 5;
return hitRate;
}
// PC がエネミー攻撃時
function getCriticalHitRate(CharLevel, EnemyLevel)
{
var p1 = min(CharLevel, 25) / 50;
var p2 = max(0, 24 - EnemyLevel) / 35;
return p1 * p2 * 100;
}
// エネミーが PC 攻撃時
function getCriticalHitRate(EnemyLevel, pc: PlayerCharacter)
{
var fortuneCorrectionValue = 2; // 未対応の為固定値。本来クラス・種族に設定される値
var fortuneValue = max(0, 19 - pc.getLevel()/5 - pc.getLuck()/6 - fortuneCorrectionValue);
var registanceRate = pc.getCriticalRegistanceRate(); // 装備している防具類1つで50%、2つで75%・・・の様に低効率が上昇
var p1 = (1 + fortuneValue) / 20;
var p2 = (1 + EnemyLevel) / 50;
var p3 = (100 - registanceRate) / 100;
return p1 * p2 * p3 * 100;
}
function getBreathEvasionRate(pc: PlayerCharacter)
{
var p1 = max(0, pc.getLuck() - 15) / 20;
return p1;
}
function useSkill(skill: Skill, user: Battler, target: Battler)
{
// 計算式による抵抗率を取得
var validFormulaId = FormulaDatabase.isValidFormulaId(skill.getResistanceFormulaId());
var resistanceRate = 0;
if (validFormulaId) {
var args = [user, target]; // a b で参照される計算式の引数
resistanceRate = FormulaDatabase.evaluate(skill.getResistanceFormulaId(), args);
}
// 失敗率を取得
var failureRate = 100 - skill.getSuccessRate();
// 失敗率と抵抗率どちらかが該当するか判定
if (Probability.testByPercent(resistanceRate) || Probability.testByPercent(failureRate)) {
// 味方に向けてのスキルで失敗した場合は状態を深化させる
if (skill.isForFriend()) {
target.deepenStates(skill.getStates());
}
return StringTable.get("The spell is not effective to [target]!");
}
// 抵抗率計算式が設定されていない場合
if (!validFormulaId) {
// スキルが敵に向けたものかつ呪文タイプの場合
if (skill.isForOpponent() && skill.isMagicalType()) {
// 知恵か信仰心によるスキルボーナスを取得
int skillBonus = 0;
if (skill.isMageType()) {
skillBonus = Math.max(0, user.param("int") - 15);
}
else if (skill.isPriestType()) {
skillBonus = Math.max(0, user.param("pie") - 15);
}
// 敵に設定された呪文無効化率で呪文を邪魔するか判定
int resistanceRate = target.getCantripInvalidityRate() - skillBonus*5;
if (Probability.testByPercent(resistanceRate)) {
// 既に死亡している場合はメッセージ無し
if (target.isDead())
return "";
return StringTable::get("[target] resists the spell!");
}
}
}
// ダメージや能力値上昇などの処理
var message = "";
// 状態回復と状態抵抗処理
var states: Array = skill.getStates();
for (var i = 0; i < states.length; ++i) {
var state = states[i];
if (skill.isForFriend()) {
// 味方に向けたスキルの場合は無条件で状態を取り除く
target.removeState(state);
}
else {
if (validFormulaId) {
// 抵抗率計算式が設定されていた場合は無条件で状態を追加
target.addState(state);
}
else {
// 敵に向けたスキルで抵抗できなかった場合、状態を追加
var resistanceRate = target.getStateResistanceRate(state); // 装備、種族、体力による抵抗率を取得
if (Probability.testByPercent(100 - resistanceRate)) {
target.addState(state);
}
}
}
}
return message;
}
// レベルに応じた最大HPは、クラスに応じた面数のダイスを、現在レベルの回数だけ振った合計になります。
// ・ダイスの面数の計算
// ダイスの面数は、生命力に応じた補正値とクラスの LevelUpHP に設定した値を足したものです。
// 生命力3以下 補正値 = -2
// 生命力4~5 補正値 = -1
// 生命力6~15 補正値 = 0
// 生命力16~ 補正値 = (生命力 - 15)
// ダイスの面数 = LevelUpHP + 補正数
// ・最大HP
// 現在のレベルだけ上記のダイスを振り、出た目を合計する。
// 合計が現在の最大HPより下の場合、現在の最大HP+1を出た目の合計とする。
// ※初期レベルのHPは上で算出された値に4を足しますが、仕様変更になるかもしれません。
// ・例:生命力15で LevelUpHP が10の場合の最大HP
// レベル1:4+1~10
// レベル2:(1~10) ×2 生命力が1上がって16になる
// レベル3:(1~11)×3
function calculateMaxHP(pc: PartyCharacter): int
{
var VIT = pc.paramBase("vit");
var classData = pc.getClass();
var bonus = 0;
if (VIT <= 3) bonus --;
if (VIT <= 5) bonus --;
if (VIT > 15) bonus = VIT - 15;
// Database > Class で設定した値 LevelUpHP
var LevelUpHP = classData.getLevelUpHP();
// レベル 10 で 生命力が 15 で LevelUpHP が 8 の場合、最大値HP は 10D23 つまり 23~230が設定されます。
var hp = Dice.Cast(getLevel(), LevelUpHP + bonus );
var maxHP = pc.getMaxHP();
// 現在の 最大HP が上の結果より大きい場合、レベルアップで上がる HP は 1 になります。
if (maxHP >= hp) {
return maxHP + 1;
}
return hp;
}
function levelUpMP(pc: PartyCharacter): void
{
// 1. 種類とランク別に現在覚えている魔法の数を数える。タイプ 0 は黒魔法 1 は白魔法
var skillCnt[2][8];
for (var i = 0; i < pc.getLearningSkillCount(); ++i) {
var skill = pc.getLearningSkillAt(i);
var type = skill.getType();
var rank = skill.getRank();
skillCnt[type][rank] += 1;
}
// 2. キャラクターの現在の Level と Class と 1 を元に、現在の最大 MP を計算する
var classID = pc.getClassID();
var pcLevel = pc.getLevel();
var classData = CharClassList.getAt(classID);
for (var rank = 1; rank < 8; ++rank) {
for (var type = 0; type < 2; ++type) {
// データベースに指定のランクが登録されていない場合は
// これ以上処理しないでタイプを切り替える
if (skillCnt[type][rank] == 0)
continue;
// Database > Class で設定した覚えるスキルの表から
// ループで使うためにクラス別の覚えるスキルの数を取得
// 次のループで指定ランクのスキルを覚える最初のレベルを取得
// 例 ファイアとスリープのランクが 1 で、覚えるレベルが 1 と 2 の場合
// learningLevel つまりスキルを覚える最初のレベルは 1 になります。
var learningSkillCount = classData.getLernningSkillCount();
var learningLevel = 0;
for (var i = 0; i < learningSkillCount; ++i) {
var id = classData.getLearningSkillIDAt(i);
var skill = CharSkillList.getAt(id);
if (skill.getRank() == rank) {
var lv = classData.getLearningSkillLevelAt(i);
if (learningLevel == 0)
learningLevel = lv;
else
learningLevel = Math.min(learningLevel, lv);
}
}
// 現在のレベルで設定されうる MP
// 上の例で現在レベル 5 の場合は
// 5 - 1 + 1 = 5 つまり MP = 5 になります。
var mpLevel = pcLevel - learningLevel + 1;
// 設定する現在の MP の最大値。 9 以上にはなりません。
var maxMP = Math.max(mpLevel, skillCnt[type][rank]);
// 現在のクラスがそのランクのスキルを覚えない場合は
// 現在のキャラクターが覚えているスキルの数が MP になります
if (learningLevel <= 0)
maxMP = skillCnt[type][rank];
if (maxMP > 9)
maxMP = 9;
// キャラクターに 最大MP をセットする
pc.setMaxMPAt(rank, type, maxMP);
}
}
}
// 25% の確率で変化しません Dice.Cast(個数, 面数)
if (Dice.Cast(1, 4) == 4)
return;
var value = 1;
// 以下の条件が真の場合、能力値が下がる、または変わらないのどちらかになります。
if (Dice.Cast(1, 130) < age) {
// 能力値が18以上の場合 5/6 の確率で変化しません。
if (ability >= 18) {
if (Dice.Cast(1, 6) < 6)
return;
}
// 3 未満の場合も変化しません。
if (ability < 3)
return;
value = -1;
}
// 能力値が、種族の基本能力値 + 10 以上になる場合も変化しません。
if (ability + value >= baseAbility + 10)
return;
ability = ability + value;
// ピット発動?
if (pc.agility < Dice.cast(1, 25) + mapLevel) {
var damage = Dice.cast(mapLevel, 8);
pc.hp -= damage;
}
// 罠の識別率を取得
function getTrapInspectionRate(pc: PartyCharacter)
{
var factor = pc.getThiefLevel() + 1;
return = min(95, pc.getAgility() * factor);
}
// 罠の解除率を取得
function getTrapDisarmRate(pc: PartyCharacter, mapLevel: int)
{
var classBonus = pc.getThiefLevel() * 10;
var p = (pc.getLevel() - mapLevel - 7 + classBonus) / 70;
return max(5, p * 100);
}
// 罠を外せなかった場合、罠の発動率を取得
function getTrapActivationRate(pc: PartyCharacter)
{
var p = (20 - pc.getAgility()) / 20;
return max(5, p * 100);
}
function getSecretDoorDetectionProbability(pc: PartyCharacter, mapLevel: int) {
var classBonus = pc.getDetectionLevel() * 5;
if (classBonus == 0)
return 0;
var p = (pc.getLevel() - mapLevel) * 3 + classBonus;
return max(5, min(95, p));
}