Project1

标题: 如何让游戏在按下红叉后不关闭?(已解决) [打印本页]

作者: 翠靈月    时间: 2017-10-24 23:25
标题: 如何让游戏在按下红叉后不关闭?(已解决)
本帖最后由 翠靈月 于 2017-10-26 00:32 编辑

确切的说,是希望在按下红叉后弹窗,按是关闭,按否继续游戏


自己用多功能 DLL SiNova v10015脚本瞎JB捣鼓弄出来的结果是:
1回到游戏后画面刷新卡成狗
2直接卡死
3用各种开关条件瞎搞一波自己也不懂的骚操作,回到游戏后暂时没问题,但是再按一次红叉就会立刻直接关闭

请各位大佬指点正确的使用姿势


作者: hyperzlib    时间: 2017-10-25 08:15
  1. window.onbeforeunload=function(){
  2.     return '你确定要关闭游戏吗?';
  3. };
复制代码

作者: guoxiaomi    时间: 2017-10-25 09:12
alias _old_exit exit
def exit
...
作者: 魔法丶小肉包    时间: 2017-10-25 12:29
先用黄鸡的脚本模板然后拿过来改一改
不过注意1点:
选择取消的时候(不退出游戏)你自己写,我这里只是强行来了遍rgss_main { SceneManager.run }而已(对这些不怎么了解所以这是目前想到的唯一方法,所以我只能改到这了)
RUBY 代码复制
  1. module MFXRB
  2. MessageBoxW            = Win32API.new('user32', 'MessageBoxW',            'lppl',   'l')  
  3.   def self.callMessageBoxW(hint, title, icon, button,hWnd = 0)
  4.     MessageBoxW.call(hWnd, hint.u2w, title.u2w, icon | button)
  5.   end
  6. end
  7. class String
  8.   def w2u
  9.     self.unpack("S*").pack("U*").sub(/\0+$/, '')
  10.   end
  11.   def u2w
  12.     self.unpack("U*").pack("S*") + "\0\0"
  13.   end
  14.   def f_e
  15.     self.force_encoding(__ENCODING__)
  16.   end
  17.  
  18.       def byte_length
  19.         ret = 0
  20.         self.each_byte{ret+=1}
  21.         ret
  22.       end
  23.  
  24.       def address
  25.         [self].pack("p").unpack("L")[0]
  26.       end
  27.  
  28.     end
  29.  
  30.     module Fux2
  31.  
  32.       module Win32Tools
  33.         RtlMoveMemoryLP = Win32API.new('kernel32','RtlMoveMemory','lpl','l')
  34.         RtlMoveMemoryPL = Win32API.new('kernel32','RtlMoveMemory','pll','l')
  35.         GetModuleHandle = Win32API.new('kernel32','GetModuleHandle','p','l')
  36.         VirtualProtect = Win32API.new('kernel32','VirtualProtect','lllp','l')
  37.  
  38.         def self.readmem(buf,addr,len)
  39.           RtlMoveMemoryPL.call(buf,addr,len)
  40.         end
  41.  
  42.         def self.writemem(addr,buf,len)
  43.           RtlMoveMemoryLP.call(addr,buf,len)
  44.         end
  45.  
  46.         def self.unprotect(addr,len)
  47.           VirtualProtect.call(addr,len,0x40,"\0"*4)
  48.         end
  49.  
  50.         def self.init
  51.           @@hModule = GetModuleHandle.call("RGSS300.dll")
  52.         end
  53.  
  54.         def self.module_handle
  55.           @@hModule
  56.         end
  57.  
  58.         init
  59.       end
  60.       module Exit_Hook
  61.  
  62.         @@hwnd = 0
  63.  
  64.         Addr_Close_Catch = Win32Tools.module_handle+0x17F396
  65.         Addr_Eval = Win32Tools.module_handle+0xC580
  66.         Addr_Hwnd = Win32Tools.module_handle+0x25EB00
  67.  
  68.         Code_Close_Catch = "\x90"*23
  69.  
  70.         Str_Close_Catch = "Fux2::Exit_Hook.exit_func"
  71.  
  72.         def self.unprotectfunc(func)
  73.           Fux2::Win32Tools.unprotect(func.address,func.byte_length)
  74.         end
  75.  
  76.         def self.unprotect_all
  77.           unprotectfunc(Code_Close_Catch)
  78.         end
  79.  
  80.         def self.hook_exit
  81.           cad = Code_Close_Catch.address
  82.           cal = Code_Close_Catch.byte_length
  83.           rem = "\0"*5
  84.           Fux2::Win32Tools.readmem(rem,Addr_Close_Catch,5)
  85.           rem = rem.unpack("C*")
  86.           retn_addr = Addr_Close_Catch+5-cad-cal
  87.           hook_addr = cad-Addr_Close_Catch-5
  88.           Fux2::Win32Tools.writemem(Addr_Close_Catch,[0xE9,hook_addr].pack("CL"),5)
  89.           eval_addr = Addr_Eval-cad-10
  90.           hook_code = [0x68,Str_Close_Catch.address,0xE8,eval_addr,0x83,0xC4,0x4,*rem,0xE9,retn_addr].pack("CLCLCCCCCCCCCL")
  91.           Fux2::Win32Tools.writemem(cad,hook_code,cal)
  92.         end
  93.  
  94.         def self.get_hwnd
  95.           rem = "\0"*4
  96.           Fux2::Win32Tools.readmem(rem,Addr_Hwnd,4)
  97.           base_addr = rem.unpack("L")[0]
  98.           Fux2::Win32Tools.readmem(rem,base_addr+8,4)
  99.           @@hwnd = rem.unpack("L")[0]
  100.         end
  101.  
  102.         def self.hwnd
  103.           @@hwnd
  104.         end
  105.  
  106.         def self.exit_func
  107.           if MFXRB.callMessageBoxW("确定关闭游戏吗?","",32,1) == 1
  108.           exit
  109.           else
  110.           DataManager.save_game(0)
  111.           rgss_main { SceneManager.run }
  112.  
  113.           end
  114.         end
  115.  
  116.         hook_exit
  117.  
  118.       end
  119.     end


