スキル[攻撃]の定義 - roratorio-hub/ratorio GitHub Wiki

死霊浄化を例にファイルを解析する
死霊浄化は新しいスキルなのでこの書き方が計算機の最新仕様と見ている

自身の周辺 19 x 19セルの敵に無属性魔法ダメージを与える。攻撃属性は、暖かい風の属性が適用される。
自身の城隍堂の範囲内で使用、または対象が「死霊憑依」状態の場合、より大きなダメージを与える。
影響 : 使用者の「BaseLv」「Spl」「霊道術修練の習得レベル」「ソウルエナジー消費数」

[Lv 1] 攻撃力 400% / 城隍堂、死霊憑依状態 500%
[Lv 2] 攻撃力 450% / 城隍堂、死霊憑依状態 600%
[Lv 3] 攻撃力 500% / 城隍堂、死霊憑依状態 700%
[Lv 4] 攻撃力 550% / 城隍堂、死霊憑依状態 800%
[Lv 5] 攻撃力 600% / 城隍堂、死霊憑依状態 900%

skill.dat.js

まずスキルのインデックスを定義する

[1196,5,"(×)死霊浄化"],

CSkillManager.js

つぎにスキルの基本情報を定義する

// ----------------------------------------------------------------
// 死霊浄化
// ----------------------------------------------------------------
SKILL_ID_SHIRYO_ZYOKA = skillId;
skillData = new function() {
	this.prototype = new CSkillData();
	CSkillData.call(this);
	this.id = skillId;
	this.name = "(×)死霊浄化";
	this.kana = "シリヨウシヨウカ";
	this.maxLv = 5;
	this.type = CSkillData.TYPE_ACTIVE | CSkillData.TYPE_MAGICAL;
	this.range = CSkillData.RANGE_LONG;
	this.element = CSkillData.ELEMENT_VOID;
};
this.dataArray[skillId] = skillData;
skillId++;

死霊浄化はまだ暫定追加されたスキルなので
上を見て分かる通り詠唱やディレイの情報が定義されていない
目指すべき完成形の例としてエビパーティーを示す

// ----------------------------------------------------------------
// エビパーティー
// ----------------------------------------------------------------
SKILL_ID_EBI_PARTY = skillId;
skillData = new function() {
	this.prototype = new CSkillData();
	CSkillData.call(this);

	this.id = skillId;
	this.name = "エビパーティー";
	this.kana = "エヒハアテイイ";
	this.maxLv = 5;
	this.type = CSkillData.TYPE_ACTIVE;
	this.range = CSkillData.RANGE_SHORT;
	this.element = CSkillData.ELEMENT_VOID;

	this.CostFixed = function(skillLv, charaDataManger) {
		return 150;
	}

	this.CastTimeVary = function(skillLv, charaDataManger) {
		return 3000;
	}

	this.DelayTimeCommon = function(skillLv, charaDataManger) {
		return 1000;
	}

	this.CoolTime = function(skillLv, charaDataManger) {
		return 1000;
	}

};
this.dataArray[skillId] = skillData;
skillId++;

caraDataManagerが渡されているからキャラクタの状態を色々取ってくることが可能?
ナイトウォッチのように武器種によってクリティカルするスキルは現在head.jsで条件分岐させているけど
CSkillManager.jsに持ってこれるならその方がありがたい気がする

head.js

最後にスキルのダメージ計算式を function BattleCalc999Core() の中に書いていく
この関数の中では以下の順に処理が行われている

  1. 物理スキル 基本計算式
  2. ダメージ計算(物理基本式)
  3. 物理スキル 特殊計算式
  4. 魔法判定スキル

スキルに応じた適切な位置に処理を書く必要がある
例えば物理スキルの「オンリーワンバレット」を
魔法判定エリアに定義されている「死霊浄化」のすぐ後ろに書いた場合
既に物理攻撃ダメージの算出は終わっているので
オンリーワンバレットのダメージは 0 になってしまう

追記する位置を探すのが大変なのでコメントでマーカーを追記しました
これを頼りに追記してください

↑ 物理攻撃スキル追加位置
↑ 魔法攻撃スキル追加位置

