【脚本】事件计时器

范例工程 http://pan.baidu.com/s/1qWkWV7Y (范例中的脚本为包含BUG的旧版本)

=begin
===============================================================================
  事件计时器 By喵呜喵5
===============================================================================

【说明】

  随着时间的推移自动操作开关、独立开关、变量

  利用本脚本可以实现类似种菜这样的效果


  在事件指令的脚本中,输入以下代码来使用本脚本:

    m5_20151117_set_time(计时器的设置)

  计时器的设置使用如下格式:

    {
      设置的属性1: 属性1的值,
      设置的属性2: 属性2的值,
      设置的属性n: 属性n的值,
    }

    ※ 前后的中括号是必须的,每条属性名后面的英文冒号是必须的
    ※ 冒号和属性的值之间请加上空格,不要忘记每条设置最后的英文逗号
    ※ 为了防止脚本太长被编辑器强制修改,请手动在每条属性后换行

  需要设置的属性如下:

    类型    设置为 '地图' 时,计时器仅在主角处于本地图时才会继续计时
            默认值为 '全局'
            前后需要加上英文引号

    操作    设置计时器时间到以后要执行的指令,可以使用的值为:
            '变量' '开关' '独立开关'
            前后需要加上英文引号

    时间    设置计时器的倒计时时间(帧),
            当时间到了以后,将执行上面设置的操作

    ===========================================================================

    ※ 当操作部分设置为'变量'时:


    变量ID  设置计时器归零后要操作的变量ID

    变量值  设置计时器归零后,对应ID变量的值

    ===========================================================================

    ※ 当操作部分设置为'开关'时:

    开关ID  设置计时器归零后要操作的开关ID

    开关值  设置计时器归零后,对应开关的状态
            true 表示开关开启, false 表示开关关闭
            默认为 true

    ===========================================================================

    ※ 当操作部分设置为'独立开关'时:

    地图ID  设置计时器归零后要操作独立开关的事件所在的地图
            默认为当前地图

    事件ID  设置计时器归零后要操作独立开关的事件的事件ID
            默认为当前事件

    开关ID  设置计时器归零后要操作的独立开关
            可以使用的值分别是:'A' 'B' 'C' 'D'
            前后需要加上英文引号

    开关值  设置计时器归零后,对应独立开关的状态
            true 表示开关开启, false 表示开关关闭
            默认为 true

    ※ 虽然上一版中操作独立开关的设置方式仍然可以使用,但是个人建议尽快更新
    ※ 旧版脚本的操作方式预计将在未来的某个版本中被移除

    ===========================================================================

    指针    设置一个储存当前事件指针的 变量ID 用于结束该计时器
            不需要的话,不去设置即可
            关于结束计时器计时的方法请参考下方的说明


  结束某个计时器的计时:

    设置了指针属性的计时器可以提前结束计时

    例如,将某个计时器的指针属性设置为 1 时

    在计时器的计时过程中,执行指令:

      M5Timer20150824.clear(1)

    该计时器便会被删除

    执行指令:

      M5Timer20150824.start(1)

    该计时器的时间便会立刻归零

    请注意,这里设置的指针 1 表示数据被保存到了 1 号变量中,

    若之后修改了 1 号变量的值,执行结束计时器指令时将会发生错误,其他值亦同

=end
$m5script ||= {};$m5script[:M5Timer20150824] = 20170210
module M5Timer20150824
#==============================================================================
#  设定部分
#==============================================================================

  SWI = 0

  # 对应ID的开关打开时,计时器暂停

  SCENE_LIST = [Scene_Map, Scene_Battle]

  # 设置要让时间流逝的场景
  #
  # 默认的设置里,除了地图场景和战斗场景外,在其他场景中(例如打开菜单时),
  # 计时器会暂停计时

#==============================================================================
#  设定结束
#==============================================================================
class << self
  def update; $game_timer.m5timer20150824.update; end
  def start *args; $game_timer.m5timer20150824.start *args; end
  def clear *args; $game_timer.m5timer20150824.clear *args; end
  def add *args; $game_timer.m5timer20150824.add *args; end
  def refresh_scene; $game_timer.m5timer20150824.refresh_scene; end
