#============================================================================= # 队伍系统 Ver 2.1 #----------------------------------------------------------------------------- # 类似于 Aveyond 的队伍系统(根据阿月系列的游戏产生的灵感) # By :RyanBern #----------------------------------------------------------------------------- # 功能特色: #----------------------------------------------------------------------------- # 1.更改队伍中成员的最大数量,有四名出战队员,但是替补队员可以有很多个。 # 2.对 Game_Party 的队员设置和 Scene_Battle 的部分方法有较大改动,可能造成脚本 # 冲突。 # 3.为队伍增加“领队”角色,作为“领队”的成员在地图上显示他的图形。 # 4.在战斗命令中增添“换人”命令,可以将替补队员换上场。 # 5.如果队伍的出战队员全部阵亡,则直接判定玩家全灭,不管有无替补队员。但是如果 # 在地图上,则是所有队员阵亡才会被判定全灭。 # 6.事件编译器中,对全体同伴的处理均包括对替补队员的处理。 # 7.(Ver 2.1)战斗中可以设置自动替换阵亡队员,自动替换的时机为所有该行动的成员 # 行动完毕之后。注意,如果某个队员的行动本来就是“换人”,不过他在回合开始后 # 才阵亡,那么他本轮的替换指令将作废。 #----------------------------------------------------------------------------- # 使用方法: #----------------------------------------------------------------------------- # 1.粘贴到默认脚本后面,Main组前面即可。 # 2.在菜单中,左侧窗口被激活时,按 A 键可以改变领队(leader)的设置,按 S 键 # 可以改变出战的队员。 # 3.为队员设置“无法出战”的状态,即该队员不能被设置为出战队员。具体方法是 # 使用事件脚本,例如,让 1 号角色无法出战: # $game_actors[1].battle_disabled = true # 让 1 号角色恢复可以出战的状态: # $game_actors[1].battle_disabled = false # ### # 4.可在下方设置替补队员在战斗胜利之后是否获得 EXP 奖励。 #----------------------------------------------------------------------------- # 更新记录: # 2015.04.22 : 重构脚本,增加战斗换人功能。 # 2015.10.09 : 增加阵亡队员自动替换替补队员的功能。 #============================================================================= module RB end module RB::Party # “换人”命令的术语 Words_Swap = "换人" # 替补队员是否能在战斗胜利后获得 EXP 奖励,设置为 true 时可以获得奖励,设置 # 为 false 时则不能。 Get_Exp_Reserve = false # 角色阵亡时,是否自动切换替补队员,设置为 true 则开启此功能。 Auto_Swap = false end class Game_Temp attr_accessor :gain_exp_flag end class Game_Party attr_reader :battle_actors alias old_ini initialize def initialize @leader_id = 0 @battle_actors = [] old_ini end def leader return @leader_id == 0 ? nil : $game_actors[@leader_id] end def set_leader(actor_id) @leader_id = actor_id $game_player.refresh $game_map.need_refresh = true end def actors all_flag = !$game_temp.in_battle || (RB::Party::Get_Exp_Reserve && $game_temp.gain_exp_flag) return all_flag ? @actors : @battle_actors end def all_actors return @actors end def reserved_actors return @actors - @battle_actors end #-------------------------------------------------------------------------- # ● 加入同伴 # actor_id : 角色 ID #-------------------------------------------------------------------------- def add_actor(actor_id) # 获取角色 actor = $game_actors[actor_id] # 同伴人数未满 4 人、本角色不在队伍中的情况下 unless @actors.include?(actor) # 添加角色 @actors.push(actor) @battle_actors.push(actor) if @battle_actors.size < 4 self.set_leader(actor.id) if self.leader.nil? # 还原主角 $game_player.refresh end end #-------------------------------------------------------------------------- # ● 角色离开 # actor_id : 角色 ID #-------------------------------------------------------------------------- def remove_actor(actor_id) actor = $game_actors[actor_id] # 删除角色 @actors.delete(actor) @battle_actors.delete(actor) self.set_leader(self.actors[0].id) if self.leader == actor # 还原主角 $game_player.refresh end #-------------------------------------------------------------------------- # ● 设置初期同伴 #-------------------------------------------------------------------------- def setup_starting_members @actors = [] @battle_actors = [] for i in $data_system.party_members @actors.push($game_actors[i]) @battle_actors.push($game_actors[i]) if @battle_actors.size < 4 end self.set_leader(@actors[0].id) unless @actors.empty? end #-------------------------------------------------------------------------- # ● 设置战斗测试用同伴 #-------------------------------------------------------------------------- def setup_battle_test_members @actors = [] @battle_actors = [] for battler in $data_system.test_battlers actor = $game_actors[battler.actor_id] actor.level = battler.level gain_weapon(battler.weapon_id, 1) gain_armor(battler.armor1_id, 1) gain_armor(battler.armor2_id, 1) gain_armor(battler.armor3_id, 1) gain_armor(battler.armor4_id, 1) actor.equip(0, battler.weapon_id) actor.equip(1, battler.armor1_id) actor.equip(2, battler.armor2_id) actor.equip(3, battler.armor3_id) actor.equip(4, battler.armor4_id) actor.recover_all @actors.push(actor) @battle_actors.push(actor) end @items = {} for i in 1...$data_items.size if $data_items[i].name != "" occasion = $data_items[i].occasion if occasion == 0 or occasion == 1 @items[i] = 99 end end end end #-------------------------------------------------------------------------- # ● 同伴成员的还原 #-------------------------------------------------------------------------- def refresh # 游戏数据载入后角色对像直接从 $game_actors # 分离。 # 回避由于载入造成的角色再设置的问题。 new_actors = [] new_battle_actors = [] @actors.each do |actor| if $data_actors[actor.id] != nil new_actors.push($game_actors[actor.id]) end end @battle_actors.each do |actor| if $data_actors[actor.id] != nil new_battle_actors.push($game_actors[actor.id]) end end @actors = new_actors @battle_actors = new_battle_actors end #-------------------------------------------------------------------------- # ● 全灭判定 #-------------------------------------------------------------------------- def all_dead? # 同伴人数为 0 的情况下 if self.actors.size == 0 return false end # 同伴中无人 HP 在 0 以上 for actor in self.actors if actor.hp > 0 return false end end # 全灭 return true end #-------------------------------------------------------------------------- # ● 对像角色的随机确定 # hp0 : 限制为 HP 0 的角色 #-------------------------------------------------------------------------- def random_target_actor(hp0 = false) # 初始化轮流 roulette = [] # 循环 for actor in @battle_actors # 符合条件的场合 if (not hp0 and actor.exist?) or (hp0 and actor.hp0?) # 获取角色职业的位置 [位置] position = $data_classes[actor.class_id].position # 前卫的话 n = 4、中卫的话 n = 3、后卫的话 n = 2 n = 4 - position # 添加角色的轮流 n 回 n.times do roulette.push(actor) end end end # 轮流大小为 0 的情况 if roulette.size == 0 return nil end # 转轮盘赌,决定角色 return roulette[rand(roulette.size)] end #-------------------------------------------------------------------------- # ● 对像角色的顺序确定 # actor_index : 角色索引 #-------------------------------------------------------------------------- def smooth_target_actor(actor_index) # 取得对像 actor = @battle_actors[actor_index] # 对像存在的情况下 if actor != nil and actor.exist? return actor end # 循环 for actor in @actors # 对像存在的情况下 if actor.exist? return actor end end end end class Game_Actor attr_reader :battle_disabled def leader? return self == $game_party.leader end def active return $game_party.battle_actors.include?(self) end def battle_disabled=(bool) @battle_disabled = bool $game_party.battle_actors.delete(self) if bool end end class Game_Player #-------------------------------------------------------------------------- # ● 刷新 #-------------------------------------------------------------------------- def refresh # 同伴人数为 0 的情况下 if $game_party.actors.size == 0 or $game_party.leader == nil # 清除角色的文件名及对像 @character_name = "" @character_hue = 0 # 分支结束 return end # 获取带头的角色 if $game_party.leader != nil actor = $game_party.leader # 设置角色的文件名及对像 @character_name = actor.character_name @character_hue = actor.character_hue # 初始化不透明度和合成方式子 @opacity = 255 @blend_type = 0 end end end class Game_BattleAction attr_accessor :reserved_actor_id unless method_defined? :rb_clear_20150422 alias rb_clear_20150422 clear def clear rb_clear_20150422 @reserved_actor_id = 0 end end end class Window_Base < Window def draw_actor_battle_position(actor, x, y) if actor.leader? if actor.active text = "领队|出战" else text = "领队" end color = knockout_color else color = disabled_color if actor.battle_disabled text = "无法出战" elsif actor.active text = "出战" color = normal_color else text = "待机" end end self.contents.font.color = color self.contents.draw_text(x, y, 120, 32, text) end end #============================================================================== # ■ Window_Selectable #------------------------------------------------------------------------------ # 拥有光标的移动以及滚动功能的窗口类。 #============================================================================== class Window_Selectable < Window_Base #-------------------------------------------------------------------------- # ● 定义实例变量 #-------------------------------------------------------------------------- attr_accessor :row_height # 行高 #-------------------------------------------------------------------------- # ● 初始画对像 # x : 窗口的 X 坐标 # y : 窗口的 Y 坐标 # width : 窗口的宽 # height : 窗口的高 # row_height : 行高 默认是32 #-------------------------------------------------------------------------- alias rb_initialize_20150421 initialize def initialize(x, y, width, height, row_height = 32) @row_height = row_height rb_initialize_20150421(x, y, width, height) end #-------------------------------------------------------------------------- # ● 获取开头行 #-------------------------------------------------------------------------- def top_row # 将窗口内容的传送源 Y 坐标、1 行的高 @row_height 等分 return self.oy / @row_height end #-------------------------------------------------------------------------- # ● 设置开头行 # row : 显示开头的行 #-------------------------------------------------------------------------- def top_row=(row) # row 未满 0 的场合更正为 0 if row < 0 row = 0 end # row 超过 row_max - 1 的情况下更正为 row_max - 1 if row > row_max - 1 row = row_max - 1 end # row 1 行高的 @row_height 倍、窗口内容的传送源 Y 坐标 self.oy = row * @row_height end #-------------------------------------------------------------------------- # ● 获取 1 页可以显示的行数 #-------------------------------------------------------------------------- def page_row_max # 窗口的高度,设置画面的高度减去 32 ,除以 1 行的高度 @row_height return (self.height - 32) / @row_height end #-------------------------------------------------------------------------- # ● 更新光标举行 #-------------------------------------------------------------------------- def update_cursor_rect # 光标位置不满 0 的情况下 if @index < 0 self.cursor_rect.empty return end # 获取当前的行 row = @index / @column_max # 当前行被显示开头行前面的情况下 if row < self.top_row # 从当前行向开头行滚动 self.top_row = row end # 当前行被显示末尾行之后的情况下 if row > self.top_row + (self.page_row_max - 1) # 从当前行向末尾滚动 self.top_row = row - (self.page_row_max - 1) end # 计算光标的宽 cursor_width = self.width / @column_max - 32 # 计算光标坐标 x = @index % @column_max * (cursor_width + 32) y = @index / @column_max * @row_height - self.oy # 更新国标矩形 self.cursor_rect.set(x, y, cursor_width, @row_height) end end class Window_MenuStatus def initialize super(0, 0, 480, 480, 112) refresh self.active = false self.index = -1 end def refresh if self.contents != nil self.contents.dispose self.contents = nil end @item_max = $game_party.actors.size self.contents = Bitmap.new(width - 32, @item_max == 0 ? 32 : @item_max * 112) for i in 0...$game_party.actors.size x = 64 y = i * 112 actor = $game_party.actors[i] draw_actor_graphic(actor, x - 40, y + 80) draw_actor_name(actor, x, y) draw_actor_class(actor, x + 144, y) draw_actor_level(actor, x, y + 32) draw_actor_state(actor, x + 90, y + 32) draw_actor_exp(actor, x, y + 64) draw_actor_hp(actor, x + 236, y + 32) draw_actor_sp(actor, x + 236, y + 64) draw_actor_battle_position(actor, x + 236, y) end end def update_cursor_rect super end end class Window_Target def initialize super(0, 0, 336, 480, 112) self.z += 10 @item_max = $game_party.actors.size self.contents = Bitmap.new(width - 32, @item_max == 0 ? 32 : @item_max * 112) refresh end def update_cursor_rect super end end class Window_ReservedActors < Window_Selectable def initialize super(0, 64, 640, 256, 112) self.opacity = 160 self.index = 0 self.active = true @column_max = 2 refresh end def actor return @data[self.index] end def refresh if self.contents != nil self.contents.dispose self.contents = nil end @data = [] $game_party.all_actors.each do |actor| @data << actor unless actor.active || actor.battle_disabled end @item_max = @data.size if @item_max > 0 self.contents = Bitmap.new (width - 32, (@item_max + 1) / 2 * 128) @data.each_with_index do |actor, index| x = 4 + index % 2 * (288 + 32) y = index / 2 * 112 draw_actor_graphic(actor, x + 16, y + 80) draw_actor_hp(actor, x + 48, y + 20) draw_actor_sp(actor, x + 48, y + 52) end end end def update_help # 帮助窗口显示角色的状态 self.actor == nil ? @help_window.set_text("") : @help_window.set_actor(self.actor) end end class Scene_Menu unless method_defined? :rb_update_command_20150421 alias rb_update_command_20150421 update_command def update_command if Input.trigger?(Input::X) $game_system.se_play($data_system.decision_se) @command_window.active = false @status_window.active = true @status_window.index = 0 @leader_adjust = true return end if Input.trigger?(Input::Y) $game_system.se_play($data_system.decision_se) @command_window.active = false @status_window.active = true @status_window.index = 0 @battler_adjust = true return end rb_update_command_20150421 end end unless method_defined? :rb_update_status_20150421 alias rb_update_status_20150421 update_status def update_status if @leader_adjust update_leader return end if @battler_adjust update_battler return end rb_update_status_20150421 end end def update_leader if Input.trigger?(Input::B) $game_system.se_play($data_system.cancel_se) @leader_adjust = false @status_window.active = false @status_window.index = -1 @command_window.active = true return end if Input.trigger?(Input::C) if $game_party.actors.size == 0 $game_system.se_play($data_system.buzzer_se) else $game_system.se_play($data_system.decision_se) $game_party.set_leader($game_party.actors[@status_window.index].id) @status_window.refresh end end end def update_battler if Input.trigger?(Input::B) $game_system.se_play($data_system.cancel_se) @battler_adjust = false @status_window.active = false @status_window.index = -1 @command_window.active = true return end if Input.trigger?(Input::C) actor = $game_party.actors[@status_window.index] if actor == nil || actor.battle_disabled || (actor.active && $game_party.battle_actors.size == 1) || (!actor.active && $game_party.battle_actors.size == 4) $game_system.se_play($data_system.buzzer_se) else $game_system.se_play($data_system.decision_se) actor.active ? $game_party.battle_actors.delete(actor) : $game_party.battle_actors.push(actor) @status_window.refresh end end end end class Scene_Battle def generate_modified_command_window if @actor_command_window != nil @actor_command_window.dispose @actor_command_window = nil end s1 = $data_system.words.attack s2 = $data_system.words.skill s3 = $data_system.words.guard s4 = $data_system.words.item s5 = RB::Party::Words_Swap @actor_command_window = Window_Command.new(160, [s1, s2, s3, s4, s5]) @actor_command_window.y = 128 @actor_command_window.back_opacity = 160 @actor_command_window.active = false @actor_command_window.visible = false @modified_generated = true end unless method_defined? :rb_phase3_setup_command_window_20150422 alias rb_phase3_setup_command_window_20150422 phase3_setup_command_window def phase3_setup_command_window generate_modified_command_window unless @modified_generated rb_phase3_setup_command_window_20150422 end end def make_auto_swap_actors return unless RB::Party::Auto_Swap available_actors = $game_party.reserved_actors.reject{|actor| actor.dead?} dead_actors = $game_party.battle_actors.select{|actor| actor.dead?} return if available_actors.empty? || dead_actors.empty? n = [available_actors.size, dead_actors.size].min dead_actors.each_with_index do |actor, i| break if i >= n actor.current_action.kind = 3 actor.current_action.reserved_actor_id = available_actors[i].id @action_battlers << actor end end def update_phase3_basic_command # 按下 B 键的情况下 if Input.trigger?(Input::B) # 演奏取消 SE $game_system.se_play($data_system.cancel_se) # 转向前一个角色的指令输入 phase3_prior_actor return end # 按下 C 键的情况下 if Input.trigger?(Input::C) # 角色指令窗口光标位置分之 case @actor_command_window.index when 0 # 攻击 # 演奏确定 SE $game_system.se_play($data_system.decision_se) # 设置行动 @active_battler.current_action.kind = 0 @active_battler.current_action.basic = 0 # 开始选择敌人 start_enemy_select when 1 # 特技 # 演奏确定 SE $game_system.se_play($data_system.decision_se) # 设置行动 @active_battler.current_action.kind = 1 # 开始选择特技 start_skill_select when 2 # 防御 # 演奏确定 SE $game_system.se_play($data_system.decision_se) # 设置行动 @active_battler.current_action.kind = 0 @active_battler.current_action.basic = 1 # 转向下一位角色的指令输入 phase3_next_actor when 3 # 物品 # 演奏确定 SE $game_system.se_play($data_system.decision_se) # 设置行动 @active_battler.current_action.kind = 2 # 开始选择物品 start_item_select when 4 # 换人 $game_system.se_play($data_system.decision_se) @active_battler.current_action.kind = 3 start_reserved_actor_select end return end end unless method_defined? :rb_update_phase3_20150422 alias rb_update_phase3_20150422 update_phase3 def update_phase3 if @actor_window != nil update_phase3_reserved_actor_select return end rb_update_phase3_20150422 end end def start_reserved_actor_select # 生成特技窗口 @actor_window = Window_ReservedActors.new # 关联帮助窗口 @actor_window.help_window = @help_window @help_window.visible = true # 无效化角色指令窗口 @actor_command_window.active = false @actor_command_window.visible = false end def end_reserved_actor_select # 释放特技窗口 @actor_window.dispose @actor_window = nil # 隐藏帮助窗口 @help_window.visible = false # 有效化角色指令窗口 @actor_command_window.active = true @actor_command_window.visible = true end def update_phase3_reserved_actor_select @actor_window.visible = true # 刷新特技窗口 @actor_window.update # 按下 B 键的情况下 if Input.trigger?(Input::B) # 演奏取消 SE $game_system.se_play($data_system.cancel_se) # 结束特技选择 end_reserved_actor_select return end # 按下 C 键的情况下 if Input.trigger?(Input::C) # 获取特技选择窗口现在选择的特技的数据 @reserved_actor = @actor_window.actor # 无法使用的情况下 if @reserved_actor == nil # 演奏冻结 SE $game_system.se_play($data_system.buzzer_se) return end # 演奏确定 SE $game_system.se_play($data_system.decision_se) # 设置行动 @active_battler.current_action.reserved_actor_id = @reserved_actor.id # 设置特技窗口为不可见状态 @actor_window.visible = false end_reserved_actor_select phase3_next_actor return end end def update_phase4_step1 # 隐藏帮助窗口 @help_window.visible = false # 判定胜败 if judge # 胜利或者失败的情况下 : 过程结束 return end # 强制行动的战斗者不存在的情况下 if $game_temp.forcing_battler == nil # 设置战斗事件 setup_battle_event # 执行战斗事件中的情况下 if $game_system.battle_interpreter.running? return end end # 强制行动的战斗者存在的情况下 if $game_temp.forcing_battler != nil # 在头部添加后移动 @action_battlers.delete($game_temp.forcing_battler) @action_battlers.unshift($game_temp.forcing_battler) end # 未行动的战斗者不存在的情况下 (全员已经行动) if @action_battlers.size == 0 make_auto_swap_actors if @action_battlers.empty? @auto_swap = false # 开始同伴命令回合 start_phase2 return else @auto_swap = true end end # 初始化动画 ID 和公共事件 ID @animation1_id = 0 @animation2_id = 0 @common_event_id = 0 # 未行动的战斗者移动到序列的头部 @active_battler = @action_battlers.shift # 如果已经在战斗之外的情况下 if @active_battler.index == nil return end # 连续伤害 if @active_battler.hp > 0 and @active_battler.slip_damage? @active_battler.slip_damage_effect @active_battler.damage_pop = true end # 自然解除状态 @active_battler.remove_states_auto # 刷新状态窗口 @status_window.refresh # 移至步骤 2 @phase4_step = 2 end def update_phase4_step2 # 如果不是强制行动 unless @active_battler.current_action.forcing # 限制为 [敌人为普通攻击] 或 [我方为普通攻击] 的情况下 if @active_battler.restriction == 2 or @active_battler.restriction == 3 # 设置行动为攻击 @active_battler.current_action.kind = 0 @active_battler.current_action.basic = 0 end # 限制为 [不能行动] 的情况下 if @active_battler.restriction == 4 && !@auto_swap # 清除行动强制对像的战斗者 $game_temp.forcing_battler = nil # 移至步骤 1 @phase4_step = 1 return end end # 清除对像战斗者 @target_battlers = [] # 行动种类分支 case @active_battler.current_action.kind when 0 # 基本 make_basic_action_result when 1 # 特技 make_skill_action_result when 2 # 物品 make_item_action_result when 3 # 换人 make_swap_action_result end # 移至步骤 3 if @phase4_step == 2 @phase4_step = 3 end end def make_swap_action_result # 获取角色 @reserved_actor = $game_actors[@active_battler.current_action.reserved_actor_id] # 无法替换的情况下 if @reserved_actor == nil || @reserved_actor.active # 移至步骤 1 @phase4_step = 1 return end # 在帮助窗口显示文字 text = "与#{@reserved_actor.name}交换" @help_window.set_text(text, 1) # 设置动画 ID @animation1_id = 0 index = $game_party.actors.index(@active_battler) $game_party.actors[index] = @reserved_actor end unless method_defined? :rb_start_phase5_20150422 alias rb_start_phase5_20150422 start_phase5 def start_phase5 $game_temp.gain_exp_flag = true rb_start_phase5_20150422 $game_temp.gain_exp_flag = false end end end
300.53 KB, 下载次数: 47
欢迎光临 Project1 (https://rpg.blue/) | Powered by Discuz! X3.1 |