Pokemon Center | 口袋中心 以口袋妖怪为主题并带有其他动漫游戏的讨论

 找回密码
 加入口袋中心
搜索
查看: 5420|回复: 10

【初学ASM】火红 提取npc脚本

[复制链接]

8

回帖

84

现金

0

勋章券

口袋学堂外的努力

Rank: 2Rank: 2

积分
32
发表于 2016-7-11 15:21:43 | 显示全部楼层 |阅读模式
本帖最后由 jiangzhengwenjz 于 2016-7-14 22:31 编辑

本人是ASM新手,刚入坑没几天,能做出这样效果,全靠版主的指导
起初只是一个无脑的想法,没想到居然成了现实,所谓的想法就是玩家面对一npc使用秘传技能后可以直接将那个npc的脚本拿来使用,听上去有点不可能,但是一步一步做下去还是有可能的
该想法有一个重点就是“如何获取面前npc的脚本”?

我们现在的剧情,大部分是点击npc触发该npc的脚本,这里边用到一个“获取玩家所点击的npc的脚本”的函数,该函数需要一个人物id来做参数,这个人物id可不是AM中的flag
这个id是用来标识npc在内存中的位置,并且在不断变化的,至于如何找到这个id,点击触发脚本有它自己的一套获取方法,我们这里用不上
了解了npc的id后就知道,我们需要给这个函数一个id编号,然后他给我们返回该id的npc脚本地址该函数在rom的0x05fc38位置,有兴趣的可以去看一下

有了这些应该就知道了我们要的效果不是点击npc获得脚本,而是面前这个npc的脚本,也就是“没有点击”也要获得脚本,但是那个函数,确确实实可以用到
函数是很老实的,他才不会管我们要用到什么,给他参数就可以返回值,也就是说,只要给他玩家面前这个npc的id就可以返回该npc的脚本地址,看上去可行


