Post by Elkat on Jan 9, 2017 4:50:11 GMT
The following script is pointed to by the bug that causes the game to crash whenever a paralyzed/frozen/sleeping enemy tries to counter attack.
#==============================================================================
# ■ Game_SrpgEvent
#------------------------------------------------------------------------------
# イベントを扱うクラスです。条件判定によるイベントページ切り替えや、並列処理
# イベント実行などの機能を持っており、Game_SrpgMap クラスの内部で使用されます。
#==============================================================================
class Game_SrpgEvent < Game_SrpgCharacter
#--------------------------------------------------------------------------
# ● 公開インスタンス変数
#--------------------------------------------------------------------------
attr_reader :trigger # トリガー
attr_reader :list # 実行内容
attr_reader :starting # 起動中フラグ
#--------------------------------------------------------------------------
# ● オブジェクト初期化
# event : RPG::Event
#--------------------------------------------------------------------------
def initialize(map_id, event)
super()
@map_id = map_id
@event = event
@id = @event.id
moveto(@event.x, @event.y)
refresh
end
#--------------------------------------------------------------------------
# ● 公開メンバ変数の初期化
#--------------------------------------------------------------------------
def init_public_members
super
@trigger = 0
@list = nil
@starting = false
end
#--------------------------------------------------------------------------
# ● 非公開メンバ変数の初期化
#--------------------------------------------------------------------------
def init_private_members
super
@move_type = 0 # 移動タイプ
@erased = false # 一時消去フラグ
@page = nil # イベントページ
@moved = false # 移動実行済みフラグ
@acted = false # 行動実行済みフラグ
@last_pos = [] # 移動前の座標
end
#--------------------------------------------------------------------------
# ● 画面 Y 座標の取得
#--------------------------------------------------------------------------
def screen_y
result = super
if battler && battler.float? && battler.use_float_effect?
#~ result -= Math.sin(Math::PI * (Graphics.frame_count % 90) / 45) * 6 + 8
end
result
end
#--------------------------------------------------------------------------
# ● イベントがゲートかどうかを返す
#--------------------------------------------------------------------------
def gate?
/<GATE>/i =~ @event.name ? true : false
end
#--------------------------------------------------------------------------
# ● バトラーイベントかどうかを返す
#--------------------------------------------------------------------------
def battler?
@battler != nil
end
#--------------------------------------------------------------------------
# ● アクターイベントかどうかを返す
#--------------------------------------------------------------------------
def actor?
false
end
#--------------------------------------------------------------------------
# ● エネミーイベントかどうかを返す
#--------------------------------------------------------------------------
def enemy?
battler? && !npc?
end
#--------------------------------------------------------------------------
# ● NPCイベントかどうかを返す
#--------------------------------------------------------------------------
def npc?
@npc
end
#--------------------------------------------------------------------------
# ● 撃破対象イベントかどうかを返す
#--------------------------------------------------------------------------
def boss?
@boss
end
#--------------------------------------------------------------------------
# ● 非撃破対象イベントかどうかを返す
#--------------------------------------------------------------------------
def rule_out?
@rule_out
end
#--------------------------------------------------------------------------
# ● 護衛対象イベントかどうかを返す
#--------------------------------------------------------------------------
def princess?
@princess
end
#--------------------------------------------------------------------------
# ● オブジェクトイベントかどうかを返す
#--------------------------------------------------------------------------
def object?
battler? && battler.object?
end
#--------------------------------------------------------------------------
# ● バトラーを返す
#--------------------------------------------------------------------------
def battler
@battler
end
#--------------------------------------------------------------------------
# ● 味方かどうかを返す
#--------------------------------------------------------------------------
def friend?(target)
return true if self == target
return false if battler.confusion_level == 2
if npc?
(target.actor? || target.npc?) ^ (battler.confusion_level == 3)
else
target.enemy? ^ (battler.confusion_level == 3)
end
end
#--------------------------------------------------------------------------
# ● 敵対するイベント配列を返す
#--------------------------------------------------------------------------
def opponent_events
$game_srpgmap.all_battler_events.select {|event| !friend?(event) }
end
#--------------------------------------------------------------------------
# ● 仲間イベント配列を返す
#--------------------------------------------------------------------------
def friend_events
$game_srpgmap.all_battler_events.select {|event| friend?(event) }
end
#--------------------------------------------------------------------------
# ● 指定した座標との距離計算
#--------------------------------------------------------------------------
def distance_pos_from(x, y)
(@x - x).abs + (@y - y).abs
end
#--------------------------------------------------------------------------
# ● 指定したイベントとの距離計算
#--------------------------------------------------------------------------
def distance_event_from(event)
distance_pos_from(event.x, event.y)
end
#--------------------------------------------------------------------------
# ● 索敵範囲内にいる敵対イベント配列を返す
#--------------------------------------------------------------------------
def near_opponent_events
opponent_events.select do |event|
distance_event_from(event) <= battler.search
end
end
#--------------------------------------------------------------------------
# ● 索敵範囲内で一番近い敵対イベントを返す
#--------------------------------------------------------------------------
def nearest_opponent_event
targets = near_opponent_events
return nil if targets.empty?
targets.sort! {|a, b| distance_event_from(a) - distance_event_from(b) }
targets[0]
end
#--------------------------------------------------------------------------
# ● 索敵範囲内にいる仲間イベント配列を返す
#--------------------------------------------------------------------------
def near_friend_events
friend_events.select do |event|
distance_event_from(event) <= battler.search
end
end
#--------------------------------------------------------------------------
# ● 索敵範囲内で一番近い仲間イベントを返す
#--------------------------------------------------------------------------
def nearest_friend_event
targets = near_friend_events
return nil if targets.empty?
targets.sort! {|a, b| distance_event_from(a) - distance_event_from(b) }
targets[0]
end
#--------------------------------------------------------------------------
# ● 移動済みかどうかを返す
#--------------------------------------------------------------------------
def moved?
@moved
end
#--------------------------------------------------------------------------
# ● 行動済みかどうかを返す
#--------------------------------------------------------------------------
def acted?
@acted
end
#--------------------------------------------------------------------------
# ● 移動をキャンセルできるかどうかを返す
#--------------------------------------------------------------------------
def can_move_cancel?
return false unless battler.movable? # 行動不能ならキャンセルもできない
return false if acted? # 行動済みならキャンセルできない
return true if moved? && !$game_srpgmap.battler_event_xy(@last_pos[0], @last_pos[1])
$game_srpgmap.gate_xy?(@x, @y) # ゲート上なら出撃キャンセル可
end
#--------------------------------------------------------------------------
# ● ロック(実行中のイベントが立ち止まる処理)
#--------------------------------------------------------------------------
def lock
unless @locked
@prelock_direction = @direction
turn_toward_player
@locked = true
end
end
#--------------------------------------------------------------------------
# ● ロック解除
#--------------------------------------------------------------------------
def unlock
if @locked
@locked = false
set_direction(@prelock_direction)
end
end
#--------------------------------------------------------------------------
# ● 指定位置に移動
#--------------------------------------------------------------------------
def moveto(x, y)
super
update_tile_state
end
#--------------------------------------------------------------------------
# ● 停止時の更新
#--------------------------------------------------------------------------
def update_stop
super
update_self_movement unless @move_route_forcing
end
#--------------------------------------------------------------------------
# ● 自律移動の更新
#--------------------------------------------------------------------------
def update_self_movement
if near_the_screen? && @stop_count > stop_count_threshold
case @move_type
when 1; move_type_random
when 2; move_type_toward_player
when 3; move_type_custom
end
end
end
#--------------------------------------------------------------------------
# ● 画面の可視領域付近にいるか判定
# dx : 画面中央から左右何マス以内を判定するか
# dy : 画面中央から上下何マス以内を判定するか
#--------------------------------------------------------------------------
def near_the_screen?(dx = 12, dy = 8)
ax = $game_srpgmap.adjust_x(@real_x) - Graphics.width / 2 / 32
ay = $game_srpgmap.adjust_y(@real_y) - Graphics.height / 2 / 32
ax >= -dx && ax <= dx && ay >= -dy && ay <= dy
end
#--------------------------------------------------------------------------
# ● 自律移動を開始する停止カウントの閾値を計算
#--------------------------------------------------------------------------
def stop_count_threshold
30 * (5 - @move_frequency)
end
#--------------------------------------------------------------------------
# ● 移動タイプ : ランダム
#--------------------------------------------------------------------------
def move_type_random
case rand(6)
when 0..1; move_random
when 2..4; move_forward
when 5; @stop_count = 0
end
end
#--------------------------------------------------------------------------
# ● 移動タイプ : 近づく
#--------------------------------------------------------------------------
def move_type_toward_player
if near_the_player?
case rand(6)
when 0..3; move_toward_player
when 4; move_random
when 5; move_forward
end
else
move_random
end
end
#--------------------------------------------------------------------------
# ● プレイヤーの近くにいるか判定
#--------------------------------------------------------------------------
def near_the_player?
sx = distance_x_from($game_player.x).abs
sy = distance_y_from($game_player.y).abs
sx + sy < 20
end
#--------------------------------------------------------------------------
# ● 移動タイプ : カスタム
#--------------------------------------------------------------------------
def move_type_custom
update_routine_move
end
#--------------------------------------------------------------------------
# ● 起動中フラグのクリア
#--------------------------------------------------------------------------
def clear_starting_flag
@starting = false
end
#--------------------------------------------------------------------------
# ● 実行内容が空か否かを判定
#--------------------------------------------------------------------------
def empty?
!@list || @list.size <= 1
end
#--------------------------------------------------------------------------
# ● 指定されたトリガーのいずれかか否かを判定
# triggers : トリガーの配列
#--------------------------------------------------------------------------
def trigger_in?(triggers)
triggers.include?(@trigger)
end
#--------------------------------------------------------------------------
# ● イベント起動
#--------------------------------------------------------------------------
def start
return if empty?
@starting = true
lock if trigger_in?([0,1,2])
end
#--------------------------------------------------------------------------
# ● 一時消去
#--------------------------------------------------------------------------
def erase
@erased = true
refresh
end
#--------------------------------------------------------------------------
# ● リフレッシュ
#--------------------------------------------------------------------------
def refresh
new_page = @erased ? nil : find_proper_page
setup_page(new_page) if !new_page || new_page != @page
end
#--------------------------------------------------------------------------
# ● 条件に合うイベントページを見つける
#--------------------------------------------------------------------------
def find_proper_page
@event.pages.reverse.find {|page| conditions_met?(page) }
end
#--------------------------------------------------------------------------
# ● イベントページの条件合致判定
#--------------------------------------------------------------------------
def conditions_met?(page)
c = page.condition
if c.switch1_valid
return false unless $game_switches[c.switch1_id]
end
if c.switch2_valid
return false unless $game_switches[c.switch2_id]
end
if c.variable_valid
return false if $game_variables[c.variable_id] < c.variable_value
end
if c.self_switch_valid
key = [@map_id, @event.id, c.self_switch_ch]
return false if $game_self_switches[key] != true
end
if c.item_valid
item = $data_items[c.item_id]
return false unless $game_party.has_item?(item)
end
if c.actor_valid
actor = $game_actors[c.actor_id]
return false unless $game_party.members.include?(actor)
end
return true
end
#--------------------------------------------------------------------------
# ● イベントページのセットアップ
#--------------------------------------------------------------------------
def setup_page(new_page)
@page = new_page
if @page
setup_page_settings
else
clear_page_settings
end
update_bush_depth
clear_starting_flag
check_event_trigger_auto
end
#--------------------------------------------------------------------------
# ● イベントページの設定をクリア
#--------------------------------------------------------------------------
def clear_page_settings
@tile_id = 0
@character_name = ""
@character_index = 0
@move_type = 0
@through = true
@trigger = nil
@list = nil
@interpreter = nil
@battler = nil
end
#--------------------------------------------------------------------------
# ● イベントページの設定をセットアップ
#--------------------------------------------------------------------------
def setup_page_settings
@tile_id = @page.graphic.tile_id
@character_name = @page.graphic.character_name
@character_index = @page.graphic.character_index
if @original_direction != @page.graphic.direction
@direction = @page.graphic.direction
@original_direction = @direction
@prelock_direction = 0
end
if @original_pattern != @page.graphic.pattern
@pattern = @page.graphic.pattern
@original_pattern = @pattern
end
@move_type = @page.move_type
@move_speed = @page.move_speed
@move_frequency = @page.move_frequency
@move_route = @page.move_route
@move_route_index = 0
@move_route_forcing = false
@walk_anime = @page.walk_anime
@step_anime = @page.step_anime
@direction_fix = @page.direction_fix
@through = @page.through
@priority_type = @page.priority_type
@trigger = @page.trigger
@list = @page.list
@interpreter = @trigger == 4 ? Game_SrpgInterpreter.new : nil
setup_ex_param
setup_srpg_battler
end
#--------------------------------------------------------------------------
# ● 表示拡張のセットアップ
#--------------------------------------------------------------------------
def setup_ex_param
clear_ex_param
if @list
if /<zm\s+(\d+(?:\.\d+)?)\s*\,\s*(\d+(?:\.\d+)?)>/i =~ @event.name
@zoom_x, @zoom_y = $1.to_f, $2.to_f
end
@list.each do |list|
if list.code == 108 || list.code == 408
text = list.parameters[0]
if /<zm\s+(\d+(?:\.\d+)?)\s*\,\s*(\d+(?:\.\d+)?)>/i =~ text
@zoom_x, @zoom_y = $1.to_f, $2.to_f
end
else
break
end
end
end
end
#--------------------------------------------------------------------------
# ● バトラーのセットアップ
#--------------------------------------------------------------------------
def setup_srpg_battler
key = [$game_srpgmap.map_id, @id, "D"]
if !$game_self_switches[key] && /<(?:ENEMY|Enemy)\s*(\d+)>/i =~ @event.name
@battler = Game_Enemy.new(@id, $1.to_i)
@npc = /<NPC>/i =~ @event.name ? true : false
@boss = /<Boss>/ =~ @event.name ? true : false
@rule_out = /<Target>/ =~ @event.name ? true : false
@princess = /<Protect>/i =~ @event.name ? true : false
set_graphic(battler.character_name, battler.character_index)
@step_anime = true
update_tile_state
else
@battler = nil
end
end
#--------------------------------------------------------------------------
# ● 自動イベントの起動判定
#--------------------------------------------------------------------------
def check_event_trigger_auto
start if @trigger == 3
end
#--------------------------------------------------------------------------
# ● フレーム更新
#--------------------------------------------------------------------------
def update
super
check_event_trigger_auto
return unless @interpreter
@interpreter.setup(@list, @event.id) unless @interpreter.running?
@interpreter.update
end
#--------------------------------------------------------------------------
# ● 向きによるダメージペナルティ状態の更新
#--------------------------------------------------------------------------
def update_dir_penalty(user, item)
battler.set_dir_penalty(@direction == user.direction)
end
#--------------------------------------------------------------------------
# ● 地形効果ステートの更新
#--------------------------------------------------------------------------
def update_tile_state
return unless battler?
region_id = $game_srpgmap.region_id(@x, @y)
state_id = TMSRPG::TILE_STATE[region_id]
state_id ||= 0
battler.set_tile_state(state_id)
end
#--------------------------------------------------------------------------
# ● 目的地をセット( nil で目的地設定を解除)
# pos : [x, y]
#--------------------------------------------------------------------------
def set_goal(pos)
@goal_pos = pos
end
#--------------------------------------------------------------------------
# ● 行動時の向きをシミュレートしてペナルティ状態を更新する
#--------------------------------------------------------------------------
def test_dir_penalty(user, x = nil, y = nil)
x ||= $game_srpgplayer.x
y ||= $game_srpgplayer.y
last_dir = user.direction
user.turn_toward_pos(x, y)
update_dir_penalty(user, user.battler.current_action.item)
user.set_direction(last_dir)
end
#--------------------------------------------------------------------------
# ● 移動前に行動時の向きをシミュレートしてペナルティ状態を更新する
#--------------------------------------------------------------------------
def test_dir_penalty_pre_move(target, pos_m, x, y)
last_x, last_y = @x, @y
@x, @y = *pos_m
target.test_dir_penalty(self, x, y)
@x, @y = last_x, last_y
end
#--------------------------------------------------------------------------
# ● 移動前の座標を記憶
#--------------------------------------------------------------------------
def set_last_pos(x, y, direction)
@last_pos = [x, y, direction]
end
#--------------------------------------------------------------------------
# ● 指定座標までの移動をセット
#--------------------------------------------------------------------------
def setup_move_route(route_text)
set_last_pos(@x, @y, @direction) # 移動前の座標を記憶
route = RPG::MoveRoute.new
route.repeat = false
route.wait = true
speed = $game_srpgmap.show_fast? ? 6 : 4 # 早送り状態なら速度を速める
route.list[0] = RPG::MoveCommand.new(ROUTE_CHANGE_SPEED, [speed])
route.list.push(RPG::MoveCommand.new(ROUTE_THROUGH_ON, []))
route_text.length.times do |i|
route.list.push(RPG::MoveCommand.new(route_text[i].to_i))
end
route.list.push(RPG::MoveCommand.new(ROUTE_THROUGH_OFF, []))
route.list.push(RPG::MoveCommand.new(ROUTE_CHANGE_SPEED, [4])) # 速度を戻す
route.list.push(RPG::MoveCommand.new(0))
force_move_route(route)
end
#--------------------------------------------------------------------------
# ● ノックバックをセット
#--------------------------------------------------------------------------
def setup_knock_back(user, item)
route = RPG::MoveRoute.new
route.repeat = false
route.skippable = true
route.wait = true
route.list[0] = RPG::MoveCommand.new(ROUTE_CHANGE_SPEED, [6])
route.list.push(RPG::MoveCommand.new(ROUTE_DIR_FIX_ON, []))
item.knock_back[0].times do |i|
route.list.push(RPG::MoveCommand.new(user.direction / 2))
end
route.list.push(RPG::MoveCommand.new(ROUTE_DIR_FIX_OFF, []))
route.list.push(RPG::MoveCommand.new(ROUTE_CHANGE_SPEED, [4])) # 速度を戻す
route.list.push(RPG::MoveCommand.new(0))
force_move_route(route)
end
#--------------------------------------------------------------------------
# ● ノックバックキャンセルをセット
#--------------------------------------------------------------------------
def setup_knock_back_cancel(user)
route = RPG::MoveRoute.new
route.repeat = false
route.wait = true
route.list[0] = RPG::MoveCommand.new(ROUTE_DIR_FIX_ON, [])
route.list.push(RPG::MoveCommand.new(ROUTE_THROUGH_ON, []))
case user.direction
when 2; route.list.push(RPG::MoveCommand.new(ROUTE_JUMP, [0, -1]))
when 4; route.list.push(RPG::MoveCommand.new(ROUTE_JUMP, [1, 0]))
when 6; route.list.push(RPG::MoveCommand.new(ROUTE_JUMP, [-1, 0]))
when 8; route.list.push(RPG::MoveCommand.new(ROUTE_JUMP, [0, 1]))
end
route.list.push(RPG::MoveCommand.new(ROUTE_THROUGH_OFF, []))
route.list.push(RPG::MoveCommand.new(ROUTE_DIR_FIX_OFF, []))
route.list.push(RPG::MoveCommand.new(0))
force_move_route(route)
end
#--------------------------------------------------------------------------
# ● 指定した座標の方向を返す
#--------------------------------------------------------------------------
def direction_from_pos(x = nil, y = nil)
x ||= $game_srpgplayer.x
y ||= $game_srpgplayer.y
sx = distance_x_from(x)
sy = distance_y_from(y)
if sx.abs > sy.abs
sx > 0 ? 4 : 6
elsif sy != 0
sy > 0 ? 8 : 2
else
0
end
end
#--------------------------------------------------------------------------
# ● 指定した座標の方を向く
#--------------------------------------------------------------------------
def turn_toward_pos(x = nil, y = nil)
d = direction_from_pos(x, y)
set_direction(d) if d > 0
end
#--------------------------------------------------------------------------
# ● 移動の実行
#--------------------------------------------------------------------------
def execute_move
@moved = true
@step_anime = false if @acted
update_tile_state
end
#--------------------------------------------------------------------------
# ● 移動のキャンセル
#--------------------------------------------------------------------------
def reset_move
moveto(@last_pos[0], @last_pos[1])
@direction = @last_pos[2]
@moved = false
end
#--------------------------------------------------------------------------
# ● ゲートへ戻すときの処理
#--------------------------------------------------------------------------
def back_to_gate
@priority_type = 0
erase
end
#--------------------------------------------------------------------------
# ● 行動の実行
#--------------------------------------------------------------------------
def execute_action
return unless battler?
@acted = true
@step_anime = false if @moved
battler.on_action_end
popup_removed_status(@real_x + 0.5, @real_y) # 解除された効果をポップアップ
end
#--------------------------------------------------------------------------
# ● ターンリセット
#--------------------------------------------------------------------------
def on_turn_end
return unless battler?
#~ execute_action unless acted? # 行動していなければここで行動終了処理
@moved = false
@acted = false
@step_anime = true
battler.on_turn_end
popup_damage(@real_x + 0.5, @real_y)
popup_added_status(@real_x + 0.5, @real_y) # 付加された効果をポップアップ
popup_removed_status(@real_x + 0.5, @real_y) # 解除された効果をポップアップ
die(nil) if battler.dead?
end
#--------------------------------------------------------------------------
# ● 被行動結果をポップアップ
#--------------------------------------------------------------------------
def popup_result(user, item)
x = @real_x + 0.5
y = @real_y
if battler.result.missed
popup_miss(x, y)
elsif battler.result.evaded
popup_evade(x, y)
else
popup_added_status(x, y) # 付加された効果をポップアップ
popup_removed_status(x, y) # 解除された効果をポップアップ
popup_critical(x, y) if battler.result.critical
popup_damage(x, y, item)
popup_drain(user.real_x + 0.5, user.real_y)
end
end
#--------------------------------------------------------------------------
# ● ミスのポップアップ
#--------------------------------------------------------------------------
def popup_miss(x, y)
$game_srpgmap.add_popup(x, y, "MISS", 10)
end
#--------------------------------------------------------------------------
# ● 回避のポップアップ
#--------------------------------------------------------------------------
def popup_evade(x, y)
$game_srpgmap.add_popup(x, y, "DODGE", 10)
end
#--------------------------------------------------------------------------
# ● 付加された効果をポップアップ
#--------------------------------------------------------------------------
def popup_added_status(x, y)
# 付与されたステート
battler.result.added_state_objects.each do |state|
$game_srpgmap.add_popup(x, y, state.name, 0, :state)
y -= 0.5
end
# 付与されたバフ
battler.result.added_buffs.each do |param_id|
$game_srpgmap.add_popup(x, y, Vocab::param(param_id) + "+", 4, :state)
y -= 0.5
end
# 付与されたデバフ
battler.result.added_debuffs.each do |param_id|
$game_srpgmap.add_popup(x, y, Vocab::param(param_id) + "-", 5, :state)
y -= 0.5
end
end
#--------------------------------------------------------------------------
# ● 解除された効果をポップアップ
#--------------------------------------------------------------------------
def popup_removed_status(x, y)
# 解除されたステート
battler.result.removed_state_objects.each do |state|
$game_srpgmap.add_popup(x, y, state.name, 8, :remove)
y += 0.5
end
# 解除されたバフ、デバフ
battler.result.removed_buffs.each do |param_id|
$game_srpgmap.add_popup(x, y, Vocab::param(param_id), 8, :remove)
y += 0.5
end
end
#--------------------------------------------------------------------------
# ● クリティカルのポップアップ
#--------------------------------------------------------------------------
def popup_critical(x, y)
$game_srpgmap.add_popup(x, y - 0.5, "CRITICAL", 6)
end
#--------------------------------------------------------------------------
# ● ダメージのポップアップ
#--------------------------------------------------------------------------
def popup_damage(x, y, item = nil)
if battler.result.hp_damage != 0 || (item && item.damage.type == 1)
color_id = battler.result.hp_damage >= 0 ? 0 : 3
$game_srpgmap.add_popup(x, y, battler.result.hp_damage.abs.to_s, color_id)
end
if battler.result.mp_damage != 0 || (item && item.damage.type == 2)
color_id = battler.result.mp_damage >= 0 ? 0 : 3
$game_srpgmap.add_popup(x, y, "MND " + battler.result.mp_damage.abs.to_s, color_id)
end
end
#--------------------------------------------------------------------------
# ● 吸収のポップアップ
#--------------------------------------------------------------------------
def popup_drain(x, y)
if battler.result.hp_drain != 0
color_id = battler.result.hp_drain >= 0 ? 3 : 0
$game_srpgmap.add_popup(x, y, battler.result.hp_drain.abs.to_s, color_id)
end
if battler.result.mp_drain != 0
color_id = battler.result.mp_drain >= 0 ? 3 : 0
$game_srpgmap.add_popup(x, y, "MND " + battler.result.mp_drain.abs.to_s, color_id)
end
end
#--------------------------------------------------------------------------
# ● アニメーションの表示
#--------------------------------------------------------------------------
def setup_animation(user, animation_id)
if animation_id < 0
animation_id = user.atk_animation_id1
end
@animation_id = animation_id
end
#--------------------------------------------------------------------------
# ● スキル/アイテムの反撃率計算
#--------------------------------------------------------------------------
def item_cnt(user, item)
return 0 unless battler
return 0 unless item.physical? # 命中タイプが物理ではない
battler.make_actions
battler.current_action.set_attack
unless $game_srpgmap.make_actable_area(x, y, battler.current_action.item)[[user.x, user.y]] == 1
return 0
end
battler.cnt
end
#--------------------------------------------------------------------------
# ● スキル/アイテムのノックバック率計算
#--------------------------------------------------------------------------
def item_knock_back(user, item)
return 0 unless battler.result.success
return 0 unless item.knock_back
return 0 unless battler
return 0 if rand < battler.knock_back_guard
return item.knock_back[1] / 100.0
end
#--------------------------------------------------------------------------
# ● 戦闘不能になった時の処理
#--------------------------------------------------------------------------
def die(attacker)
gain_reward(attacker)
unless object?
if enemy?
$game_srpgmap.increase_enemy_death
else
$game_srpgmap.increase_npc_death
end
end
Sound.play_enemy_collapse
key = [$game_srpgmap.map_id, @id, "D"]
$game_self_switches[key] = true
@priority_type = 0
@battler = nil
$game_srpgmap.check_gameover # ゲームオーバー判定
end
#--------------------------------------------------------------------------
# ● 撃破時のリワード獲得
#--------------------------------------------------------------------------
def gain_reward(attacker = nil)
exp = battler.exp
$game_party.members.each do |actor|
if attacker && attacker.actor? && actor.id == attacker.battler.id
actor.gain_exp((exp * TMSRPG::EXP_ATTACKER_RATE).to_i)
elsif $game_srpgmap.actor_in_battle?(actor.id)
actor.gain_exp((exp * TMSRPG::EXP_BATTLER_RATE).to_i)
else
actor.gain_exp((exp * TMSRPG::EXP_PARTY_RATE).to_i)
end
end
$game_party.gain_gold(battler.gold)
x = @real_x + 0.5
y = @real_y
battler.make_drop_items.each do |item|
$game_party.gain_item(item, 1)
$game_srpgmap.add_popup(x, y, "+" + item.name, 17, :reward)
y -= 0.5
end
end
#--------------------------------------------------------------------------
# ● 行動内容から移動先を決定する
#--------------------------------------------------------------------------
def make_move_pos
if @goal_pos # 移動目標が設定されている場合
return nearest_pos_from_goal(*@goal_pos)
end
if battler.actions.empty? || !battler.current_action.item # 行動が設定されていない場合は逃げる
target = nearest_opponent_event
return target ? farest_pos_from_target(target) : nil
end
item = battler.current_action.item
if acted? || item.effects.any? {|effect| effect.code == 41 && effect.data_id == 0 }
target = nearest_opponent_event
return nil unless target
farest_pos_from_target(target)
else
targets = item.for_friend? ? near_friend_events : near_opponent_events
return nil if targets.empty?
result = nil
score = 0
$game_srpgmap.movable_area_table.keys.each do |pos_m|
$game_srpgmap.make_actable_area(pos_m[0], pos_m[1], item).keys.each do |pos_a|
new_score = 0
effect_area_table = $game_srpgmap.make_effect_area_abs(self, pos_a)
targets.each do |target|
next unless effect_area_table.include?([target.x, target.y])
test_dir_penalty_pre_move(target, pos_m, target.x, target.y)
n = target.battler.test_damage_value(battler, item).abs + 1
n *= 2 if target.battler.hp < target.battler.mhp / 4
n *= 2 if target.battler.item_has_any_valid_effects?(battler, item)
new_score += n
end
result, score = pos_m, new_score if new_score > score
end
end
return result if result
targets.sort! {|a, b| distance_event_from(a) - distance_event_from(b) }
nearest_pos_from_target(targets[0])
end
end
#--------------------------------------------------------------------------
# ● 移動可能範囲の中から移動目標に一番近づける座標を返す
#--------------------------------------------------------------------------
def nearest_pos_from_goal(x, y)
return nil if pos?(x, y) # すでに目的地にいるなら移動しない
d = 500
result = nil
$game_srpgmap.movable_area_table.keys.each do |pos|
new_d = (pos[0] - x).abs + (pos[1] - y).abs
d, result = new_d, pos if new_d < d
end
result
end
#--------------------------------------------------------------------------
# ● 移動可能範囲の中から対象に一番近づける座標を返す
#--------------------------------------------------------------------------
def nearest_pos_from_target(target)
d = 500
result = nil
$game_srpgmap.movable_area_table.keys.each do |pos|
new_d = target.distance_pos_from(*pos)
d, result = new_d, pos if new_d < d
end
result
end
#--------------------------------------------------------------------------
# ● 移動可能範囲の中から対象から一番遠ざかる座標を返す
#--------------------------------------------------------------------------
def farest_pos_from_target(target)
d = 0
result = nil
$game_srpgmap.movable_area_table.keys.each do |pos|
new_d = target.distance_pos_from(*pos)
d, result = new_d, pos if new_d > d
end
result
end
#--------------------------------------------------------------------------
# ● 行動を実行する座標を決定する
#--------------------------------------------------------------------------
def make_action_pos
item = battler.current_action.item
score = 0
result = nil
$game_srpgmap.actable_area_table.keys.each do |pos_a|
new_score = 0
$game_srpgmap.effect_area_table.each do |pos_e|
x = pos_a[0] + pos_e[0]
y = pos_a[1] + pos_e[1]
target = $game_srpgmap.battler_event_xy(x, y)
next unless target # 誰も見つからない
next unless item.for_friend? == friend?(target) # 行動対象ではない
target.test_dir_penalty(self, target.x, target.y)
n = target.battler.test_damage_value(battler, item).abs + 1
n *= 2 if target.battler.hp < target.battler.mhp / 4
n *= 2 if target.battler.item_has_any_valid_effects?(battler, item)
new_score += n
end
score, result = new_score, pos_a if new_score > score
end
result
end
#--------------------------------------------------------------------------
# ● 指定したイベントのHPを回復する
#--------------------------------------------------------------------------
def gain_hp(value, enable_death = false)
if battler?
battler.change_hp(value, enable_death)
die(nil) if battler.dead?
end
end
#--------------------------------------------------------------------------
# ● 指定したイベントのMPを回復する
#--------------------------------------------------------------------------
def gain_mp(value)
battler.mp += value if battler?
end
#--------------------------------------------------------------------------
# ● 指定したイベントにステートを付加する
#--------------------------------------------------------------------------
def add_state(state_id)
battler.add_state(state_id) if battler?
end
#--------------------------------------------------------------------------
# ● 指定したイベントのステートを解除する
#--------------------------------------------------------------------------
def remove_state(state_id)
battler.remove_state(state_id) if battler?
end
#--------------------------------------------------------------------------
# ● 指定したイベントを全回復させる
#--------------------------------------------------------------------------
def recover_all
battler.recover_all if battler?
end
end