518 lines
No EOL
21 KiB
Ruby
518 lines
No EOL
21 KiB
Ruby
#_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
|
||
#_/
|
||
#_/ ■ RGSS3 Script WideRangeEvent - イベントの接触範囲を拡大 -
|
||
#_/----------------------------------------------------------------------------
|
||
#_/ 制 作 者 : CanariAlternate
|
||
#_/ 配 布 元 : カルトの鳥篭 (http://canarialt.blog.fc2.com)
|
||
#_/----------------------------------------------------------------------------
|
||
#_/ □ 概要 : イベントの接触範囲を拡大するスクリプトです。
|
||
#_/
|
||
#_/ □ 必須 : 「注釈取得スクリプト」
|
||
#_/
|
||
#_/ □ 位置 : 「経路探索VXAce」より上
|
||
#_/ 「注釈取得スクリプト」より下
|
||
#_/ 「イベント起動判定拡張」より下
|
||
#_/----------------------------------------------------------------------------
|
||
#_/ 注意 : 「マルチレイヤーシステム」との併用は不可
|
||
#_/
|
||
#_/----------------------------------------------------------------------------
|
||
#_/ 仕様 : プライオリティ「通常キャラと同じ」とそれ以外で接触範囲の拡大方法が
|
||
#_/ 異なります。「通常キャラと同じ」は接触範囲のみを拡大しています。
|
||
#_/ 対して、それ以外は接触範囲だけでなく当たり判定も拡大しています。
|
||
#_/----------------------------------------------------------------------------
|
||
#_/ 更新履歴 : 2014/05/28 Ver1.00 スクリプトを作成した。
|
||
#_/ : 2014/06/07 Ver1.01 上向き用の図を左向きに変換にする処理を修正した。
|
||
#_/ : 2014/06/07 Ver1.02 イベントから接触した場合も起動するように変更した。
|
||
#_/ : 2014/06/10 Ver1.03 イベントから接触の判定タイミングを調整した。
|
||
#_/ : 2020/06/11 Ver1.04 経路探索との競合を修正した。(pos?の継承問題)
|
||
#_/
|
||
#_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
|
||
|
||
$imported ||= {}
|
||
$imported[:CanariAlternate_RangeEvent] = true
|
||
|
||
#==============================================================================
|
||
# ■ CaltRangeEvent
|
||
#------------------------------------------------------------------------------
|
||
# このスクリプトの設定です。
|
||
#==============================================================================
|
||
module CaltRangeEvent
|
||
#----------------------------------------------------------------------------
|
||
# ▼ 接触範囲の設定取得
|
||
#
|
||
# ◇ 注釈から設定を取得する為の正規表現
|
||
EVENT_NOTE = /\[\s*接触範囲\s*\:\s*(.+?)\s*\]/m # 記述した頁に適用(全ての頁より優先して採用)
|
||
WHOLE_NOTE = /\<\s*接触範囲\s*\:\s*(.+?)\s*\>/m # 全ての頁に適用(1頁目に記述)
|
||
#
|
||
# 例1 注釈に記述した頁に適用(全ての頁より優先して採用)
|
||
#
|
||
# ◆注釈:[接触範囲: 前方5 ]
|
||
#
|
||
#
|
||
# 例2 全ての頁に適用(1頁目に記述)
|
||
#
|
||
# ◆注釈:<接触範囲: 前方4 >
|
||
#
|
||
# 例1、例2は予め定義してある接触範囲図の接触範囲が適用されます。
|
||
#
|
||
#
|
||
# 例3 図を使用して範囲を指定
|
||
#
|
||
# ◆注釈:[接触範囲:
|
||
# :□□■
|
||
# :■★■
|
||
# :■□■
|
||
# :■□■■
|
||
# :■□■
|
||
# ◆注釈:■■□■■]
|
||
#
|
||
# 例3のように接触範囲図を直接記述することも出来ます。
|
||
#
|
||
#----------------------------------------------------------------------------
|
||
# ▼ 接触範囲図の定義
|
||
# イベントの位置を基準にして接触範囲を図で定義します。
|
||
# 注釈に接触範囲図を直接記述できますが多用する接触範囲はここで定義することを
|
||
# 推奨します。
|
||
#
|
||
# 各記号の意味
|
||
# ■ : 接触する
|
||
# □ : 接触しない
|
||
# ★ : 基準(向きに関係なく固定)
|
||
# ▲ : 基準(向きに合わせて回転。図は上が前。※8方向には非対応)
|
||
# ※基準となる ★ または ▲ は必ず1つ必要です。
|
||
#
|
||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||
# ◇ 接触範囲図のハッシュを生成
|
||
RANGE_DIAGRAM = {}
|
||
#
|
||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||
# ◇ 接触範囲図 1
|
||
RANGE_DIAGRAM["1"] =
|
||
"□■□
|
||
■★■
|
||
□■□"
|
||
#
|
||
# ◇ 接触範囲図 2
|
||
RANGE_DIAGRAM["2"] =
|
||
"□□■□□
|
||
□■■■□
|
||
■■★■■
|
||
□■■■□
|
||
□□■□□"
|
||
#
|
||
# ◇ 接触範囲図 3
|
||
RANGE_DIAGRAM["3"] =
|
||
"□□□■□□□
|
||
□□■■■□□
|
||
□■■■■■□
|
||
■■■★■■■
|
||
□■■■■■□
|
||
□□■■■□□
|
||
□□□■□□□"
|
||
#
|
||
# ◇ 接触範囲図 4
|
||
RANGE_DIAGRAM["4"] =
|
||
"□□□□■□□□□
|
||
□□□■■■□□□
|
||
□□■■■■■□□
|
||
□■■■■■■■□
|
||
■■■■★■■■■
|
||
□■■■■■■■□
|
||
□□■■■■■□□
|
||
□□□■■■□□□
|
||
□□□□■□□□□"
|
||
#
|
||
# ◇ 接触範囲図 5
|
||
RANGE_DIAGRAM["5"] =
|
||
"□□□□□■□□□□□
|
||
□□□□■■■□□□□
|
||
□□□■■■■■□□□
|
||
□□■■■■■■■□□
|
||
□■■■■■■■■■□
|
||
■■■■■★■■■■■
|
||
□■■■■■■■■■□
|
||
□□■■■■■■■□□
|
||
□□□■■■■■□□□
|
||
□□□□■■■□□□□
|
||
□□□□□■□□□□□"
|
||
#
|
||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||
# ◇ 接触範囲図 前方4
|
||
RANGE_DIAGRAM["前方4"] =
|
||
"■■■■■■■■■
|
||
□■■■■■■■□
|
||
□□■■■■■□□
|
||
□□□■■■□□□
|
||
□□□□▲□□□□"
|
||
#
|
||
# ◇ 接触範囲図 前方5
|
||
RANGE_DIAGRAM["前方5"] =
|
||
"■■■■■■■■■■■
|
||
□■■■■■■■■■□
|
||
□□■■■■■■■□□
|
||
□□□■■■■■□□□
|
||
□□□□■■■□□□□
|
||
□□□□□▲□□□□□"
|
||
#
|
||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||
# ◇ 接触範囲図 全方向を別々に定義
|
||
RANGE_DIAGRAM["全方向を別々に定義"] = diagrams = Array.new(10, "★")
|
||
# 下
|
||
diagrams[2] =
|
||
"□■□
|
||
■★■
|
||
□□□"
|
||
# 左
|
||
diagrams[4] =
|
||
"□■□
|
||
■★□
|
||
□□□"
|
||
# 右
|
||
diagrams[6] =
|
||
"□■□
|
||
■★■
|
||
■□□"
|
||
# 上
|
||
diagrams[8] =
|
||
"□□□
|
||
■★■
|
||
□□□"
|
||
#
|
||
#----------------------------------------------------------------------------
|
||
end
|
||
|
||
#==============================================================================
|
||
# ■ CaltRangeEvent
|
||
#------------------------------------------------------------------------------
|
||
# 接触範囲図から情報を抽出して変換する処理を定義しています。
|
||
#==============================================================================
|
||
module CaltRangeEvent
|
||
#--------------------------------------------------------------------------
|
||
# ○ 接触範囲図から情報を抽出
|
||
#--------------------------------------------------------------------------
|
||
def self.read_diagram(diagram)
|
||
range_list = []
|
||
diagram = diagram.clone
|
||
# 基準を探索
|
||
length = diagram.index(/★|▲/) + 1
|
||
last_line = nil
|
||
oy = -1
|
||
diagram[0, length].each_line do |line|
|
||
last_line = line
|
||
oy += 1
|
||
end
|
||
ox = last_line.scan(/■|□|★|▲/).size - 1
|
||
# 接触範囲図を範囲リストに変換
|
||
x = ox
|
||
y = oy
|
||
begin
|
||
case diagram.slice!(0, 1)
|
||
when "\n"
|
||
x = ox
|
||
y -= 1
|
||
when "■"
|
||
range_list.push [x, y]
|
||
x -= 1
|
||
when "□"
|
||
x -= 1
|
||
when "★"
|
||
fix = true
|
||
x -= 1
|
||
when "▲"
|
||
fix = false
|
||
x -= 1
|
||
end
|
||
end until diagram.empty?
|
||
return range_list, fix
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ○ 接触範囲情報を生成
|
||
#--------------------------------------------------------------------------
|
||
def self.create_range(diagram)
|
||
if diagram.kind_of?(String)
|
||
range_list, fix = read_diagram(diagram)
|
||
if fix # 向き固定か判定
|
||
range_hash = {}
|
||
range_list.each {|key| range_hash[key] = true }
|
||
return Array.new(10, range_hash) # ★ は8方向とも同じ接触範囲
|
||
else
|
||
result = Array.new(10, {})
|
||
|
||
range_hash = {}
|
||
range_list.each {|key| range_hash[ [-key[0], -key[1]] ] = true }
|
||
result[2] = range_hash
|
||
|
||
range_hash = {}
|
||
range_list.each {|key| range_hash[ [key[1], -key[0]] ] = true }
|
||
result[4] = range_hash
|
||
|
||
range_hash = {}
|
||
range_list.each {|key| range_hash[ [-key[1], key[0]] ] = true }
|
||
result[6] = range_hash
|
||
|
||
range_hash = {}
|
||
range_list.each {|key| range_hash[key] = true }
|
||
result[8] = range_hash
|
||
|
||
return result # ▲ は8方向には非対応
|
||
end
|
||
else
|
||
return Array.new(10) do |i| # 全方向を対応する接触範囲図で設定
|
||
range_hash = {}
|
||
read_diagram(diagram[i])[0].each {|key| range_hash[key] = true }
|
||
next range_hash
|
||
end
|
||
end
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ○ 上で定義した接触範囲図を接触範囲情報に変換
|
||
#--------------------------------------------------------------------------
|
||
RANGE = {}
|
||
RANGE_DIAGRAM.each {|key, diagram| RANGE[key] = create_range(diagram) }
|
||
end
|
||
|
||
#==============================================================================
|
||
# ■ Game_Map
|
||
#------------------------------------------------------------------------------
|
||
# マップを扱うクラスです。スクロールや通行可能判定などの機能を持っています。
|
||
# このクラスのインスタンスは $game_map で参照されます。
|
||
#==============================================================================
|
||
class Game_Map
|
||
#--------------------------------------------------------------------------
|
||
# ○ 公開インスタンス変数
|
||
#--------------------------------------------------------------------------
|
||
attr_accessor :normal_event_range_mode # 通常キャラの接触判定モード
|
||
#--------------------------------------------------------------------------
|
||
# ● オブジェクト初期化
|
||
#--------------------------------------------------------------------------
|
||
alias :__RangeEvent__initialize :initialize
|
||
def initialize
|
||
__RangeEvent__initialize
|
||
@normal_event_range_mode = false
|
||
end
|
||
end
|
||
|
||
#==============================================================================
|
||
# ■ Game_Player
|
||
#------------------------------------------------------------------------------
|
||
# プレイヤーを扱うクラスです。イベントの起動判定や、マップのスクロールなどの
|
||
# 機能を持っています。このクラスのインスタンスは $game_player で参照されます。
|
||
#==============================================================================
|
||
class Game_Player < Game_Character
|
||
#--------------------------------------------------------------------------
|
||
# ● 同位置のイベント起動判定
|
||
#--------------------------------------------------------------------------
|
||
alias :__RangeEvent__check_event_trigger_here :check_event_trigger_here
|
||
def check_event_trigger_here(triggers)
|
||
$game_map.normal_event_range_mode = true
|
||
start_map_event(@x, @y, triggers, true)
|
||
$game_map.normal_event_range_mode = false
|
||
__RangeEvent__check_event_trigger_here(triggers)
|
||
end
|
||
end
|
||
|
||
#==============================================================================
|
||
# ■ Game_Event
|
||
#------------------------------------------------------------------------------
|
||
# イベントを扱うクラスです。条件判定によるイベントページ切り替えや、並列処理
|
||
# イベント実行などの機能を持っており、Game_Map クラスの内部で使用されます。
|
||
#==============================================================================
|
||
class Game_Event < Game_Character
|
||
#--------------------------------------------------------------------------
|
||
# ● 非公開メンバ変数の初期化
|
||
#--------------------------------------------------------------------------
|
||
alias :__RangeEvent__init_private_members :init_private_members
|
||
def init_private_members
|
||
__RangeEvent__init_private_members
|
||
@range_list = nil
|
||
@last_range_x = nil
|
||
@last_range_y = nil
|
||
@last_range_d = nil
|
||
@last_range_p = nil
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 座標一致判定
|
||
#--------------------------------------------------------------------------
|
||
def pos?(x, y)
|
||
return in_event_range?(x, y, true) if $game_map.normal_event_range_mode
|
||
super(x, y) || in_event_range?(x, y, false)
|
||
end
|
||
# 経路探索と競合:変更前の親クラスを継承して正しい動作にならない。
|
||
# alias :__RangeEvent__pos? :pos?
|
||
# def pos?(x, y)
|
||
# return in_event_range?(x, y, true) if $game_map.normal_event_range_mode
|
||
# __RangeEvent__pos?(x, y) || in_event_range?(x, y, false)
|
||
# end
|
||
#--------------------------------------------------------------------------
|
||
# ● 停止時の更新
|
||
#--------------------------------------------------------------------------
|
||
alias :__RangeEvent__update_stop :update_stop
|
||
def update_stop
|
||
if !@locked && stopping? && (@last_range_x != @x || @last_range_y != @y ||
|
||
@last_range_d != @direction || @last_range_p != @page)
|
||
@last_range_x = @x
|
||
@last_range_y = @y
|
||
@last_range_d = @direction
|
||
@last_range_p = @page
|
||
check_event_trigger_touch_range
|
||
end
|
||
__RangeEvent__update_stop
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ○ 接触イベントの拡大した範囲の起動判定
|
||
#--------------------------------------------------------------------------
|
||
def check_event_trigger_touch_range
|
||
return false unless @range_list
|
||
return false unless normal_priority? == true
|
||
result = false
|
||
@range_list[@direction].each_key do |xy|
|
||
x2 = $game_map.round_x(@x - xy[0])
|
||
y2 = $game_map.round_y(@y - xy[1])
|
||
result = true if check_event_trigger_touch(x2, y2)
|
||
end
|
||
return result
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● イベントページ更新時に注釈から設定を取得
|
||
#--------------------------------------------------------------------------
|
||
alias :__RangeEvent__setup_note_settings :setup_note_settings
|
||
def setup_note_settings
|
||
__RangeEvent__setup_note_settings
|
||
@range_list = get_range_list
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ○ 接触範囲の取得
|
||
#--------------------------------------------------------------------------
|
||
def get_range_list
|
||
result = nil
|
||
if @page.event_note[CaltRangeEvent::EVENT_NOTE]
|
||
result = CaltRangeEvent::RANGE[$1]
|
||
result = CaltRangeEvent.create_range($1) unless result
|
||
elsif @event.pages[0].event_note[CaltRangeEvent::WHOLE_NOTE]
|
||
result = CaltRangeEvent::RANGE[$1]
|
||
result = CaltRangeEvent.create_range($1) unless result
|
||
end
|
||
return result
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ○ 接触範囲内か判定
|
||
#--------------------------------------------------------------------------
|
||
def in_event_range?(x, y, normal)
|
||
return false unless @range_list
|
||
return false unless normal_priority? == normal
|
||
return @range_list[@direction][ [distance_x_from(x), distance_y_from(y)] ]
|
||
end
|
||
end
|
||
|
||
#_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
|
||
#_/
|
||
#_/ ▼ 以下、イベント起動判定拡張との競合回避
|
||
#_/
|
||
#_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
|
||
|
||
if $imported[:CanariAlternate_EventEveryone]
|
||
#==============================================================================
|
||
# ■ Game_Player
|
||
#------------------------------------------------------------------------------
|
||
# プレイヤーを扱うクラスです。イベントの起動判定や、マップのスクロールなどの
|
||
# 機能を持っています。このクラスのインスタンスは $game_player で参照されます。
|
||
#==============================================================================
|
||
class Game_Player < Game_Character
|
||
#--------------------------------------------------------------------------
|
||
# ● 非公開メンバ変数の初期化
|
||
#--------------------------------------------------------------------------
|
||
alias :__RangeEvent__init_private_members :init_private_members
|
||
def init_private_members
|
||
__RangeEvent__init_private_members
|
||
@last_range_x = nil
|
||
@last_range_y = nil
|
||
@last_range_d = nil
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ● 座標一致判定
|
||
#--------------------------------------------------------------------------
|
||
def pos?(x, y)
|
||
return in_event_range?(x, y, true) if $game_map.normal_event_range_mode
|
||
super(x, y) || in_event_range?(x, y, false)
|
||
end
|
||
# 経路探索と競合:変更前の親クラスを継承して正しい動作にならない。
|
||
# alias :__RangeEvent__pos? :pos?
|
||
# def pos?(x, y)
|
||
# return in_event_range?(x, y, true) if $game_map.normal_event_range_mode
|
||
# __RangeEvent__pos?(x, y) || in_event_range?(x, y, false)
|
||
# end
|
||
#--------------------------------------------------------------------------
|
||
# ● 停止時の更新
|
||
#--------------------------------------------------------------------------
|
||
alias :__RangeEvent__update_stop :update_stop
|
||
def update_stop
|
||
if !@locked && stopping? && (@last_range_x != @x || @last_range_y != @y ||
|
||
@last_range_d != @direction)
|
||
@last_range_x = @x
|
||
@last_range_y = @y
|
||
@last_range_d = @direction
|
||
check_event_trigger_touch_range
|
||
end
|
||
__RangeEvent__update_stop
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ○ 接触イベントの拡大した範囲の起動判定
|
||
#--------------------------------------------------------------------------
|
||
def check_event_trigger_touch_range
|
||
range_list = get_range_list
|
||
return false unless range_list
|
||
return false unless normal_priority? == true
|
||
result = false
|
||
range_list[@direction].each_key do |xy|
|
||
x2 = $game_map.round_x(@x - xy[0])
|
||
y2 = $game_map.round_y(@y - xy[1])
|
||
result = true if check_event_trigger_touch(x2, y2)
|
||
end
|
||
return result
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ○ 接触範囲内か判定
|
||
#--------------------------------------------------------------------------
|
||
def in_event_range?(x, y, normal)
|
||
range_list = get_range_list
|
||
return false unless range_list
|
||
return false unless normal_priority? == normal
|
||
return range_list[@direction][ [distance_x_from(x), distance_y_from(y)] ]
|
||
end
|
||
#--------------------------------------------------------------------------
|
||
# ○ 接触範囲の取得
|
||
#--------------------------------------------------------------------------
|
||
def get_range_list
|
||
return nil unless event_list = get_list
|
||
event_note = Calt.Read_EventNote(event_list)
|
||
range_list = nil
|
||
if event_note[CaltRangeEvent::EVENT_NOTE]
|
||
range_list = CaltRangeEvent::RANGE[$1]
|
||
range_list = CaltRangeEvent.create_range($1) unless range_list
|
||
elsif event_note[CaltRangeEvent::WHOLE_NOTE]
|
||
range_list = CaltRangeEvent::RANGE[$1]
|
||
range_list = CaltRangeEvent.create_range($1) unless range_list
|
||
end
|
||
return range_list
|
||
end
|
||
end
|
||
|
||
#==============================================================================
|
||
# ■ Game_Event
|
||
#------------------------------------------------------------------------------
|
||
# イベントを扱うクラスです。条件判定によるイベントページ切り替えや、並列処理
|
||
# イベント実行などの機能を持っており、Game_Map クラスの内部で使用されます。
|
||
#==============================================================================
|
||
class Game_Event < Game_Character
|
||
#--------------------------------------------------------------------------
|
||
# ● 同位置のイベント起動判定
|
||
#--------------------------------------------------------------------------
|
||
alias :__RangeEvent__check_event_trigger_here :check_event_trigger_here
|
||
def check_event_trigger_here(triggers)
|
||
$game_map.normal_event_range_mode = true
|
||
start_map_event(@x, @y, triggers, true)
|
||
$game_map.normal_event_range_mode = false
|
||
__RangeEvent__check_event_trigger_here(triggers)
|
||
end
|
||
end
|
||
end |