在原版的rom中,也有一些东西是可以获得玩家面前的npc的一些东西,比如npc的id,
在hm里的碎岩技能,直接在精灵菜单里使用,也就是“不用点击”,它会检查玩家面前这个npc的行走图编号是不是0x60(岩石),在AM里看下就知道了0x60也就是96号行走图确实是岩石,
那么问题就有了,“如何获得面前npc的行走图?”,在碎岩的程序里我找到了一个函数专门处理这种情况,在rom里的0x0c97a8位置,
该函数是一个bool函数,接受一个npc行走图编号做参数,返回玩家面前这个npc的行走图是不是给定参数里的行走图编号,当然bool函数,返回1或0,
看似这个函数用在这里很没用,但其实我把它帖出来就知道
  1. PUSH    {R4,R5,LR}
  2.                  MOVS    R5, R0
  3.                  LSLS    R5, R5, #0x18
  4.                  LSRS    R5, R5, #0x18
  5.                  LDR     R4, =coords16_in_front_of_player
  6.                  ADDS    R1, R4, #2
  7.                  MOVS    R0, R4
  8.                  BL      player_get_pos_to_plus_one_step_in_direction_player_is_facing       /*rom 0x05c4f4*/
  9.                  BL      player_get_height       /*rom 0x05c700*/
  10.                  STRB    R0, [R4,#(height_in_front_of_player - coords16_in_front_of_player)]
  11.                  LDRH    R0, [R4]
  12.                  LDRH    R1, [R4,#(coords16_in_front_of_player.y - coords16_in_front_of_player)]
  13.                  LDRB    R2, [R4,#(height_in_front_of_player - coords16_in_front_of_player)]
  14.                  BL      npc_id_by_pos_and_height       /*rom 0x05f894*/
复制代码
看到npc_id_by_pos_and_height这个函数,就是获取id的东西,它的参数是一个坐标和玩家的高度(height)
这就是我们想要的东西,面前npc的id,但是npc_id_by_pos_and_height这个函数,是不能单独使用的,因为他的参数也是要通过函数才能知道。
所以,机智的人已经知道要怎么办了,自己写一个函数,把这些放进去就好了,可是楼主是懒人的代表,所以我直接改动了原版程序,。,
当然你要自己写一个也行,
总之楼主是这样处理的
  1. 在080c99e4处写入8042
复制代码
也就是这个函数被楼主改了,那么原版的碎岩就不能用了,我将
npc_id_by_pos_and_height函数返回值(r0的值)写在了r3上,当然你说我重写一新函数也行,去no$gba里都有地址,全抄下来也不是问题,反正记住r0就是npc_id_by_pos_and_height返回的id编号就可以了


已经成功的获取了面前npc的id,那么只要把这个id给专门的“从id获取脚本”这个函数就可以返回面前npc的脚本,前面已经说了这个函数在rom的0x05fc38位置,直接调用就好了
那么将id放在r0,它会返回的脚本地址也存在r0中
非常ok啊,已经获取了脚本地址了,就运行它吧,版主给我的一个地址是用来运行脚本的,也不深度解释它,r0放脚本地址就可以正确运行了
这个运行脚本的函数在rom的0x069ae4
那么这个设想也就完成了,然后把它写成一个函数形式,大致是这样的
  1. bl 获取玩家面前npc的id
  2. bl 通过id获取脚本
  3. bl 运行脚本
复制代码
在你不改动原版程序的情况下,你可以这么用。

这就是主要的方法,至于如何让它像秘传技能那样直接在精灵界面使用,可以去参考版主的帖子“攀岩的实现”里面有说如何扩充秘传技能的方法
至于楼主,,既然楼主很懒,那么我们直接改碎岩好了,。,因为实在是太懒了,。,
改碎岩的话,你其实也可以改一字斩,你更可以改劲力,我觉得碎岩用的少一点罢了,。,哈哈哈
首先要让碎岩使用没有限制,就是除了徽章限制以外,让碎岩一直可以使用

  1. 在rom的0x0c97ca处
  2. 原本是0006
  3. 写入031c
复制代码
我又改了什么?

原本这里是碎岩的判断,判断玩家能不能使用碎岩,现在我直接让它的判断一直为“可以使用”
还没有完,可以使用后,还必须改掉程序指针,因为可以使用是运行一段程序,不可以使用运行的是另一段程序,既然都是原版的,我们直接改成我们自己的吧
  1. 在rom的0x0c9a0c处写入新程序指针+1
复制代码
好了现在开始我们的新程序,。,(新人,代码很渣,渣到自己不想看)

  1. .text
  2. .align 2
  3. .thumb

  4. main:
  5. push {lr}

  6. ldr r0,.flag    /*这里是一个flag 0xc00*/
  7. bl .check_flag  /*运行检查flag的程序*/

  8. cmp r0,#0       /*如果flag不存在,就不能使用,运行一段脚本*/
  9. beq .wrong

  10. bl get_poke    /*这里是原版秘传技能运行脚本的程序,我直接抄过来了,可以不用管这一段*/
  11. ldr r1,.oe_state
  12. lsl r0,r0,#0x18
  13. lsl r0,r0,#0x18
  14. str r0,[r1]

  15. bl jump_1      /*改动原版程序后,r3是我们面前npc的id编号,如果不改它只会在r0上返回1或0*/

  16. cmp r3,#0x10   /*如果面前没人,也使用了这个程序,r3将是0x10*/
  17. beq .no_id     /*面前没有人的处理情况,运行一段脚本*/

  18. /*所有检查完了以后,为了可以在脚本里灵活使用,我们只要运行程序到这里*/
  19. [font=微软雅黑][size=3]/*接上一段*/
  20. /*都会将变量0x800d设定为一个特殊值*/

  21. ldr r0,.var    /*将0x800d的值设定为0xffa0,一个特殊值*/
  22. ldr r1,.oa_state
  23. strh r1,[r0]

  24. mov r0,r3      /*把r3的id移动回r0,为下一步做准备*/
  25. bl fun_get_script_by_id    /*r0就是返回的脚本地址*/
  26. bl run_script     /*最后运行该脚本*/
  27. pop {r0}
  28. bx r0

  29. jump_1:
  30. ldr r0,.jump1
  31. bx r0

  32. run_script:
  33. ldr r2,.run
  34. bx r2

  35. fun_get_script_by_id:
  36. ldr r3,.get_script
  37. bx r3

  38. get_poke:
  39. ldr r2,.get_pokemon
  40. bx r2

  41. .no_id:
  42. ldr r0,.no_id_ev
  43. bl run_script
  44. pop {r0}
  45. bx r0

  46. .check_flag:
  47. ldr r2,.flag_check
  48. bx r2

  49. .wrong:
  50. ldr r0,.no_use   /*flag 0xc00不存在,不能使用*/
  51. bl run_script
  52. pop {r0}
  53. bx r0

  54. .align 2
  55. .jump1:
  56. .word 0x080c97a9

  57. .run:
  58. .word 0x08069ae5

  59. .get_script:
  60. .word 0x0805fc39

  61. .get_pokemon:
  62. .word 0x0811Fb0d

  63. .oe_state:
  64. .word 0x020386e0

  65. /*面前没有人时候的对话显示.word后是一个脚本指针,用来提示面前没人*/
  66. .no_id_ev:
  67. .word 0x08B00072

  68. /*用来触发的flag 0xc00*/
  69. .flag:
  70. .word 0x00000c00

  71. .flag_check:
  72. .word 0x0806e6d1

  73. /*不能使用时候的对话显示.word后是一个脚本指针,用来提示现在不能使用*/
  74. .no_use:
  75. .word 0x08B000B8

  76. /*0x800d是一个特殊值*/
  77. .oa_state:
  78. .word 0x0000ffa0

  79. .var:
  80. .word 0x020270B6 + (0x800D * 2)
复制代码

代码实在是太渣了,大神们就不要吐槽了,那么,我加入了一些东西以至于可以很好的在脚本里使用
因为这是直接获取npc的脚本并执行,这个直接点击npc运行脚本没两样,有人说这有什么用?
加入了将0x800d的值设定为0xffa0,以及检查flag 0xc00的程序,这就说明,直接点击npc运行脚本,0x800d的值不会是0xffa0,也不会检查0xc00这个flag
只有在精灵界面使用该技能后才可以触发这两个效果,但是运行的脚本是一样的,所以脚本里的检查,必不可少


脚本里这样用
一上来先检查0x800d的值是否是0xffa0
  1. compare 0x800d 0xffa0
  2. if 0x1 goto 特殊的脚本
  3. 正常情况下点击人物所运行的脚本
复制代码
有了这个检查,两种运行方式所处理的脚本截然不同,但是要注意的是,在脚本的最后一定要将0x800d值设定为0(当然其他值也行,只要不是0xffa0)

  1. #org 特殊的脚本
  2. ...
  3. ...
  4. ...
  5. ...
  6. setvar 0x800d 0x0
  7. end
复制代码
脚本里这样用没错,但是flag的作用不容无视,因为这个flag关系到这个功能否使用,每当我们setflag 0xc00的时候,这个功能就开启了,clearflag 0xc00的时候,这个功能就关闭了

当然,也不一定非要是0xc00,在源码里自己设置吧
最后呈上效果图




评分

参与人数 1积分 +10 现金 +20 收起 理由
jiangzhengwenjz + 10 + 20

查看全部评分

回复

使用道具 举报

20

回帖

77

现金

0

勋章券

口袋学堂外的努力

Rank: 2Rank: 2

积分
40
发表于 2016-7-11 16:06:28 | 显示全部楼层
学了几天写出来的代码比我这个学了几年的都要好,还有现在的人为什么都这么矫情,发个帖老是强调自己渣,自己懒,真有意思,难道这也算是一种装B手段
回复 支持 反对

使用道具 举报

9

回帖

36

现金

0

勋章券

口袋学堂外的努力

Rank: 2Rank: 2

积分
23
发表于 2016-7-11 17:10:15 | 显示全部楼层
还不错,支持
回复 支持 反对

使用道具 举报

8

回帖

84

现金

0

勋章券

口袋学堂外的努力

Rank: 2Rank: 2

积分
32
 楼主| 发表于 2016-7-11 21:07:27 | 显示全部楼层
Against 发表于 2016-7-11 16:06
学了几天写出来的代码比我这个学了几年的都要好,还有现在的人为什么都这么矫情,发个帖老是强调自己渣,自 ...

怎么说呢,我的代码在别人看来也没有什么,用的标签太多,以至于我自己都没信心发出来,另外一个懒 确实嫌麻烦直接改原版程序了,这样改了话,原版碎岩就没用了,所以还是有风险的,其实只要全部抄下来封装成函数,就可以了,。,可是就是嫌麻烦,觉得那样用的标签就更多了,。,就更没自信发出来,。,
回复 支持 反对

使用道具 举报

23

回帖

172

现金

0

勋章券

新伙伴的欢笑

Rank: 3

积分
96
发表于 2016-7-11 23:14:11 | 显示全部楼层
玩家面对一npc使用秘传技能后可以直接将那个npc的脚本拿来使用


貌似空之花神有个类似的剧情

怎么说呢,我的代码在别人看来也没有什么,用的标签太多,以至于我自己都没信心发出来,另外一个懒 确实嫌麻烦直接改原版程序了,这样改了话,原版碎岩就没用了,所以还是有风险的,其实只要全部抄下来封装成函数,就可以了,。,可是就是嫌麻烦,觉得那样用的标签就更多了,。,就更没自信发出来,。,


个人建议除非代码设计上运用比较复杂的逻辑,否则不去做过多的标签,看起来就不会很乱。
回复 支持 反对

使用道具 举报

8

回帖

84

现金

0

勋章券

口袋学堂外的努力

Rank: 2Rank: 2

积分
32
 楼主| 发表于 2016-7-12 10:51:01 | 显示全部楼层
OnePunch 发表于 2016-7-11 23:14
貌似空之花神有个类似的剧情

空之花神那边我不是很清楚,这个想法是前几天突然冒出来的,还是靠版主提醒,要不然我也不会想到从碎岩下手
另外标签问题,。,我听说bl跳转只能跳标签,于是就是你们看到那种一堆标签,哈哈蛤
回复 支持 反对

使用道具 举报

23

回帖

172

现金

0

勋章券

新伙伴的欢笑

Rank: 3

积分
96
发表于 2016-7-12 13:19:03 | 显示全部楼层
前世今生 发表于 2016-7-12 10:51
空之花神那边我不是很清楚,这个想法是前几天突然冒出来的,还是靠版主提醒,要不然我也不会想到从碎岩下 ...

好吧看来我理解错你说的标签了
回复 支持 反对

使用道具 举报

20

回帖

77

现金

0

勋章券

口袋学堂外的努力

Rank: 2Rank: 2

积分
40
发表于 2016-7-12 14:37:11 | 显示全部楼层
前世今生 发表于 2016-7-11 21:07
怎么说呢,我的代码在别人看来也没有什么,用的标签太多,以至于我自己都没信心发出来,另外一个懒 确实 ...

标签多有啥好没信心的,只要写出来了,那不就是好的,另外你强调的渣,懒,的确有点过头了。。
回复 支持 反对

使用道具 举报

43

回帖

396

现金

0

勋章券

繁华都市的喧闹

Rank: 5Rank: 5Rank: 5

积分
188

时光印记Lv.1

发表于 2016-7-19 18:01:43 | 显示全部楼层
我装作不知道楼主是谁
回复 支持 反对

使用道具 举报

10

回帖

38

现金

0

勋章券

口袋学堂外的努力

Rank: 2Rank: 2

积分
20
发表于 2018-5-12 22:07:16 | 显示全部楼层
嗯......对我来说好深奥
回复 支持 反对

使用道具 举报

33

回帖

0

现金

0

勋章券

新伙伴的欢笑

Rank: 3

积分
74
发表于 2018-5-27 12:18:39 | 显示全部楼层
不错嘛,顶一个
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入口袋中心

本版积分规则

手机版|Archiver|Pokemon Center

GMT+8, 2024-11-21 18:30 , Processed in 0.114515 second(s), 55 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表