投稿記事

2020年 06月の記事 (7)

ニル 2020/06/23 12:18

育成システムについて考える

育成システムについて考える

RPGだけでなく色々なゲームでありますよね。育成システム。
その筆頭がレベルであり、他にもトレーニングや使い込みで永続的に能力が上がる……
とかだったり、FF10のスフィア盤なんかも独特ですよね。
そういう多種多様な育成システムがある中で、

俺が好きなのはスキルツリーシステムなんですよね。

↑の画面はグリムドーンというハクスラです。

フトコロさんのスキルツリープラグインもとても素晴らしいモノなのですが、

強化したらどうなるかは分からないんですよねー。
それと、威力だけは計算式でどうにかなりますが、
追加効果とかはどうにもならないです。
その辺りの説明も含めるとスキルそのものの説明文を書き換えるしかないわけで。


レベル分のスキルを用意するか……?


と、実はかなり初期の段階で一度、
このプラグインを試した後に考えたことがありました。


結果から言えば、却下したんですけどね。
その理由は自作戦闘システムである、

『スキル連携:チェーンシステム』

にも深く結びついていて、あれって実は取得しているスキルと関連するスキルを、
2つも持ってるんですよ。

https://www.youtube.com/watch?v=hHvSehdW1XU&t=353s

以前も貼った動画ですが、こういう感じの連携です。


【フルスイング】という戦闘で用いられるスキル

【フルスイング】(連携可能)
【フルスイング】(連携不能)

この二つの何方を覚えているかで、
フルスイングへの連携を許可するかしないかを決めています。

2個のスキルで分岐することも出来るのですが、
設定時は名前で【連携可能】とか見えてる方が良いですけど、
戦闘中は見えて欲しくないじゃないですか。

そんな訳で一つに付き3倍のスキルとなってしまいました。
アイテムとかじゃないのは、アクターそれぞれの取得状況を判別出来ると言うのが、
最も都合が良かったからですね。


……でまぁ、これでランクによってスキル数が肥大化すると、条件分岐が肥大化し、
もう手に負えないと考えたから実装を見送った経緯があります。

余談

ただ、一つ思いついたのは、この連携可否をスキルの取得回数で分岐させる事で、
スキルの数を3分の1……とまではいかずとも、半分未満まで削れそうなんですよね。
その場合、スキルツリーシステムで取得状況を1段階だけ戻す。
という処理の追加さえできればと思いますがー……。

ガワだけは割と簡単に出来ましたが、中身の処理が出来ません。

Window_StsConf.prototype.makeItemList = function() {
  this._data = [
    {dicision:true, disp:FTKR.STS.conf.okFormat},
    {dicision:true, disp:FTKR.STS.conf.declineFormat},
    {dicision:false, disp:FTKR.STS.conf.cancelFormat}

  ];
};

    {dicision:true, disp:FTKR.STS.conf.declineFormat},        

が追加した行ですが、dicisionはtureかfalseしか入らない…?
その上、ここで選んだ処理内容で進むので、現状は一段階戻るを押したところで、
true 側の処理。つまり一段階、取得段階が進むだけです。

なんとかしたいなぁ。

やりたいことは、ここの分岐で取得段階が2以上のスキルに限り、
1段階下げるというもの。そもそもデフォルトで一段階戻すことを用意していないのは、
ツリーでより上位のスキルの取得状況との兼ね合いとかをどうするかに迷った?
とか面倒になったから、一括リセットしかないのかなと。

なので、スキルの取得状態及び、前提スキルの状態は維持したまま、
スキルの取得回数を一段階下げる事を可能にしたい。

……ということですね。

一段階下げる処理だけであれば

Game_Actor.prototype.stsCountUp = function(skillId) {
    if (FTKR.STS.enableSkillCount) {
        this.setStsSkillCount(skillId, this.stsCount(skillId) + 1);
    } else {
        this.setStsSkillCount(skillId, + 1);
    }
};

