查看: 5443|回复: 6

[RMVA发布] 让RGSS3记住事件移动后的位置

[复制链接]
梦石
0
星屑
1580
在线时间
1564 小时
注册时间
2008-7-30
回帖
4207

贵宾

发表于 2014-7-26 18:53:06 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 DeathKing 于 2014-7-26 18:54 编辑
TL;DR
使用此脚本前,您应该阅读:自由脚本协议(Free Script License)
您也可以在GitHub上查看此脚本的最新版:1.1.0726版本
这里是参考范例工程: [FSL][1.1.0726]RememberWorld.rar (1.42 MB, 下载次数: 205)


RGSS3中存在什么问题?


RM系列一直存在这个问题。每次切换到新地图时,RGSS会重新从Map***.r*data文件中加载数据,重新设置地图(见Game_Map#setup_events),这样,有些执行过“设置事件位置”或者随机移动路线的事件就会再切换回地图时重新回到在编辑器中设定的位置。

这其实是很诡异的。我们希望RGSS3记住事件移动后的位置。

RememberWorld是如何解决这个问题的?

简而言之,给Scene_Map的pre_transfer加个钩子,添加我们的处理代码。基本思想是让RGSS3将当前地图中的事件的坐标存放在Game_System的一个实例变量中。然后再给Game_Map的setup_events加钩子,使得地图重新加载时,会从Game_System的那个实例变量中读取事件位置。这样就实现了事件位置的记录。

现在比较纠结的问题。

  • 除了坐标外,还有没有其它需要记录的东西?
  • 是否要同时提供白名单/黑名单特性?现在提供的是黑名单特性,也就是如果事件页的第一行是注释,而且注释的内容为<FSL::RememberWorld not-track>,那么脚本就不会跟踪记录这个事件。但是有可能你只需要记录少数几个事件,那么就希望脚本提供白名单的特性。考虑以后是不是要加上这个功能。

为什么有这个脚本?

正在做一个非常有趣的脚本,就需要这个功能的支撑。仓促之作,应该还会有许多没有考虑到的地方,希望大家多多提交BUG。



img1.png



img3.png



[fold=脚本]
[pre lang="ruby" line="1"]#===============================================================================
# ■ [VA] 记忆事件位置
#    [VA] RememberWorld
#-------------------------------------------------------------------------------
#    让RGSS3记住事件移动后的位置。
#   
#-------------------------------------------------------------------------------
#    更新作者: DeathKing
#    许可协议: FSL
#    项目版本: 1.1.0726
#    最后更新: 2014-07-26
#    引用网址:
#-------------------------------------------------------------------------------
#    能让RGSS3记忆住NPC的移动位置,避免出现地图切换后NPC又回到了初始位置的尴尬。
#
#    目前这个版本只是简单的记忆了事件的X、Y坐标,并写入Game_System的map_events中,  
#    事实上,可能还需要写入更多的信息,但是具体要写入什么,我正在探索中。
#-------------------------------------------------------------------------------
#    - 1.1.0726 By DeathKing
#      * 使用Game_System作为载体,避免对地图文件本身做出修改。
#
#    - 1.0.0725 By DeathKing
#      * 初始版本完成;
#
#===============================================================================
$fscript ||= {}
$fscript["RememberWorld"] = "1.1.0726"

#-------------------------------------------------------------------------------
# ▼ 登记FSL
#-------------------------------------------------------------------------------
module FSL
  module RememberWorld
   
    # 控制开关编号
    # 当 ENABLE_SWITCH 号开关打开时,此功能有效
    ENABLE_SWITCH = 21
   
    # 不要记录标记
    # 如果事件的当前事件页第一条指令为一个注释,而且包含有下面的字符串的话
    # 脚本那不记住事件位置。
    NOT_REMEMBER_MARK = "<FSL::RememberWorld not-track>"
   
  end
end

#==============================================================================
# ■ Game_System
#------------------------------------------------------------------------------
#  处理系统附属数据的类。保存存档和菜单的禁止状态之类的数据。
#   本类的实例请参考 $game_system 。
#==============================================================================

class Game_System
  #--------------------------------------------------------------------------
  # ● 开放map_events实例变量
  #--------------------------------------------------------------------------
  def map_events
    @map_events ||= {}
    @map_events
  end
end

#==============================================================================
# ■ Game_Event
#------------------------------------------------------------------------------
#  处理事件的类。拥有条件判断、事件页的切换、并行处理、执行事件等功能。
#   在 Game_Map 类的内部使用。
#==============================================================================
class Game_Event < Game_Character
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_reader   :event
end

#==============================================================================
# ■ Game_Map
#------------------------------------------------------------------------------
#  管理地图的类。拥有卷动地图以及判断通行度的功能。
#   本类的实例请参考 $game_map 。
#==============================================================================
class Game_Map
  
  include FSL::RememberWorld
  
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  def remember_world
    saved = {}
    if $game_switches[ENABLE_SWITCH]
      @events.each do |i, event|
        # 跳过那些指明不要记住的事件
        instruction = event.find_proper_page.list.first
        next if (instruction and
                 instruction.code == 108 and
                 instruction.parameters[0].include? NOT_REMEMBER_MARK)
        saved = [event.x, event.y]
      end
      $game_system.map_events[@map_id] = saved
    end
  end
  
  #--------------------------------------------------------------------------
  # ● 设置事件
  #--------------------------------------------------------------------------
  alias old_rm_setup_events setup_events
  def setup_events
    old_rm_setup_events
    if (events = $game_system.map_events[@map_id])
      events.each do |id, coordinate|
        @events[id].moveto(*coordinate)
      end
    end
  end
end

#==============================================================================
# ■ Scene_Map
#------------------------------------------------------------------------------
#  地图画面
#==============================================================================
class Scene_Map
  alias old_rw_pre_transfer pre_transfer
  #--------------------------------------------------------------------------
  # ● 场所移动前的处理
  #--------------------------------------------------------------------------
  def pre_transfer
    old_rw_pre_transfer
    $game_map.remember_world
  end
end
[/pre][/fold]

评分

参与人数 4星屑 +250 收起 理由
kuerlulu + 30 ↓
影月千秋 + 20 所谓撞车糖
satgo1546 + 100 ↓
taroxd + 100 卧槽竟然是DK菊苣!

查看全部评分


See FScript Here:https://github.com/DeathKing/fscript
潜心编写URG3中。
所有对URG3的疑问和勘误或者建议,请移步至发布页面。
欢迎萌妹纸催更
梦石
0
星屑
48
在线时间
312 小时
注册时间
2014-2-28
回帖
861
发表于 2014-7-26 19:17:58 | 显示全部楼层
LZ做的很棒!就是Bgm有点问题哈

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
由于我不服H·H·Y大触事件满于是他让我的事件也调满于是我照着做了结果那货居然把事件调低了……结果我现在原稿找不回来了只好保持着事件满的状态在大家面前闹笑话擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦擦
回复

使用道具 举报

运否天赋

梦石
10
星屑
5246
在线时间
3568 小时
注册时间
2014-5-15
回帖
1441

开拓者

发表于 2014-7-26 20:24:04 | 显示全部楼层
之前看过一个保存事件位置的脚本,内部切换黑/白名单
https://rpg.blue/thread-230430-1-1.html

点评

其实我也写过……在我那个经常和别人撞车的插件脚本合集里……  发表于 2014-7-26 21:26
不太知道……不过确实是撞了。  发表于 2014-7-26 21:17
土猫三国开发完成
回复

使用道具 举报

梦石
0
星屑
1580
在线时间
1564 小时
注册时间
2008-7-30
回帖
4207

贵宾

 楼主| 发表于 2014-7-26 22:02:22 | 显示全部楼层
喵kano 发表于 2014-7-26 20:24
之前看过一个保存事件位置的脚本,内部切换黑/白名单
https://rpg.blue/thread-230430-1-1.html ...

看了一下脚本 @feizhaodan 的是直接HOOK Game_Map#setup,在实际执行地图切换前记录事件位置,并直接让Game_Map来记录这些内容,某种程度上来说比我的脚本来得巧妙。

美中不足的是,需要将68行处,由:

[pre lang="ruby" line="68"]      e.direction( @event_pos[@map_id][2])[/pre]

修改为:

[pre lang="ruby" line="68"]      e.set_direction( @event_pos[@map_id][2])[/pre]

这样就能正确处理事件朝向的问题了。

其实我还要实现一个核功能,就是让这个地图的事件移动到另一个地图,并保持有效,这个比较棘手,也是我最想解决的。

点评

哇没发现囧 去修改  发表于 2014-7-27 23:21
保护环境的那个?  发表于 2014-7-26 23:33
事件挂在一个临时的列表上,当做移动语义移过去(好像是什么奇怪的东西)  发表于 2014-7-26 22:43

See FScript Here:https://github.com/DeathKing/fscript
潜心编写URG3中。
所有对URG3的疑问和勘误或者建议,请移步至发布页面。
欢迎萌妹纸催更
回复

使用道具 举报

菜鸟飞呀飞 该用户已被删除
发表于 2014-7-26 22:38:21 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

梦石
0
星屑
94
在线时间
648 小时
注册时间
2009-2-3
回帖
208
发表于 2014-7-28 02:11:14 | 显示全部楼层
希望能有xp版本
回复

使用道具 举报

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

发表于 2014-7-28 07:40:13 | 显示全部楼层
本帖最后由 taroxd 于 2014-7-28 07:44 编辑
DeathKing 发表于 2014-7-26 22:02
看了一下脚本 @feizhaodan 的是直接HOOK Game_Map#setup,在实际执行地图切换前记录事件位置,并直接让Ga ...


[pre lang="ruby" line="1"]

class Game_Map
  
  alias init_20140728 initialize
  def initialize
    init_20140728
    @moved_events   = {}
    @removed_events = {}
  end
  
  # default_proc 不能存档简直忧伤……
  def get_moved_events(map_id)
    @moved_events[map_id] ||= {}
  end
  
  def get_removed_events(map_id)
    @removed_events[map_id] ||= {}
  end

  def setup_events
    @events = {}
    @map.events.each do |i, event|
      unless get_removed_events(@map_id)
        @events = Game_Event.new(@map_id, event)
      end
    end
    get_moved_events(@map_id).each do |i, (x, y, direction, event)|
      @events = event = Game_Event.new(@map_id, event)
      event.moveto(x, y)
      event.set_direction(direction)
    end
    @common_events = parallel_common_events.collect do |common_event|
      Game_CommonEvent.new(common_event.id)
    end
    refresh_tile_events
  end
end

class Game_Event
  def moveto_new_map(map_id, x, y, direction = nil)
    if map_id == @map_id
      moveto(x, y)
      set_direction(direction) if direction
      return
    end
    $game_map.get_moved_events(@map_id).delete(@id)
    $game_map.get_removed_events(@map_id)[@id] = true
    new_map = load_data(sprintf("Data/Map%03d.rvdata2", map_id))
    size = new_map.width * new_map.height
    begin
      @event.id = @id = size + rand(0xffff) + @id # just a random number big enough
    end while $game_map.get_moved_events(map_id).key?(@id)
    $game_map.get_moved_events(map_id)[@id] =
      [x, y, (direction || @direction), @event]
    $game_map.get_removed_events(map_id).delete(@id)
  end
end[/pre]

一个不太完善的版本,仅仅提供一个思路。
有很多问题没有考虑到,比如从当前地图移动走的时候,事件仍然会停留在地图上。
比如独立开关的问题没有处理。

反正我也不需要这个功能,所以也没有太在意美观和可读性什么的。总之就是提供一个思路吧。这些小问题应该都不难解决的。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部