262 lines
9.7 KiB
Ruby
262 lines
9.7 KiB
Ruby
#==============================================================================
|
|
# ■ Game_Action
|
|
#------------------------------------------------------------------------------
|
|
# 戦闘行動を扱うクラスです。このクラスは Game_Battler クラスの内部で使用され
|
|
# ます。
|
|
#==============================================================================
|
|
|
|
class Game_Action
|
|
#--------------------------------------------------------------------------
|
|
# ● 公開インスタンス変数
|
|
#--------------------------------------------------------------------------
|
|
attr_reader :subject # 行動主体
|
|
attr_reader :forcing # 戦闘行動の強制フラグ
|
|
attr_reader :item # スキル / アイテム
|
|
attr_accessor :target_index # 対象インデックス
|
|
attr_reader :value # 自動戦闘用 評価値
|
|
#--------------------------------------------------------------------------
|
|
# ● オブジェクト初期化
|
|
#--------------------------------------------------------------------------
|
|
def initialize(subject, forcing = false)
|
|
@subject = subject
|
|
@forcing = forcing
|
|
clear
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● クリア
|
|
#--------------------------------------------------------------------------
|
|
def clear
|
|
@item = Game_BaseItem.new
|
|
@target_index = -1
|
|
@value = 0
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 味方ユニットを取得
|
|
#--------------------------------------------------------------------------
|
|
def friends_unit
|
|
subject.friends_unit
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 敵ユニットを取得
|
|
#--------------------------------------------------------------------------
|
|
def opponents_unit
|
|
subject.opponents_unit
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 敵キャラの戦闘行動を設定
|
|
# action : RPG::Enemy::Action
|
|
#--------------------------------------------------------------------------
|
|
def set_enemy_action(action)
|
|
if action
|
|
set_skill(action.skill_id)
|
|
else
|
|
clear
|
|
end
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 通常攻撃を設定
|
|
#--------------------------------------------------------------------------
|
|
def set_attack
|
|
set_skill(subject.attack_skill_id)
|
|
self
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 防御を設定
|
|
#--------------------------------------------------------------------------
|
|
def set_guard
|
|
set_skill(subject.guard_skill_id)
|
|
self
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● スキルを設定
|
|
#--------------------------------------------------------------------------
|
|
def set_skill(skill_id)
|
|
@item.object = $data_skills[skill_id]
|
|
self
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● アイテムを設定
|
|
#--------------------------------------------------------------------------
|
|
def set_item(item_id)
|
|
@item.object = $data_items[item_id]
|
|
self
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● アイテムオブジェクト取得
|
|
#--------------------------------------------------------------------------
|
|
def item
|
|
@item.object
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 通常攻撃判定
|
|
#--------------------------------------------------------------------------
|
|
def attack?
|
|
item == $data_skills[subject.attack_skill_id]
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● ランダムターゲット
|
|
#--------------------------------------------------------------------------
|
|
def decide_random_target
|
|
if item.for_dead_friend?
|
|
target = friends_unit.random_dead_target
|
|
elsif item.for_friend?
|
|
target = friends_unit.random_target
|
|
else
|
|
target = opponents_unit.random_target
|
|
end
|
|
if target
|
|
@target_index = target.index
|
|
else
|
|
clear
|
|
end
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 混乱行動を設定
|
|
#--------------------------------------------------------------------------
|
|
def set_confusion
|
|
set_attack
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 行動準備
|
|
#--------------------------------------------------------------------------
|
|
def prepare
|
|
set_confusion if subject.confusion? && !forcing
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 行動が有効か否かの判定
|
|
# イベントコマンドによる [戦闘行動の強制] ではないとき、ステートの制限
|
|
# やアイテム切れなどで予定の行動ができなければ false を返す。
|
|
#--------------------------------------------------------------------------
|
|
def valid?
|
|
(forcing && item) || subject.usable?(item)
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 行動速度の計算
|
|
#--------------------------------------------------------------------------
|
|
def speed
|
|
speed = subject.agi + rand(5 + subject.agi / 4)
|
|
speed += item.speed if item
|
|
speed += subject.atk_speed if attack?
|
|
speed
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● ターゲットの配列作成
|
|
#--------------------------------------------------------------------------
|
|
def make_targets
|
|
if !forcing && subject.confusion?
|
|
[confusion_target]
|
|
elsif item.for_opponent?
|
|
targets_for_opponents
|
|
elsif item.for_friend?
|
|
targets_for_friends
|
|
else
|
|
[]
|
|
end
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 混乱時のターゲット
|
|
#--------------------------------------------------------------------------
|
|
def confusion_target
|
|
case subject.confusion_level
|
|
when 1
|
|
opponents_unit.random_target
|
|
when 2
|
|
if rand(2) == 0
|
|
opponents_unit.random_target
|
|
else
|
|
friends_unit.random_target
|
|
end
|
|
else
|
|
friends_unit.random_target
|
|
end
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 敵に対するターゲット
|
|
#--------------------------------------------------------------------------
|
|
def targets_for_opponents
|
|
if item.for_random?
|
|
Array.new(item.number_of_targets) { opponents_unit.random_target }
|
|
elsif item.for_one?
|
|
num = 1 + (attack? ? subject.atk_times_add.to_i : 0)
|
|
if @target_index < 0
|
|
[opponents_unit.random_target] * num
|
|
else
|
|
[opponents_unit.smooth_target(@target_index)] * num
|
|
end
|
|
else
|
|
opponents_unit.alive_members
|
|
end
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 味方に対するターゲット
|
|
#--------------------------------------------------------------------------
|
|
def targets_for_friends
|
|
if item.for_user?
|
|
[subject]
|
|
elsif item.for_dead_friend?
|
|
if item.for_one?
|
|
[friends_unit.smooth_dead_target(@target_index)]
|
|
else
|
|
friends_unit.dead_members
|
|
end
|
|
elsif item.for_friend?
|
|
if item.for_one?
|
|
[friends_unit.smooth_target(@target_index)]
|
|
else
|
|
friends_unit.alive_members
|
|
end
|
|
end
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● 行動の価値評価(自動戦闘用)
|
|
# @value および @target_index を自動的に設定する。
|
|
#--------------------------------------------------------------------------
|
|
def evaluate
|
|
@value = 0
|
|
evaluate_item if valid?
|
|
#@value += rand if @value > 0
|
|
@value += rand
|
|
self
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● スキル/アイテムの評価
|
|
#--------------------------------------------------------------------------
|
|
def evaluate_item
|
|
item_target_candidates.each do |target|
|
|
value = evaluate_item_with_target(target)
|
|
if item.for_all?
|
|
@value += value
|
|
elsif value > @value
|
|
@value = value
|
|
@target_index = target.index
|
|
end
|
|
end
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● スキル/アイテムの使用対象候補を取得
|
|
#--------------------------------------------------------------------------
|
|
def item_target_candidates
|
|
if item.for_opponent?
|
|
opponents_unit.alive_members
|
|
elsif item.for_user?
|
|
[subject]
|
|
elsif item.for_dead_friend?
|
|
friends_unit.dead_members
|
|
else
|
|
friends_unit.alive_members
|
|
end
|
|
end
|
|
#--------------------------------------------------------------------------
|
|
# ● スキル/アイテムの評価(ターゲット指定)
|
|
#--------------------------------------------------------------------------
|
|
def evaluate_item_with_target(target)
|
|
target.result.clear
|
|
target.make_damage_value(subject, item)
|
|
if item.for_opponent?
|
|
return target.result.hp_damage.to_f / [target.hp, 1].max
|
|
else
|
|
recovery = [-target.result.hp_damage, target.mhp - target.hp].min
|
|
return recovery.to_f / target.mhp
|
|
end
|
|
end
|
|
end
|