これをこういう感じの文を一段階下げる分岐に与えれば良いと思うのですが、

this.setStsSkillCount(skillId, this.stsCount(skillId) - 1);
        

そもそもそこまで処理としてたどり着けないんですよね。



もし分かる方がいらっしゃいましたら、ご教授頂けたらめっちゃ喜びます。
スクリプト難しい。マジで難しい。

更に余談

そういうスキル圧縮が出来れば、スキル枠が開いてくるので、
スキルツリーにパッシブスキルを入れていけそうなんですよね。
ただ、パッシブスキルって色々見ていっても、
やっぱり、独自のステータスを増やす事とかは出来なさそうなんですよ。

例えば、属性攻撃力とかね?

で、そういうモノって”特徴”を有する場所に記述できるケースが多くて、
何が言いたいかって、枠は余計に食いますが、
ステートが中継地点としては一番使い勝手が良いわけです。

で、

YEP_AutoPassiveStates

は、スキルにパッシブステートを付ける事が出来るので、
空のパッシブスキルに扱いのモノに、ステートを付与する事で、
自由自在なステータス強化が可能になる。と。

そうするとですよ。
多様なプラグインから引っ張ってきた、多くの独自仕様を変更させることが出来る、
とてもスキルツリーらしいスキルツリーが出来そうです。

まぁ、その分スキルとステートの幅を取ってしまいますが。

……という訳で、暫くは改変を頑張ってみます。
無理そうならツクマテなりで質問する事にしますかねー。



なんか余談のまま終わっちゃいましたがそんな感じです。

ニル 2020/06/22 10:39

スキル計算式とプラグインの話

スキルのダメージ計算に自作関数を

これ自体はより詳しい先人もいらっしゃいますが、
当時自分で何処がよくわからなかった事を思い出して、記事を書いてみます。

スクリプトはまだまだなので、
どこか間違ってたら申し訳ないけど、多分あってる、多分。

うるせえ!サンプルだけよこせ!
って人は一番最後にプラグインが置いてあるんでそちらにどうぞ~


Ci-enのブログ、なんか米印が潰されてしまうので × にしてあります。

作ろうとするスキル

デフォルト
a.atk × 4 - b.def × 2

つくるやつ
(a.atk - b.def × 0.5) × スキル威力

これをベースとします。ツクールのデフォ計算式に近いですね。
スキル威力が1だと、それを丁度4分の1した値となります。
スキル威力4で、デフォの通常攻撃と同じ威力ですね。

0.5の値は相手の防御力影響を決める数値ですね。
ここも例えば貫通率が高いスキル……みたいに変動させたいので、

(a.atk - b.def × 貫通率) × スキル威力

といった感じにします。
これが全ての基礎になる計算式ですね。




次に、運の値を持ってきます。ちょっと複雑なので順を追います。

① 0~自分の運の数値までをランダムで抽選

② 0~相手の運の数値までをランダムで抽選

③ ① - ②

例をあげますかね。
ハロルド君の運は999。スライムの運が10だとします。
この場合、0~999の中で抽選された数値 - 0~10の中で抽選された数値

つまり、答え(ダメージ)は -10 ~ 999 という事になります。

自分の運が高ければ高い程、高いダメージが出やすく、最大値も高い。
但し、相手の運が高ければ高い程ダメージを抑えられる確率も高い。

…という感じですね。式にするとこんな感じになります。

a.luk = Math.floor( Math.random() × (a.luk + 1))
b.luk = Math.floor( Math.random() × (b.luk + 1))

damage = (a.luk - b.luk) × level

このままじゃスキルの計算式には入りませんけどね。
もっと簡潔に書けるかもしれないけど俺は分かりません!



この、基礎となるといった
自分の攻撃・相手の防御から算出するダメージと、
自分の運・相手の運から算出するダメージのを比較し、高い方を取る。
……というのが、今回のサンプル計算式となります。


実際の設定

計算式には

Luk_atk(a, b, 0.5, 1)

