あばれる状態とは
技を使うと、しばらくの間その技のみしか使用できなくなる技があります。その状態を「あばれる状態」と言います。
あばれる状態(ポケモンwiki)
あばれるの効果
2~3ターンの間攻撃し続け、交換したり、他の指示を出すことが出来ない。
攻撃が終わるとこんらん状態になる。
初代では名称どおり「あばれる」という技が存在しており、他にも「はなびらのまい」が該当します。第2世代ではドラゴンタイプの「げきりん」が登場して、現在ではこの3つがあばれる状態を発生させる技になります。
こちらも状態変化として管理をするので、まずは状態変化クラスを作成しましょう。
あばれる:状態変化(/Classes/StateChange/ScThrash.php)
<?php
$root_path = __DIR__.'/../..';
require_once($root_path.'/Classes/StateChange.php');
// あばれる
class ScThrash extends StateChange
{
/**
* 正式名称
* @var string
*/
protected $name = 'あばれる';
}
あばれる状態になっても、特別なメッセージはありません。なので、現状は名称のみの空クラスとして作成します。
状態変化用メソッドの修正
あばれる状態にも残ターン数とどの技であばれる状態になっているかが判別できなければなりません。なので、状態変化にはターン数とパラメーター(技クラス)を格納します。
この2つをピンポイントで取得するためのメソッドが未実装だったため、このタイミングで作成して、他の処理でも簡潔に記述できるようにしておきましょう。
ポケモンクラス用Getトレイト(/App/Traits/Class/Pokemon/ClassPokemonGetTrait.php)
/**
* 現在の状態変化を取得する
* @param class:string
* @param turn:boolean
* @param param:boolean
* @return mixed
*/
public function getSc(string $class='', bool $turn=false, bool $param=false)
{
if(empty($class)){
// 全状態異常を取得
return $this->sc;
}else{
if($this->checkSc($class)){
// 残ターン数を取得
if($turn){
return $this->sc[$class]['turn'];
}
// パラメーターを取得
if($param){
return $this->sc[$class]['param'];
}
}
}
}
第2引数でtrueを指定すればターン数、第3引数でtrueを指定すればパラメーターを取得します。手前から判別していくので、パラメーター(技クラス)を取得する際は第2引数をfalseに設定する必要があります。
オートバトル
次にオートバトルの設定をしましょう。チャージ技と同様に使用すれば終わるまで別の行動指示が出せなくなります。なので、コントローラーでの分岐処理後にチェックを行い、前処理が終わるまで選択ができないようループをさせます。
バトルコントローラー(/App/Controllers/Battle/BattleController.php)
/**
* 次のターンへの判定処理
*
* @return boolean
*/
private function nextTurn()
{
// ひんしポケモンがでた場合の処理
if($this->fainting['enemy'] || $this->fainting['friend']){
$this->judgment();
return false;
}
// チャージ中、反動有り、あばれる状態なら再度アクション実行
if(
$this->chargeNow() ||
$this->pokemon->checkSc('ScRecoil') ||
$this->pokemon->checkSc('ScThrash')
){
$this->branch();
return true;
}else{
$this->setMessage('行動を選択してください');
return false;
}
}
敵ポケモンの技選択においても同様です。技選択のAIでもあばれる状態をチェックする処理を追加しましょう。
相手ポケモンの技選択AI(/App/Traits/Service/Battle/ServiceBattleEnemyAiTrait.php)
<?php
// 敵ポケモンの行動AI
trait ServiceBattleEnemyAiTrait
{
/**
* 技の選択
*
* @return string
*/
protected function aiSelectMove()
{
// チャージ中ならチャージ技を返却
if($this->enemy->checkSc('ScCharge')){
return $this->enemy
->getChargeMove();
}
// あばれる中ならあばれる技を返却
if($this->enemy->checkSc('ScThrash')){
return $this->enemy
->getSc('ScThrash', false, true);
}
// 技の一覧を配列形式で取得
$move = $this->enemy
->getMove(null, 'array');
// ランダムで1つ返却
return $move[array_rand($move)];
}
}
これであばれる状態終了までの技固定は完了です。
技PPの減少対策
PPの減少についても、チャージ技と同様に判定をいれましょう。でなければ一度あばれる(はなびらのまい)を使用すれば、PPが経過ターン数分減ってしまうことになります。
バトルサービスチェック用トレイト(/App/Traits/Service/Battle/ServiceBattleCheckTrait.php)
<?php
// チェック関係格納トレイト
trait ServiceBattleCheckTrait
{
/**
* 技の使用可不可判定
*
* @param object $move Move
* @param object $pokemon Pokemon
* @return boolean (true: 使用可, false:使用不可(わるあがき))
*/
protected function checkEnabledMove(object $move, object $pokemon)
{
$move_class = get_class($move);
if($move_class === 'MoveStruggle'){
// わるあがき
return false;
}
// ポケモンの技一覧
$move_list = $pokemon->getMove(null, 'array');
// 選択された技の添番を取得
$num = array_search(
$move_class,
array_column($move_list, 'class'),
);
// PP残数の確認
if($move_list[$num]['remaining'] > 0){
// チャージターンかつあばれる状態でなければPP減少
if(!$this->checkChargeTurn($pokemon, $move) && !$pokemon->checkSc('ScThrash')){
// 残PPをマイナス1
$pokemon->calRemainingPp('sub', 1, $num);
}
return true;
}else{
// 使用不可
return false;
}
}
これであばれる状態にする技の制御処理の実装が完了です。
あばれる
では、技クラスを作成していきましょう。あばれる状態になる技の代表として「あばれる」を実装します。
あばれる:技(/Classes/Move/MoveThrash.php)
<?php
$root_path = __DIR__.'/../..';
require_once($root_path.'/Classes/Move.php');
// あばれる
class MoveThrash extends Move
{
/**
* 正式名称
* @var string
*/
protected $name = 'あばれる';
/**
* 説明文
* @var string
*/
protected $description = '2〜3ターンの間あばれる状態になり、その間攻撃し続ける。攻撃終了後、自分がこんらん状態になる。';
/**
* タイプ
* @var string
*/
protected $type = 'TypeNormal';
/**
* 分類
* @var string(physical:物理|special:特殊|status:変化)
*/
protected $species = 'physical';
/**
* 威力
* @var integer
*/
protected $power = 120;
/**
* 命中率
* @var integer
*/
protected $accuracy = 100;
/**
* 使用回数
* @var integer
*/
protected $pp = 10;
/**
* 追加効果
*
* @param array $args
* @return void
*/
public function effects(...$args)
{
/**
* @param Pokemon $atk 攻撃ポケモン
* @param Pokemon $def 防御ポケモン
*/
list($atk, $def) = $args;
// 現在あばれる状態でなければ「あばれる状態」をセット
if(!$atk->checkSc('ScThrash')){
// あばれる状態をセット
$atk->setSc('ScThrash', random_int(2, 3), get_class());
}
// ターンカウントを進める
$atk->goScTurn('ScThrash');
// あばれる状態が解除されており、こんらん状態でなければ、こんらん状態にする
if(!$atk->checkSc('ScThrash') && !$atk->checkSc('ScConfusion')){
$msg = $atk->setSc('ScConfusion', random_int(1, 4));
$this->setMessage($msg);
}
}
}
※優先度は親クラスで初期値0としました
effectsにほぼ前処理を書き込みましたが、最終シリーズまで合わせて3つしか該当する技がないため、わざわざフラグをもたせたり、特別処理は不要と判断しました。
こんらん状態のセット
それではeffectsメソッド内を見ていきましょう。まずはあばれる状態をセットするための分岐からです。
// 現在あばれる状態でなければ「あばれる状態」をセット
if(!$atk->checkSc('ScThrash')){
// あばれる状態をセット
$atk->setSc('ScThrash', random_int(2, 3), get_class());
}
ただセットするだけでは、あばれる状態での技使用時に更に上書きされてしまい、永久に暴れる状態から抜け出せなくなってしまいます。そうならないためにも、現在があばれる状態かどうかを確認してからセットするようにしています。
次に、ターンの進行を行います。
// ターンカウントを進める
$atk->goScTurn('ScThrash');
こちらは状態変化チェック時でも構いませんが、流れとしてはあばれる状態では無くなった時点でこんらんをセットするのが正しいため、effects内でターン進行と解除処理を行います。
次に、最終ターンのこんらん処理についてです。
// あばれる状態が解除されており、こんらん状態でなければ、こんらん状態にする
if(!$atk->checkSc('ScThrash') && !$atk->checkSc('ScConfusion')){
$msg = $atk->setSc('ScConfusion', random_int(1, 4));
$this->setMessage($msg);
}
ターンカウント進行後に、あばれる状態でなければ最終ターンということになります。また、場合によってはこんらん状態でターンを終えることもあるため、その際にはこんらんのセットは不要です。
それでは実際に使ってみましょう。
技選択後、あばれるが終わるまで(混乱するまで)オートで戦闘が進行しました。これであばれる状態・技の実装が完了です。
※あばれるを威力120のままでテストすると、終了までに相手のHPを削りきってしまうため、威力20にして検証しています
まとめ
いかがだったでしょうか。
今回のPHPポケモンは「あばれる状態・技」の実装方法をご紹介しました。
あばれる関係は初代ではそこまで注目が当たらなかった技ですが、第2世代でげきりんが追加され、威力も120と上昇したこともあり、ポケモンのメインウェポンとして採用されることが多くなった技種類の1つです。
こういった歴史的背景も考えながら実装していくと、ゲームバランスの作り込みが重要だということがわかります。
現在プログラミング学習に取り組んでいる方や、興味がある人は、ぜひ参考にしてみてくださいね。