a-story-about-stolen-lover/Scripts/Game_Action.rb
2024-02-03 15:51:02 -06:00

261 lines
9.4 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
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