という値が入っています。


そして、プラグインファイルには、18行目から

function luk_atk(a, b, perforate, level){

から続く関数が入っています。
ちょっと文字の色に注目して見てくださいね。


luk_atk(a, b, 0.5, 1) ← スキル計算式

function luk_atk(a, b, perforate, level){ ← プラグインの中身の関数


これはスキルで記述した名前(緑の文字)をプラグインから引っ張っています。
そして、()内の青文字は , で区切られて4つの数値が入っています。

スキル計算式の方は
(a, b, 0.5, 1)

プラグインの方は
(a, b, perforate, level)

1~2番目の数値

a と b は、デフォルトの計算式でも用いられている、a.atk や b.def に用いられる情報で、主体と対象の情報です。デフォルトであれば

主体の攻撃 - 対象の防御

というような形になっているわけですね。
今回は a と b という情報だけをプラグインに渡しています。

つまり、HPやら会心率やら、属性有効度やら。

原理とか仕組みとか正直あまり詳しくはわかりませんが、
主体情報・対象情報のデータベースを開く鍵を渡しているようなものです(多分)

3番目の数値

0.5 と  perforate は、貫通率です。
別に元々そういう機能が用意されている、とかいうわけではなく、

スキル計算式の方から、3番目に送った数値が0.5というだけです。
そして、プラグインの方ではその3番目の数値に俺が勝手に
perforate という名前を付けて、貫通率として計算しているだけですね。

4番目の数値

1 と level ですね。

これはスキル威力になっています。
4であればデフォルトの通常攻撃と同じになります。
これも3番目の数値と同様に、俺が勝手に名前をつけただけです。
プレイヤーレベルとちょっと混同しやすいかもしれませんけど。


計算に必要な値の説明や記述

少しわかって来たでしょうか?


スキル計算式の方は
(a, b, 0.5, 1)

luk_atk という関数を参照せよ。その際、4つの情報を持っていけ。

( a = 主体情報, b = 対象情報, 0.5 = 貫通率, 1 = スキル威力)

という感じですね。



そして、プラグインの方は
(a, b, perforate, level)

受け取った4つの値にそれぞれ、
(a,b,perforate, level)という名前を付けて、計算をしていくことになります。



function luk_atk(a, b, perforate, level){
↑ここまで説明が終わりました

{ ← は、これを使って計算するスペースはここからだぜ!ってことですね。
その計算が↓から始まります。

var a_atk = a.atk;
var a_luk = a.luk;


var ← これは変数を作れってこと
var a_atk ← これで、a_atk という名前の変数を作れ
var a_atk = a.atk; ←これでa_atk という名前の変数を作れ。中身はa.atk だ。になります。

元の値を弄ってしまうのは良くないので、a_atkという名のコピーを作っている感じです。これも、名前に関しては俺が勝手に決めています。

仮に var で作った名前が、sasaki であろうと suzuki であろうと中の値に影響はありません。

でも、佐々木や鈴木の中に攻撃力とか運が入ってたら後で見返した時に訳わからんでしょ? っていうだけです。

こうしてコピーを増やした理由は、
例えばダメージ計算の為だけにキャラの攻撃力自体が増えたらバグの温床になってしまうからですね。

今回はa.atk と a.luk の情報が必要なので、それを呼び出し、コピーしています。
以下の記述も概ね同じですね。対象の防御と運をコピーしています。

var b_def = b.def;
var b_luk = b.luk;

最後のこれは、最終的にスキルの方に計算結果であるダメージを返すのですが、
攻撃力側の算出と運側算出を比較するために、こうして先に変数を用意している感じですね。

var damage = 0;
var damage2 = 0;


さて、↓まで説明が終わりました。これでもう半分ですよ!

function luk_atk(a, b, perforate, level){ //スキル計算式から受け取った4つの値を持つ
 var a_atk = a.atk; //a_atk という変数を用意し、a.atkの値を代入
 var a_luk = a.luk; //a_luk という変数を用意し、a.lukの値を代入

 var b_def = b.def; //b_def という変数を用意し、b.defの値を代入
 var b_luk = b.luk; //b_luk という変数を用意し、b.lukの値を代入

 var damage = 0; //damege という変数を用意しておく。中身は0
 var damage2 = 0; //damege2 という変数を用意しておく。中身は0


では続きを行きましょう。

攻撃と防御の計算式

damage = (a_atk - b_def × perforate) × level;

もう何を書いてあるかそろそろわかりますかね?

damage ←さっき作った。中身は0の変数
a_atk ←さっき作った。中身はa.atk つまり主体の攻撃力
a_def ←さっき作った。中身はb.def つまり対象の防御力

perforate ←スキル計算式から受け取った3つめの値。受け取った時点で名前を付けた。中身は 0.5

level ←スキル計算式から受け取った4つめの値。受け取った時点で名前を付けた。中身は 1


damage = (a_atk - b_def × perforate) × level;

damage =(主体攻撃力 - 対象防御力 × 貫通率)× スキル威力
ってことが書いてあるってわけですね。

一番最初にかいた、攻撃と防御からなる基礎計算式はこれで終わりってことです。

運を扱う計算式

では、運を扱う二つ目の計算結果を出しましょう。


var luk1 = Math.floor( Math.random() × (a_luk + 1));

新しく luk1 という変数を作り、その中には
0~主体の運までの乱数値を代入する。

var luk2 = Math.floor( Math.random() × (b_luk + 1));

新しく luk2 という変数を作り、その中には
0~対象の運までの乱数値を代入する。


damage2 = (luk1 - luk2) × level;

damage2 =(0~主体の運までの乱数値 - 0~対象の運までの乱数値) × スキル威力
ってことが書いてあります。

これで二つ目の計算結果も出ましたね。

比較して値を返す

もう終わりですよ!

return Math.max(damage, damage2);

値を返しなさい。大きい方です。(damage,damage2)
と書いてあります。ここまでで、damage には物理部分の算出。
damage2には運部分の算出が出来ているので、それで大きかった方を返します。


}
↑これは呼び出した関数はここまでですよというやつ。これを書いたら、
やっとスキル計算式に戻ります。


これで全部終わりです。最後におさらい。


function luk_atk(a, b, perforate, level){ //スキル計算式から受け取った4つの値を持つ
 var a_atk = a.atk; //a_atk という変数を用意し、a.atkの値を代入
 var a_luk = a.luk; //a_luk という変数を用意し、a.lukの値を代入

 var b_def = b.def; //b_def という変数を用意し、b.defの値を代入
 var b_luk = b.luk; //b_luk という変数を用意し、b.lukの値を代入

 var damage = 0; //damege という変数を用意しておく。中身は0
 var damage2 = 0; //damege2 という変数を用意しておく。中身は0

damage = (a_atk - b_def * perforate) × level; //物理部分の計算式

var luk1 = Math.floor( Math.random() × (a_luk + 1));//新しく luk1 という変数を作り、その中には0~主体の運までの乱数値を代入する。

var luk2 = Math.floor( Math.random() × (b_luk + 1));//新しく luk2 という変数を作り、その中には0~対象の運までの乱数値を代入する。

damage2 = (luk1 - luk2) * level;////運部分の計算式

return Math.max(damage, damage2); //damage, damage2の大きい値を返す

} // luk_atk という関数はここまで。




最後にそのままそっくり置いておきます

https://drive.google.com/file/d/1_4O3YNXNEcHPgvZx-XMlXucj95pg8uyx/view?usp=sharing

サンプルとして説明していたのを加えて、ぱぱっと7つだけ式が入っています。

貫通率が決められる物理攻撃
貫通率が決められる魔法攻撃

運・物理参照攻撃(サンプルと一緒)
運・魔力参照攻撃
運・敏捷参照攻撃

攻撃・魔力参照攻撃(複合ではなく、それぞれ参照しダメージの高い方を取る)
攻撃・敏捷参照攻撃(複合ではなく、それぞれ参照しダメージの高い方を取る)


何かのお役に立てば幸いです。


ちょこっと追記

複合ダメージはどうやりたいかで色々変わってきますが、
記述的にはそう難しいものでもありません。

atk_mat2(a, b, 0.5, 10 , 5)

スキルの方はこんな感じで設定。
貫通率50% 物理部分の威力が10 魔法部分の威力が5です。
仮に物理部分と魔法部分の貫通率も変えたいならさらに値を増やす必要がありますね。


function atk_mat2(a, b, perforate, atk_level, mat_level){

 var a_atk = a.atk;
 var a_mat = a.mat;

 var b_def = b.def;
 var b_mdf = b.mdf;

 var damage = 0;
 var damage2 = 0;

 damage = ((a_atk  -  b_def * perforate) * atk_level) + ((a_mat  -  b_mdf * perforate) * mat_level);

return damage;
} 

レベルをatk_levelとmat_levelという2つパラメータに変更。
物理によるダメージと魔法によるダメージをそれぞれ算出し、最後に加算します。

物理威力が5
魔法威力が2

とか色々変える事が出来ます。
一応、これもテンプレに入れておきます。

ニル 2020/06/21 19:19

Mystic Star その3

砂川赳さん作 MysticStar

ダウンロード・砂川さんのサイトはこちらから
http://newrpg.seesaa.net/category/13166216-1.html


この下はネタバレしていきますよ!
これはネタバレ防止用の画像……


続きです

現在プレイ時間は10時間程です。ちょっと途中放置とかあったかも。
全員21lv付近。

戦闘回数 221 → 392
勝利回数 192 → 325
全滅回数 6   → 11
逃走回数 22  → 56


水の四天王で結構苦戦しました。土IIと光IIを持っていなかったのですが、
5回程負けたので引き返して買いに行きました。

そうしたらアースシールドめっちゃ有能でした。もっと早く買うべきだった。
装備はこんな感じ。別に何か工夫してるわけでもないですね。

地図を手に入れて、船を手に入れて、最初にやったのは水の四天王でした。
lv16で付近の村にいたのですが、
直前の船でも苦戦したので18lvまでレベリングしてました。
そこからはハルトをバーサーカー化させたこともあって比較的なんとかなり、
水の四天王を倒した時点でこの記事を書いています。


スキルはこんな感じ。
前回の方針を引き継いでいますね。

魔珠は結構変わりましたね。こんな感じです。



ハルト

雷魔法I 水魔法I 攻撃I 反撃I TP回復I

注目 暴走 会心II HPII 反撃II 攻撃II 感受II

注目により狙われやすくなり、
物理攻撃を受けると80%で反撃するという構成。
反撃威力を上げる為に常時暴走であり、
被ダメージが増えるので、感受IIによりリカバリーをしやすくしています。
HPII と 攻撃II は役割の補強。改心率も合計23%でそこそこ見れます。

万能ポジから一転。完全に狂戦士。メインアタッカー。

イナーシャ→クリューネ

闇魔法II 炎魔法II 氷魔法I 雷魔法I MP回復I

水魔法II 炎魔法II 雷魔法II 魔力II MP回復I 反撃I

ハルトが完全にアタッカーとして台頭し、毒による安定火力を持つメアと比較し、
イナーシャが微妙な立場に。
水四天王という事で耐性の差もありイナーシャからクリューネになりました。

いわゆる魔人切りである激流衝が中々便利であり、
赤奥義で全体回復である恵みの雨がいざと言うときに心強く、
このままスタメン入りするかもしれません。

メア

氷魔法II 水魔法II 闇魔法I 土魔法I HPI

氷魔法II 水魔法II 光魔法II 土魔法II 攪乱II 持続II

毒が相変わらず強いので、毒成功率と持続力を上げています。
持続IIを活かせるように防御・魔防上昇のバフと、
暗闇と毒付与を扱えるサポ―トキャラになっています。
後は暇になりやすいので状態異常解除も担当。

最初に毒にさせれば仕事の半分は終わり。

サイアス

光魔法I 闇魔法I 風魔法II 慈愛I MP回復II MP回復I

光魔法I 闇魔法I 風魔法II 慈愛I MP回復II MP回復I 無し

安定感ありすぎて珠増やしてたのに付ける事すら忘れてた。

全員に 感受II を装備させれば、
ちょっと頼りない全体回復魔法であるメローブリーズの使い勝手が
大幅に上がりそうだと今更気づいたので、付けてみようかと思っています。

ニル 2020/06/20 17:55

Mystic Star その2

砂川赳さん作 MysticStar

ダウンロード・砂川さんのサイトはこちらから
http://newrpg.seesaa.net/category/13166216-1.html

続きです

現在プレイ時間は5時間程です。全員13lv位。

戦闘回数 221
勝利回数 192
全滅回数 6
逃走回数 22


ハルト

雷魔法I 水魔法I 攻撃I 反撃I TP回復I

TP回復 I・IIと攻撃スキル。
乱真空を連打してましたが、段々と火力不足が目立つように。
飛燕斬空を覚えたら結構変わったので、今は火力・耐久・回復の万能ポジ。

イナーシャ

闇魔法II 炎魔法II 氷魔法I 雷魔法I MP回復I

MP回復IIIまでと、スプレッドアロー。期待してましたが、実は命中難でした。
とはいえ威力は高めでMP回復の合間に使えるのでまぁまぁ。
全体技を連打するPT内のメインアタッカー。

メア

氷魔法II 水魔法II 闇魔法I 土魔法I HPI

毒がめっちゃ強いのは気づいていてイナーシャに連打させていたのですが、
まさかの縦範囲の毒付与攻撃持ち。即主力でした。もはやこれが採用理由。
TPIIまで取って後は適当。氷の全体魔法が一応使えるのも良し。サブアタッカー。

サイアス

光魔法I 闇魔法I 風魔法II 慈愛I MP回復II MP回復I

MP回復IIIまでを取得し、後は適当。申し分ない回復役。
心情的にはロビンを使ってあげたかったが、性能の差は超えられない。
シンセンスが消費5で100以上回復するのが嬉しい。



今のところ出会うボスがどれも手ごたえがあります。
全滅回数の表記が増えるのはアレですが、死んだら街まで戻るので、
それで装備を整えてボスを突破とかも良くある話。

ニル 2020/06/20 11:29

Mystic Star その1

砂川赳さん作 MysticStar

ダウンロード・砂川さんのサイトはこちらから
http://newrpg.seesaa.net/category/13166216-1.html

Twitterで話題になっていたのでプレイしてみました

ちょっとやってみたら面白くてですね。
現在プレイ時間は2時間程です。
ロビンだけ7、後は8lvです。

戦闘回数 102
勝利回数 92
全滅回数 3
逃走回数 7

ハルトはTP回復 I・IIをベースにTP技を連打できるように。
雷魔法I 闇魔法I 水魔法I 攻撃I TP回復I

ロビンはMP回復I・IIをベースに回復技を使いやすくするように。
風魔法I 闇魔法I 光魔法I 慈愛I MP回復I

イナーシャは
闇魔法I 炎魔法I 氷魔法I 土魔法I MP回復I



仲間の数は何人になるんですかねー?
予想では属性の数と同じ8人なんですけど。

(多分)明確な回復役が入っていないので現在は脚の速いロビンを回復役にしています。

……今日は割と連投することになるかもしれない。

追記1

二度目のスケさんめっちゃ強い。
もう10回くらい負けてる。
IIレベル魔法覚えてないから不味いんだろうか。

……と思ったら勝てました。

« 1 2

月別アーカイブ

記事のタグから探す

限定特典から探す

記事を検索