死霊浄化は詠唱などの情報が未定義なので該当コードがコメントアウトされている
CSkillManager.js の定義が完成してからコメントを外せば詠唱やディレイが実装されるはず

case SKILL_ID_SHIRYO_ZYOKA:
	// TODO: 詠唱時間等未実測スキル
	g_bUnknownCasts = true;

	// 属性は暖かい風依存
	n_A_Weapon_zokusei = eval(document.calcForm.A_Weapon_zokusei.value);

	// 詠唱時間等
	/*
	wCast = g_skillManager.GetCastTimeVary(battleCalcInfo.skillId, battleCalcInfo.skillLv, charaData);
	n_KoteiCast = g_skillManager.GetCastTimeFixed(battleCalcInfo.skillId, battleCalcInfo.skillLv, charaData);
	n_Delay[2] = g_skillManager.GetDelayTimeCommon(battleCalcInfo.skillId, battleCalcInfo.skillLv, charaData);
	n_Delay[7] = g_skillManager.GetCoolTime(battleCalcInfo.skillId, battleCalcInfo.skillLv, charaData);
	*/

	// 基本倍率、SPL補正
	if (n_B_IJYOU[MOB_CONF_DEBUF_ID_SHIRYO_HYOI]) {
		wbairitu = 400 + (100 * n_A_ActiveSkillLV);
	}
	else {
		wbairitu = 350 + (50 * n_A_ActiveSkillLV);
	}

	// SPL補正
	wbairitu += 2 * GetTotalSpecStatus(MIG_PARAM_ID_SPL);

	// ベースレベル補正
	wbairitu *= n_A_BaseLV / 100;

	break;

DEF無視のスキルは上記に加えて function _SUB_ApplyMonsterDefence() に追加の処理を書く

/**
 * モンスターの防御力を適用する.
 * @param dmg ダメージ
 * @return 適用後のダメージ
 */
function _SUB_ApplyMonsterDefence(mobData, dmg){

	var bPenetrate = false;



	// DEF無視スキルのチェック

	// カウンタースラッシュ
	if(n_A_ActiveSkill==469) {
		bPenetrate = true;
	}

(参考)ファイアーダンス

skill.dat.js

SKILL_ID_FIRE_DANCE = 830;
[830,10,"ファイアーダンス"],

CAttackMethodAreaComponentManager.js

//----------------------------------------------------------------
// リベリオン:ファイアーダンス
//----------------------------------------------------------------
case SKILL_ID_FIRE_DANCE:
	// オプションリストを生成、追加
	attackMethodOptList = funcCreateOptionListAsLearnLvSelect(attackMethodOptList, SKILL_ID_DEATHPERAD, -1);
	break;

CSkillManager.js

// ----------------------------------------------------------------
// ファイアーダンス
// ----------------------------------------------------------------
SKILL_ID_FIRE_DANCE = skillId;
skillData = new function() {
	this.prototype = new CSkillData();
	CSkillData.call(this);
	this.id = skillId;
	this.name = "ファイアーダンス";
	this.kana = "フアイアアタンス";
	this.maxLv = 10;
	this.type = CSkillData.TYPE_ACTIVE | CSkillData.TYPE_PHYSICAL;
	this.range = CSkillData.RANGE_LONG;
	this.element = CSkillData.ELEMENT_VOID;
	this.CostFixed = function(skillLv, charaDataManger) {
		return 30 + 2 * skillLv;
	}
	this.Power = function(skillLv, charaDataManger) {
		return -1;
	}
	this.DelayTimeCommon = function(skillLv, charaDataManger) {
		return 1000;
	}
};
this.dataArray[skillId] = skillData;
skillId++;

head.js

case SKILL_ID_FIRE_DANCE:
	wbairitu = 1000 + 100 * n_A_ActiveSkillLV;
	wbairitu += 20 * attackMethodConfArray[0].GetOptionValue(0);
	wbairitu = ROUNDDOWN(wbairitu * n_A_BaseLV / 100);
	n_Enekyori=1;
	wCast = 0;
	n_Delay[2] = 1000;
	n_Delay[7] = 0;
	break;