# ▽△▽ XAS.【アクションシステム】 ▽△▽ # # # #============================================================================== # カスタマイズポイント #============================================================================== module XAS # # アクション命中反応 変数ID # HIT_ID = 3 # # 「アクションテンプレート」MAP ID # ACTION_TEMPLATE_MAP_ID = 1 # # アクションID=>アイテムID 消費ハッシュ # ITEM_COST = { 3=>7, 21=>1, 22=>2, 23=>3, 24=>4, 25=>5 } end #------------------------------------------------------------------------------ # # # ▽ アクションテンプレート # # #============================================================================== # --- XAS. アクションテンプレート --- #============================================================================== module XRXS_ActionTemplate # MAP ID の取得 map_id = XAS::ACTION_TEMPLATE_MAP_ID # マップをファイルからロード map = load_data(sprintf("Data/Map%03d.rxdata", map_id)) # そのマップのイベント群を保持する @@events = map.events end class Token_Event < Game_Event include XRXS_ActionTemplate end #============================================================================== #============================================================================== # --- テンポラリ アクティブトークン --- #============================================================================== class Game_Temp attr_accessor :active_token end #============================================================================== # --- XAS. アクションアタッチメント機構 --- #============================================================================== module XAS_ACTION #-------------------------------------------------------------------------- # ○ 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :action attr_reader :erased #-------------------------------------------------------------------------- # ○ アクションの実行 #-------------------------------------------------------------------------- def shoot(action_id) # 例外処理 return if action_id == 0 # アイテム所持判別 item_id = XAS::ITEM_COST[action_id] if item_id != nil and $game_party.item_number(item_id) == 0 # ブザー SE を演奏 $game_system.se_play($data_system.buzzer_se) return end # セルフアクションアタッチメント self.action_attachment(action_id) # # [前隙]の取得 # n = Database_Bullet::PRELAGS[action_id].to_i + 1 @action.prelag = n # # [後隙]の取得 # m = Database_Bullet::SUFLAGS[action_id].to_i @action.duration = n + m end #-------------------------------------------------------------------------- # ○ アクションアタッチメント #-------------------------------------------------------------------------- def action_attachment(action_id) # # アクションの作成 # @action = Game_Action.new(self, action_id) @action.attachment(action_id) # # [自己アニメーション予約]の取得 # plan = Database_Bullet::SELF_ANIMATION_PLANS[action_id] @self_animation_plan = plan.nil? ? nil : plan.dup end #-------------------------------------------------------------------------- # ○ アクションフレーム更新 #-------------------------------------------------------------------------- def action_update # アクションがない場合 return unless @action.is_a?(Game_Action) # # [自己モーション]の更新 # if @self_motion != nil self.character_name_suffix = @self_motion @pattern = 0 @pattern_count = 0 @self_motion = nil end # # [自己アニメーション予約]の更新 # if @self_animation_plan != nil animation_id = @self_animation_plan[@action.now_count] self.animation_id = animation_id unless animation_id.nil? end # # [前隙] # if @action.prelag > 0 @action.prelag -= 1 self.shoot_bullet(@action.id) if @action.prelag == 0 return end # # 最後にアクションを更新 # @action.update end #-------------------------------------------------------------------------- # ○ 攻撃によるイベント起動判定 #-------------------------------------------------------------------------- def check_event_trigger_attack() # イベント実行中の場合 if $game_system.map_interpreter.running? return end # アクションまたは攻撃IDがない場合 if @action.nil? or @action.attack_id == 0 return end # hit_check = false # 全イベントのから命中するイベントを検索 range = @action.attack_range hit = [] targets = [$game_player] + (@action.player_damage ? [] : $game_map.events.values) for event in targets # (自分 / 命中済み / ジャンプ中 / 一時消去) の場合は飛ばす next if event == self or @action.hit_events.include?(event) or event.jumping? or event.erased body_size = event.body_size event_center_x = event.x event_center_y = event.y - body_size dx = event_center_x - self.x dy = event_center_y - self.y dx = (dx >= 0 ? [dx - body_size, 0].max : [dx + body_size, 0].min) dy = (dy >= 0 ? [dy - body_size, 0].max : [dy + body_size, 0].min) case @action.attack_range_type when Map::RHOMBUS hit_check = (dx.abs + dy.abs <= range) when Map::SQUARE hit_check = (dx.abs <= range and dy.abs <= range) when Map::LINE case self.direction when 2 hit_check = (dx == 0 and dy >= 0 and dy <= range) when 8 hit_check = (dx == 0 and dy <= 0 and dy >= -range) when 6 hit_check = (dy == 0 and dx >= 0 and dx <= range) when 4 hit_check = (dy == 0 and dx <= 0 and dx >= -range) end end hit.push(event) if hit_check hit_check = false end # 命中したイベントらへアクションの効果適用 for event in hit if event.action_effect(self, self.action.attack_id) hit_check = true end # ヒット済み対象に登録 @action.hit_events.push(event) end if hit_check # テンポラリアクティブトークンに登録 $game_temp.active_token = self # 命中時、[貫通]性能がないなら消滅を早める self.action_finalize if not self.action.piercing end end #-------------------------------------------------------------------------- # ○ アクションの効果適用 #-------------------------------------------------------------------------- def action_effect(attacker, attack_id) return false unless self.is_a?(Game_Event) for page in @event.pages if page.condition.variable_valid and page.condition.variable_id == XAS::HIT_ID and page.condition.variable_value == attack_id # リアクションヴァリッド IDを設定 self.reaction_valid_attack_id = attack_id # リフレッシュして適用 self.refresh @trigger = 0 # イベントを即座に実行 self.start return true end end return false end #-------------------------------------------------------------------------- # ○ 飛び道具の発射 (発生) #-------------------------------------------------------------------------- def shoot_bullet(action_id) # 例外処理 return false if action_id == 0 # アイテム消費 item_id = XAS::ITEM_COST[action_id] if item_id != nil $game_party.lose_item(item_id, 1) end # 飛び道具トークンを作成 bullet_token = Token_Bullet.new(self, action_id) # マップにに登録 $game_map.add_token(bullet_token) # [自己モーション]の取得 @self_motion = Database_Bullet::SELF_MOTIONS[action_id] # return bullet_token end #-------------------------------------------------------------------------- # ○ くらい判定の取得 (拡張用) #-------------------------------------------------------------------------- def body_size return 0 end #-------------------------------------------------------------------------- # ○ アクション強制末尾化 #-------------------------------------------------------------------------- def action_finalize @action.finalize if @action != nil end #-------------------------------------------------------------------------- # ○ アクションクリア #-------------------------------------------------------------------------- def action_clear @action = nil self.character_name_suffix = nil end end class Game_Character include XAS_ACTION end #============================================================================== # --- 更新と解放 --- #============================================================================== module XAS_Dispose def update # アクションフレーム更新 action_update # 呼び戻す super # [アクション寿命] 判定 if @action.is_a?(Game_Action) and @action.done? self.action_clear end end end class Game_Player < Game_Character include XAS_Dispose end class Game_Event < Game_Character include XAS_Dispose end #============================================================================== # --- 接尾キャラクター名 機構 (アクセサ character_name_suffix を提供します) --- #============================================================================== module XAS_CharacterName_Suffix def character_name # 基本を取得 character_name = super # 新しいファイル名の作成 file_name = character_name + self.character_name_suffix.to_s # 新しいグラフィックファイルへ変更 (ファイルがある場合) character_name = file_name if RPG_FileTest.character_exist?(file_name) # return character_name end attr_accessor :character_name_suffix end class Game_Player < Game_Character include XAS_CharacterName_Suffix end class Game_Event < Game_Character include XAS_CharacterName_Suffix end #============================================================================== # --- アクション中は移動不可能 --- #============================================================================== module XAS_StopToAction def acting? return self.action != nil end def moving? return (super or self.acting?) end end class Game_Player < Game_Character include XAS_StopToAction end #============================================================================== # --- リアクションヴァリッド機能 --- #============================================================================== class Interpreter alias xrxs64_command_end command_end def command_end # リストのクリア @list = nil # イベントの取得 event = $game_map.events[@event_id] # イベントが既に存在しない場合は終了 return if event == nil # リアクションヴァリッドをクリア if event.reaction_valid_attack_id event.reaction_valid_attack_id = nil event.refresh end # 呼び戻す xrxs64_command_end end end class Game_Event < Game_Character attr_accessor :reaction_valid_attack_id #-------------------------------------------------------------------------- # ● リフレッシュ [再定義] #-------------------------------------------------------------------------- def refresh # ローカル変数 new_page を初期化 new_page = nil # 一時消去されていない場合 unless @erased # 番号の大きいイベントページから順に調べる for page in @event.pages.reverse # イベント条件を c で参照可能に c = page.condition # スイッチ 1 条件確認 if c.switch1_valid if $game_switches[c.switch1_id] == false next end end # スイッチ 2 条件確認 if c.switch2_valid if $game_switches[c.switch2_id] == false next end end # 変数 条件確認 (この部分だけ変更) if c.variable_valid if c.variable_id == XAS::HIT_ID and c.variable_value == self.reaction_valid_attack_id # elsif $game_variables[c.variable_id] < c.variable_value next end end # セルフスイッチ 条件確認 if c.self_switch_valid key = [@map_id, @event.id, c.self_switch_ch] if $game_self_switches[key] != true next end end # ローカル変数 new_page を設定 new_page = page # ループを抜ける break end end # 前回と同じイベントページの場合 if new_page == @page # メソッド終了 return end # @page に現在のイベントページを設定 @page = new_page # 起動中フラグをクリア clear_starting # 条件を満たすページがない場合 if @page == nil # 各インスタンス変数を設定 @tile_id = 0 @character_name = "" @character_hue = 0 @move_type = 0 @through = true @trigger = nil @list = nil @interpreter = nil # メソッド終了 return end # 各インスタンス変数を設定 @tile_id = @page.graphic.tile_id @character_name = @page.graphic.character_name @character_hue = @page.graphic.character_hue 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 @opacity = @page.graphic.opacity @blend_type = @page.graphic.blend_type @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 @always_on_top = @page.always_on_top @trigger = @page.trigger @list = @page.list @interpreter = nil # トリガーが [並列処理] の場合 if @trigger == 4 # 並列処理用インタプリタを作成 @interpreter = Interpreter.new end # 自動イベントの起動判定 check_event_trigger_auto end end #============================================================================== # □ Game_Action #------------------------------------------------------------------------------ # アクションを扱うクラスです。Game_Character 以下のクラスから参照されます。 #============================================================================== class Game_Action #-------------------------------------------------------------------------- # ○ 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :id # (Numeric) attr_accessor :prelag # (Numeric) attr_accessor :attack_id # (Numeric) attr_reader :attack_range # (Numeric) attr_reader :attack_range_type # (Numeric) attr_accessor :user # (Game_Battler) attr_reader :hit_events # (Array)[Game_Character] attr_accessor :now_count # (Numeric) attr_reader :final_mark # (nil / Numeric) attr_accessor :duration # (nil / Numeric) attr_reader :blow_power # (Numeric) attr_reader :piercing # (true / nil) attr_reader :player_damage # (true / nil) attr_reader :ignore_invincible # (true / nil) #-------------------------------------------------------------------------- # ○ オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(user, action_id) @user = user @id = action_id @prelag = 0 @now_count = 0 @duration = nil @attack_id = 0 @attack_range= 0 @hit_events = [] @blow_power = 0 end #-------------------------------------------------------------------------- # ○ アクションアタッチメント #-------------------------------------------------------------------------- def attachment(action_id) # # [寿命時間 / ファイナライズマーク]の取得 # @duration = Database_Bullet::DURATIONS[action_id] @final_mark = Database_Bullet::FINALIZE_MARKS[action_id] # # [ブロー力]の取得 # power = Database_Bullet::BLOW_POWERS[action_id] @blow_power = power == nil ? 1 : power # # [攻撃ID予約]の取得 # @attack_id_plan = Database_Bullet::ATTACK_ID_PLANS[action_id] # # [攻撃射程タイプ] / [攻撃射程予約]の取得 # @attack_range_type = Database_Bullet::ATTACK_RANGE_TYPES[action_id] plan = Database_Bullet::ATTACK_RANGE_PLANS[action_id] @attack_range_plan = plan.nil? ? nil : plan.dup # # [貫通]の取得 # @piercing = Database_Bullet::PIERCINGS[action_id] # [自己巻き込み]の取得 @self_damage = Database_Bullet::SELF_DAMAGES[self.id] # [プレイヤーのみダメージ]の取得 @player_damage = Database_Bullet::PLAYER_DAMAGES[action_id] # [ダメージハイブリンク貫通]の取得 @ignore_invincible = Database_Bullet::IGNORE_INVINCIBLES[action_id] end #-------------------------------------------------------------------------- # ○ フレーム更新 #-------------------------------------------------------------------------- def update # [攻撃ID予約]の更新 if @attack_id_plan != nil id = @attack_id_plan[@now_count] unless id.nil? @attack_id = id @hit_events.clear @hit_events.push(self.user) unless @self_damage end end # [攻撃射程予約]の更新 if @attack_range_plan != nil range = @attack_range_plan[@now_count] @attack_range = range unless range.nil? end # アクションをカウント @now_count += 1 end #-------------------------------------------------------------------------- # ○ アクション強制末尾化 #-------------------------------------------------------------------------- def finalize # ファイナライズマークへ移行 if @duration.is_a?(Numeric) and @final_mark.is_a?(Numeric) @now_count = [@now_count, @final_mark].max end end #-------------------------------------------------------------------------- # ○ 終えた? #-------------------------------------------------------------------------- def done? return (self.duration.to_i > 0 and self.now_count >= self.duration) end end #============================================================================== # □ Token_Bullet #------------------------------------------------------------------------------ # 飛び道具トークンなどを扱うクラスです。 #============================================================================== class Token_Bullet < Token_Event #-------------------------------------------------------------------------- # ○ オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(user, action_id) # アクションテンプレートの取得 original_event = @@events[Database_Bullet::EVENT_IDS[action_id]] return if original_event == nil event = original_event.dup # dup必須 event.x = user.x event.y = user.y # とりあえず 0 ページ目を表示 event.pages[0].graphic.direction = user.direction @character_name = event.pages[0].graphic # 呼び戻す super($game_map.map_id, event) # セルフアクションアタッチメント self.action_attachment(action_id) # 使用者を設定 @action.user = user # 飛び道具自体の寿命 @remain_for_an_act = @action.duration.is_a?(Numeric) end #-------------------------------------------------------------------------- # ○ フレーム更新 #-------------------------------------------------------------------------- def update # 呼び戻す super # アクション終了時、飛び道具ならば一時消去 erase if @action == nil and @remain_for_an_act # 攻撃によるイベント開始判定 check_event_trigger_attack end end #============================================================================== # □ Database_Bullet #------------------------------------------------------------------------------ # ブリッツデータベース。飛び道具などのアクション設定を管理する。 #============================================================================== module Map # 定数 RHOMBUS = 1 SQUARE = 2 LINE = 3 end module Database_Bullet include Map # # 初期化 # EVENTS = [] EVENT_IDS = [] DURATIONS = [] PRELAGS = [] SUFLAGS = [] FINALIZE_MARKS = [] ATTACK_ID_PLANS = [] ATTACK_RANGE_TYPES = [] ATTACK_RANGE_PLANS = [] BLOW_POWERS = [] SELF_MOTIONS = [] SELF_ANIMATION_PLANS = [] PIERCINGS = [] SELF_DAMAGES = [] PLAYER_DAMAGES = [] IGNORE_INVINCIBLES = [] end