作者: 翠靈月    时间: 2017-10-25 19:03
guoxiaomi 发表于 2017-10-25 09:12
alias _old_exit exit
def exit
...

虽然我知道应该还要再加些其他代码,不过能力不足就先直接添加了
添加后达成了不退出并进行游戏的目的
但又有了新问题
假如设为1号开关开启后按红叉不退出,之后即使1号开关关闭也一样无法退出
代换为主楼的情况就是第一次按否,之后再按是也关不了游戏
请大佬开示


作者: guoxiaomi    时间: 2017-10-25 19:11
本帖最后由 guoxiaomi 于 2017-10-25 19:25 编辑
翠靈月 发表于 2017-10-25 19:03
虽然我知道应该还要再加些其他代码,不过能力不足就先直接添加了
添加后达成了不退出并进行游戏的目的
但 ...

可以理解为,按下X会调用Kernel#exit方法,所以这里把这个方法直接改写了,就无法退出了。

我不太熟悉win32api的功能,不知道怎么调出有选项的对话框,我的处理大概是这样:
  1. alias _old_exit exit
  2. def exit
  3.   w = Window_Exit.new
  4.   loop do
  5.     Graphics.update
  6.     Input.update
  7.     w.update
  8.     case w.choice
  9.     when 0
  10.       _old_exit
  11.     when 1
  12.        break
  13.     else
  14.     end
  15.   end
  16.   w.dispose
  17. end
复制代码

大概就是这种感觉吧?按下X之后打开一个(游戏里的)窗口,让玩家选择是否退出。

我好像理解了你的意思……要用开关控制对吧:
  1. alias _old_exit exit
  2. def exit
  3.   _old_exit if $game_variables[1]
  4. end
复制代码

作者: Lemax    时间: 2017-10-26 12:45
请问楼主如果解决问题,可以请你代码发一下吗,我可能也需要这个。:)
作者: Lemax    时间: 2017-10-26 17:34
没事的,怎么样都行,我也可以学习一下。
作者: 翠靈月    时间: 2017-10-26 22:25
Lemax 发表于 2017-10-26 17:34
没事的,怎么样都行,我也可以学习一下。

即使看到很蠢的用法也求别笑

Project5.rar

1.52 MB, 下载次数: 71






欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1