############################ アイテム変化システム ############################ # # # 「変化アイテム」を使用することで変化するアイテムを作成します。 # # 「変化:アイテムID」の属性が含まれている武器・防具・道具のは、 # # 「変化:」の後に書かれたIDのアイテムに変化します。 # # # # ただし、アイテムIDの書き方は若干特殊なものになっています。 # # 道具に変化させたい場合は「i○」(○は半角で1以上の整数) # # 武器に変化させたい場合は「w○」(○は半角で1以上の整数) # # 防具に変化させたい場合は「a○」(○は半角で1以上の整数) # # といった形式で書いてください。最初の「i」「w」「a」は省略不可能です。 # # # # これら変化のアイテムを鑑定するアイテムは「効果:変化」の属性がついた道具。 # # ただし、この道具はどういう設定にしても戦闘中は使うことができません。 # # Scene_Itemからのみ呼び出しが可能な設定にしているためです。 # # # # CAN_USE_CHANGE_ALL は全てのアイテムに変化アイテムが使えるかのフラグです。 # # trueにするとたとえそれが「変化:」属性を含まない場合でも使用可能になり、 # # 変化アイテムを使っても「変化しませんでした」とだけ表示されます。 # # また、「変化後のアイテム」が既に所持限界に達している場合も、 # # アイテムの変化に失敗し、アイテム変化の際に使った道具の所持数が減ります。 # # # # また、一つのアイテムに複数の変化結果を設定した場合 # # (例えば「変化:w1」と「変化:i5」と「変化:a3」の属性がついた道具) # # それらのうちのいずれかにランダムで変化します。 # # またその変化後のアイテムの算出は使用した瞬間に決定します。 # # # ############################################################################## # 設定ここから module Annex CHANGE_ITEM_ELEMENT = "効果:変化" # 変化アイテムにつける属性 CHANGABLE_ITEM = "変化:" # 変化する効果があるアイテム CAN_USE_CHANGE_ALL = false # 全てのアイテムに変化アイテムを使えるか CHANGE_SUCCESS_SE = ["056-Right02", 70, 100] # 変化成功 CHANGE_FAILURE_SE = ["039-Switch08", 70, 100] # 変化失敗 # 鑑定時に流れるSE (名前、 ボリューム、 ピッチの順) # 省略した場合(ITEM_JUDGE_SE = nilとする)は音が鳴らない。 end # 設定ここまで #============================================================================== # ■ Game_Party #============================================================================== class Game_Party #-------------------------------------------------------------------------- # ○ アイテムの使用可能判定 # item_id : アイテム ID #-------------------------------------------------------------------------- alias item_change_item_can_use? item_can_use? def item_can_use?(item_id) item = $data_items[item_id] # 変化効果の属性を持つアイテムの場合 if include_element?(item.element_set, Annex::CHANGE_ITEM_ELEMENT) # 戦闘中なら false を返す if $game_temp.in_battle return false end end # 呼び戻し return item_change_item_can_use?(item_id) end #-------------------------------------------------------------------------- # ◎ 追加:任意の属性配列に指定した属性名が含まれているか # element_set : 属性テーブル # name : 属性名 #-------------------------------------------------------------------------- def include_element?(element_set, name) return element_set.include?($data_system.elements.index(name)) end end #============================================================================== # □ 追加:Window_Changable_Item #------------------------------------------------------------------------------ #  アイテム画面で、変化可能なアイテムを選択するウィンドウです。 # (Window_Itemの下位クラスとして作成しています) #============================================================================== class Window_Changable_Item < Window_Item #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize super # Window_Item よりも z の値を 10 大きくする(Window_Itemより手前にする) self.z += 10 end #-------------------------------------------------------------------------- # ● リフレッシュ #-------------------------------------------------------------------------- def refresh if self.contents != nil self.contents.dispose self.contents = nil end @data = [] # アイテムを追加 for i in 1...$data_items.size if $game_party.item_number(i) > 0 # アイテム変化効果のあるアイテムは描画しない # (つまりアイテム変化アイテムにアイテム変化アイテムを使えない) next if include_element?($data_items[i].element_set, Annex::CHANGE_ITEM_ELEMENT) @data.push($data_items[i]) end end for i in 1...$data_weapons.size if $game_party.weapon_number(i) > 0 @data.push($data_weapons[i]) end end for i in 1...$data_armors.size if $game_party.armor_number(i) > 0 @data.push($data_armors[i]) end end # 項目数が 0 でなければビットマップを作成し、全項目を描画 @item_max = @data.size if @item_max > 0 self.contents = Bitmap.new(width - 32, row_max * 32) for i in 0...@item_max draw_item(i) end end end #-------------------------------------------------------------------------- # ● 項目の描画 # index : 項目番号 #-------------------------------------------------------------------------- def draw_item(index) item = @data[index] case item when RPG::Item number = $game_party.item_number(item.id) when RPG::Weapon number = $game_party.weapon_number(item.id) when RPG::Armor number = $game_party.armor_number(item.id) end # アイテムが変化可能か、全アイテムに変化アイテムを適用可能ならばnormal_color if item_can_change?(item, true) or Annex::CAN_USE_CHANGE_ALL self.contents.font.color = normal_color else self.contents.font.color = disabled_color end # ここから先はWindow_Itemの def draw_item と同じなので、 # Window_Item に 改造を加えている人は以下も変更しておく方がみやすいかも。 x = 4 + index % @column_max * (288 + 32) y = index / @column_max * 32 rect = Rect.new(x, y, self.width / @column_max - 32, 32) self.contents.fill_rect(rect, Color.new(0, 0, 0, 0)) bitmap = RPG::Cache.icon(item.icon_name) opacity = self.contents.font.color == normal_color ? 255 : 128 self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity) self.contents.draw_text(x + 28, y, 212, 32, item.name, 0) self.contents.draw_text(x + 240, y, 16, 32, ":", 1) self.contents.draw_text(x + 256, y, 24, 32, number.to_s, 2) end #-------------------------------------------------------------------------- # ● アイテムが変化可能かの確認 # item : アイテム # check_only : 変化アイテムかの確認だけかどうか #-------------------------------------------------------------------------- def item_can_change?(item, check_only = false) # 属性の取得 case item when RPG::Item element = item.element_set when RPG::Weapon element = item.element_set when RPG::Armor element = item.guard_element_set end # 属性から変化アイテムか確認を実行する。 return check_changable_item?(element, check_only) end #-------------------------------------------------------------------------- # ● 変化アイテムかの確認 # element_set : 属性の配列 # check_only : 変化アイテムかの確認だけかどうか #-------------------------------------------------------------------------- def check_changable_item?(element_set, check_only = false) # 変化アイテムの属性名取得 key = Annex::CHANGABLE_ITEM # 変化後のアイテム候補を格納する配列 candidature = [] # 何かアイテムに変化するかの確認 # (変化アイテム属性+[i, w, a] で 始まる属性からIDを取得) for kind in ["i", "w", "a"] id = get_element_key_id(element_set, key + kind) # 合致した場合 if id != [] # 変化アイテムかどうかの確認だけならばここでtrueを返す if check_only return true end # candidature に順にpushしていく for item in id candidature.push([kind, item]) end end end # 変化アイテムかどうかの確認だけならばここでfalseを返す if check_only return false end # candidature に中身がある場合、ここで乱数を回して取得 if candidature.size > 0 # 乱数の初期化 srand(Integer(Time.new) + rand(256)) return candidature[rand(candidature.size)] end # 変化アイテムで無い場合は両方ともゼロを返す return [0, 0] end #-------------------------------------------------------------------------- # ◎ 追加:「属性名+数字」の形式の属性が含まれていればその数字部分を取得。 # element_set : 属性の配列 # key : 取得する属性名 #-------------------------------------------------------------------------- def get_element_key_id(element_set, key) id = [] for i in element_set if $data_system.elements[i] =~ /#{key}([0-9]+)/ # ID取得 id.push($1.to_i) end end return id end #-------------------------------------------------------------------------- # ◎ 追加:任意の属性配列に指定した属性名が含まれているか # element_set : 属性テーブル # name : 属性名 #-------------------------------------------------------------------------- def include_element?(element_set, name) return element_set.include?($data_system.elements.index(name)) end end #============================================================================== # □ 追加:Window_ChangeResult #------------------------------------------------------------------------------ #  変化した結果を一時的に表示するウィンドウです #============================================================================== class Window_ChangeResult < Window_Base #-------------------------------------------------------------------------- # ● オブジェクト初期化 # name : アイテム変化に使うアイテムの名前 #-------------------------------------------------------------------------- def initialize(name) super(164, 176, 312, 128) self.contents = Bitmap.new(width - 32, height - 32) # z 座標は Window_Message と同じ値(一番手前) self.z = 5000 self.visible = false @item = nil @name = name refresh end #-------------------------------------------------------------------------- # ● アイテム取得 #-------------------------------------------------------------------------- def set_item(item) @item = item refresh end #-------------------------------------------------------------------------- # ● リフレッシュ #-------------------------------------------------------------------------- def refresh self.visible = false # @item が nil だったらここまで return if @item == nil self.contents.clear self.visible = true # @item が Miss では無い場合(アイテム変化が成功した場合) if @item != "Miss" # テキスト表示 self.contents.draw_text(0, 0, 280, 32, @name + "を使った結果", 0) # アイテムアイコン表示 bitmap = RPG::Cache.icon(@item.icon_name) self.contents.blt(20, 36, bitmap, Rect.new(0, 0, 24, 24), 255) self.contents.draw_text(48, 32, 212, 32, @item.name, 0) self.contents.draw_text(0, 64, 280, 32, "に変化しました。", 2) # アイテム変化を失敗した場合 else text = "何も起きませんでした。" self.contents.draw_text(0, 32, 280, 32, text, 1) end end end #============================================================================== # ■ Scene_Item #============================================================================== class Scene_Item #-------------------------------------------------------------------------- # ○ フレーム更新 #-------------------------------------------------------------------------- alias change_item_update update def update # 未鑑定アイテムウィンドウがアクティブの場合: update_unjudge を呼ぶ if @change_window != nil # ウィンドウを更新 @help_window.update @change_window.update @result_window.update if @result_window.visible == true update_change_result return end update_change_item return end # 呼び戻し change_item_update end #-------------------------------------------------------------------------- # ○ フレーム更新 (アイテムウィンドウがアクティブの場合) #-------------------------------------------------------------------------- alias change_item_update_item update_item def update_item # C ボタンが押された場合 + 変化アイテムの場合 if @item_window.item.is_a?(RPG::Item) and include_element?(@item_window.item.element_set, Annex::CHANGE_ITEM_ELEMENT) if Input.trigger?(Input::C) # アイテムウィンドウで現在選択されているデータを取得 @item = @item_window.item # 使用できない場合 unless $game_party.item_can_use?(@item.id) # ブザー SE を演奏 $game_system.se_play($data_system.buzzer_se) return end # 変化ウィンドウの設定 @change_window = Window_Changable_Item.new @change_window.help_window = @help_window @result_window = Window_ChangeResult.new(@item.name) # 決定 SE を演奏 $game_system.se_play($data_system.decision_se) @item_window.active = false # インデックスの調整 @change_window.index = 0 return end end # 呼び戻し change_item_update_item end #-------------------------------------------------------------------------- # ◎ 追加:フレーム更新 (アイテム変化ウィンドウがアクティブの場合) #-------------------------------------------------------------------------- def update_change_item # B ボタンが押された場合 if Input.trigger?(Input::B) # キャンセル SE を演奏 $game_system.se_play($data_system.cancel_se) # アイテム変化終了 end_change_item return end # C ボタンが押された場合 if Input.trigger?(Input::C) # 現在選択されているデータを取得 old_item = @change_window.item # 鑑定後のアイテムを取得 new_item = @change_window.item_can_change?(old_item) # number = 鑑定後のアイテムを既にいくつもっているか case new_item[0] # 鑑定不可 when 0 number = 0 # 道具変化 when "i" number = $game_party.item_number(new_item[1]) # 武器変化 when "w" number = $game_party.weapon_number(new_item[1]) # 防具変化 when "a" number = $game_party.armor_number(new_item[1]) end # 全てのアイテムに強制的に変化アイテムを適用できない場合 if (not Annex::CAN_USE_CHANGE_ALL) and new_item[0] == 0 # ブザー SE を演奏 $game_system.se_play($data_system.buzzer_se) return end # 鑑定アイテムが消耗品の場合 if @item.consumable # 鑑定に使用したアイテムを消費 $game_party.lose_item(@item.id, 1) end # ウェイトカウントをとりあえず設定しておく @change_wait_count = 50 # 変化後に得られるはずのアイテムが所持限界を超えている場合 if number == 99 # 変化後のアイテムを[0, 0](変化不可能) に変更 new_item = [0, 0] end # 変化失敗の場合 if new_item[0] == 0 # 変化失敗 SE を演奏 if Annex::CHANGE_FAILURE_SE != nil s = Annex::CHANGE_FAILURE_SE if s[0] != "" Audio.se_play("Audio/SE/" + s[0], s[1], s[2]) end end @change_window.active = false # 変化失敗の旨を表示する @result_window.set_item("Miss") return end # 変換に成功した場合 # 鑑定 SE を演奏 if Annex::CHANGE_SUCCESS_SE != nil s = Annex::CHANGE_SUCCESS_SE if s[0] != "" Audio.se_play("Audio/SE/" + s[0], s[1], s[2]) end end # 変化後のアイテムを入手、new_itemにアイテムのデータを格納 case new_item[0] when "i" $game_party.gain_item(new_item[1], 1) new_item = $data_items[new_item[1]] when "w" $game_party.gain_weapon(new_item[1], 1) new_item = $data_weapons[new_item[1]] when "a" $game_party.gain_armor(new_item[1], 1) new_item = $data_armors[new_item[1]] end # 変化前のアイテムを消費する case old_item when RPG::Item $game_party.lose_item(old_item.id, 1) when RPG::Weapon $game_party.lose_weapon(old_item.id, 1) when RPG::Armor $game_party.lose_armor(old_item.id, 1) end # 変化アイテムウィンドウの再描画 @change_window.refresh @change_window.active = false # 鑑定結果のアイテムを表示する @result_window.set_item(new_item) end end #-------------------------------------------------------------------------- # ◎ 追加:フレーム更新 (変化結果ウィンドウが表示状態の場合) #-------------------------------------------------------------------------- def update_change_result # ウェイトカウントの減算 @change_wait_count -= 1 # 最初の 10 フレームは 操作を受け付けない return if @change_wait_count > 30 # C ボタンが押された場合 or ウェイトカウントが 0 (50フレーム経過)の場合 if Input.trigger?(Input::C) or @change_wait_count == 0 # 決定 SE を演奏 $game_system.se_play($data_system.decision_se) # リザルトウィンドウの消去 @result_window.visible = false # 鑑定アイテムが残っている場合は続行 if $game_party.item_number(@item.id) > 0 @change_window.active = true return end # 残っていない場合は終了 end_change_item return end if Input.trigger?(Input::B) # キャンセル SE を演奏 $game_system.se_play($data_system.cancel_se) # アイテム変化終了 end_change_item return end end #-------------------------------------------------------------------------- # ◎ 追加:アイテム変化処理の終了 #-------------------------------------------------------------------------- def end_change_item # ウィンドウを解放 @change_window.dispose @change_window = nil @result_window.dispose @result_window = nil # アイテムウィンドウの再描画 @item_window.refresh @item_window.active = true end #-------------------------------------------------------------------------- # ◎ 追加:任意の属性配列に指定した属性名が含まれているか # element_set : 属性テーブル # name : 属性名 #-------------------------------------------------------------------------- def include_element?(element_set, name) return element_set.include?($data_system.elements.index(name)) end end