很早就想做这个队伍系统了,应该有人做过类似的,不过还是自己做一个分享一下吧。应该有一定的实用价值。
内容还不是很完善,有时间会改进的。
具体的说明全在代码里了,在新的RMXP工程中可以正常运行。
最近炒的第二顿冷饭,这个人物仓库系统重新写了一下。增添了战斗换人的若干内容,修复了一些BUG。
新功能没用做特别多,因为功能越多脚本冲突越大,你懂的。如果外挂脚本过多,很可能需要整合才可使用。
如果已经使用了旧脚本,则强烈建议用这个新版本的队伍系统。
2.0 版本使用方法依然在脚本当中,这次附上了范例。
测试次数较少,如果发现错误欢迎报告。
RUBY 代码
- #=============================================================================
- # 队伍系统 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
- moduleRB::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)ifself.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)ifself.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 in1...$data_items.size
- if$data_items[i].name != ""
- occasion = $data_items[i].occasion
- if occasion == 0or occasion == 1
- @items[i] = 99
- end
- end
- end
- end
- #--------------------------------------------------------------------------
- # ● 同伴成员的还原
- #--------------------------------------------------------------------------
- def refresh
- # 游戏数据载入后角色对像直接从 $game_actors
- # 分离。
- # 回避由于载入造成的角色再设置的问题。
- new_actors = []
- new_battle_actors = []
- @actors.eachdo |actor|
- if$data_actors[actor.id] != nil
- new_actors.push($game_actors[actor.id])
- end
- end
- @battle_actors.eachdo |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 的情况下
- ifself.actors.size == 0
- returnfalse
- end
- # 同伴中无人 HP 在 0 以上
- for actor inself.actors
- if actor.hp > 0
- returnfalse
- end
- end
- # 全灭
- returntrue
- 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.timesdo
- roulette.push(actor)
- end
- end
- end
- # 轮流大小为 0 的情况
- if roulette.size == 0
- returnnil
- end
- # 转轮盘赌,决定角色
- return roulette[rand(roulette.size)]
- end
- #--------------------------------------------------------------------------
- # ● 对像角色的顺序确定
- # actor_index : 角色索引
- #--------------------------------------------------------------------------
- def smooth_target_actor(actor_index)
- # 取得对像
- actor = @battle_actors[actor_index]
- # 对像存在的情况下
- if actor != niland 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?
- returnself == $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 == 0or$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 等分
- returnself.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
- ifself.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 in0...$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
- ifself.contents != nil
- self.contents.dispose
- self.contents = nil
- end
- @data = []
- $game_party.all_actors.eachdo |actor|
- @data 0
- self.contents = Bitmap.new(width - 32, (@item_max + 1) / 2 * 128)
- @data.each_with_indexdo |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
- returnunlessRB::Party::Auto_Swap
- available_actors = $game_party.reserved_actors.reject{|actor| actor.dead?}
- dead_actors = $game_party.battle_actors.select{|actor| actor.dead?}
- returnif available_actors.empty? || dead_actors.empty?
- n = [available_actors.size, dead_actors.size].min
- dead_actors.each_with_indexdo |actor, i|
- breakif i >= n
- actor.current_action.kind = 3
- actor.current_action.reserved_actor_id = available_actors[i].id
- @action_battlers 0and@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 == 2or@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
- when0 # 基本
- make_basic_action_result
- when1 # 特技
- make_skill_action_result
- when2 # 物品
- make_item_action_result
- when3 # 换人
- 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
复制代码
截图效果如下:
这个换人的效果比较短,只是角色闪了一下,人就换好了。目前正在改进当中。
附范例一枚:
本帖来自P1论坛作者李少安,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:
https://rpg.blue/forum.php?mod=viewthread&tid=332273 若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。