end
class Timer
  def collect_event_id(id)
    value = $game_variables[id]
    return [] unless value.is_a? Array
    return [] unless value[0] == :m5_20151117
    ev_id = value[1]
    return [] unless @event_list[ev_id].object_id == value[2]
    [ev_id]
  end
  def start(id)
    operate_event(collect_event_id(id), true, true)
  end
  def clear(id)
    operate_event(collect_event_id(id), false, true)
  end
  def initialize
    @scene = false
    clear_all
  end
  def clear_all
    @map_timeline = []
    @global_timeline = []
    @event_list = []
    @timeline_list = []
  end
  def add_event(value)
    ev_id = @event_list.index(nil) || @event_list.size
    @event_list[ev_id] = value
    return ev_id
  end
  def add_timeline(ev_id, time_id)
    if !time_id
      time_id = @timeline_list.index(nil) || @timeline_list.size
      @timeline_list[time_id] = []
    end
    @timeline_list[time_id] << ev_id
    return time_id
  end
  def add(global, time, event)
    timeline = global ? @global_timeline : @map_timeline[event[:_MAP]]
    timeline ||= []
    ev_id = add_event(event)
    time_id = add_timeline(ev_id, timeline[time])
    event[:_TIME] = timeline[time] = time_id
    if event[:指针]
      $game_variables[event[:指针]] = [:m5_20151117, ev_id, event.object_id]
    end
  end
  def operate_timeline(time_id)
    index_list = @timeline_list[time_id]
    operate_event(index_list, true)
    @timeline_list[time_id] = nil
  end
  def operate_event(index_list, start, update_timeline = false)
    index_list.each do |ev_id|
      next unless @event_list[ev_id]
      if update_timeline
        time_id = @event_list[ev_id][:_TIME]
        @timeline_list[time_id].delete(ev_id)
      end
      start ? start_event(ev_id) : clear_event(ev_id)
    end
  end
  def clear_event(index)
    @event_list[index] = nil
  end
  def refresh_scene
    scene = SceneManager.scene.class
    SCENE_LIST.each {|s| return (@scene = true) if s == scene }
    @scene = false
  end
  def update
    return unless @scene
    return if $game_switches[SWI]
    update_list @map_timeline[$game_map.map_id]
    update_list @global_timeline
  end
  def update_list(list)
    return unless list
    time_id = list.shift
    return unless time_id
    operate_timeline(time_id)
  end
  def start_event(index)
    event = @event_list[index]
    return unless event
    case event[:操作]
    when "变量" then operate_variable(event)
    when "开关" then operate_switches(event)
    when "脚本" then operate_script(event)
    when "独立开关" then operate_self_switches(event)
    end
    $game_variables[event[:指针]] = 0 if event[:指针]
    clear_event(index)
  end
  def operate_variable(event)
    $game_variables[event[:变量ID]] = event[:变量值]
  end
  def operate_switches(event)
    $game_switches[event[:开关ID]] = event[:开关值]
  end
  def operate_self_switches(event)
    key = [event[:地图ID], event[:事件ID], event[:开关ID]]
    $game_self_switches[key] = event[:开关值]
  end
  def operate_script(event)
    eval(event[:代码])
  end
end
end # M5Timer20150824

class Game_Timer
  attr_reader :m5timer20150824
  alias m5_20151117_initialize initialize
  def initialize
    m5_20151117_initialize
    @m5timer20150824 = M5Timer20150824::Timer.new
  end
end
class << Graphics
  alias m5_20150824_update update
  def update; m5_20150824_update; M5Timer20150824.update; end
end
class Game_Interpreter
  def m5_20151117_set_time(param)
    event = {
      :类型 => '全局',    :_MAP => @map_id,
      :地图ID => @map_id, :事件ID => @event_id, :开关值 => true,
    }
    event.merge!(param)
    global = event[:类型] == '全局'
    time = event[:时间] || (raise '未设置计时器时间!')
    event[:操作] || (raise '未设置操作类型!')
    case event[:操作]
    when '变量'
      raise '未设置变量ID!' unless event[:变量ID]
      raise '未设置变量值!' unless event[:变量值]
    when '开关', '独立开关'
      raise '未设置开关ID!' unless event[:开关ID]
    end
    M5Timer20150824.add(global, time, event)
  end
  def m5_20150912_set_time *args
    args = [@map_id, @event_id].concat args if args[0].is_a?(String)
    args.insert(3,true) if args[3].is_a?(Numeric)
    args[5] = "A" unless args.size == 6
    type = args[5] == "A" ? '全局' : '地图'
    event = {
      :地图ID => args[0],  :事件ID => args[1], :类型 => type,
      :操作 => '独立开关', :开关ID => args[2], :开关值 => args[3],
      :时间 => args[4]
    }
    m5_20151117_set_time(event)
  end
end
class Scene_Base
  alias m5_20170210_start start
  def start
    M5Timer20150824.refresh_scene
    m5_20170210_start
  end
end

发表评论

电子邮件地址不会被公开。 必填项已用*标注