|
本帖最后由 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,
看似这个函数用在这里很没用,但其实我把它帖出来就知道
- PUSH {R4,R5,LR}
- MOVS R5, R0
- LSLS R5, R5, #0x18
- LSRS R5, R5, #0x18
- LDR R4, =coords16_in_front_of_player
- ADDS R1, R4, #2
- MOVS R0, R4
- BL player_get_pos_to_plus_one_step_in_direction_player_is_facing /*rom 0x05c4f4*/
- BL player_get_height /*rom 0x05c700*/
- STRB R0, [R4,#(height_in_front_of_player - coords16_in_front_of_player)]
- LDRH R0, [R4]
- LDRH R1, [R4,#(coords16_in_front_of_player.y - coords16_in_front_of_player)]
- LDRB R2, [R4,#(height_in_front_of_player - coords16_in_front_of_player)]
- 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这个函数,是不能单独使用的,因为他的参数也是要通过函数才能知道。
所以,机智的人已经知道要怎么办了,自己写一个函数,把这些放进去就好了,可是楼主是懒人的代表,所以我直接改动了原版程序,。,
当然你要自己写一个也行,
总之楼主是这样处理的也就是这个函数被楼主改了,那么原版的碎岩就不能用了,我将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
那么这个设想也就完成了,然后把它写成一个函数形式,大致是这样的
- bl 获取玩家面前npc的id
- bl 通过id获取脚本
- bl 运行脚本
复制代码 在你不改动原版程序的情况下,你可以这么用。
这就是主要的方法,至于如何让它像秘传技能那样直接在精灵界面使用,可以去参考版主的帖子“攀岩的实现”里面有说如何扩充秘传技能的方法
至于楼主,,既然楼主很懒,那么我们直接改碎岩好了,。,因为实在是太懒了,。,
改碎岩的话,你其实也可以改一字斩,你更可以改劲力,我觉得碎岩用的少一点罢了,。,哈哈哈
首先要让碎岩使用没有限制,就是除了徽章限制以外,让碎岩一直可以使用
- 在rom的0x0c97ca处
- 原本是0006
- 写入031c
复制代码 我又改了什么?
原本这里是碎岩的判断,判断玩家能不能使用碎岩,现在我直接让它的判断一直为“可以使用”
还没有完,可以使用后,还必须改掉程序指针,因为可以使用是运行一段程序,不可以使用运行的是另一段程序,既然都是原版的,我们直接改成我们自己的吧
好了现在开始我们的新程序,。,(新人,代码很渣,渣到自己不想看)
- .text
- .align 2
- .thumb
- main:
- push {lr}
- ldr r0,.flag /*这里是一个flag 0xc00*/
- bl .check_flag /*运行检查flag的程序*/
- cmp r0,#0 /*如果flag不存在,就不能使用,运行一段脚本*/
- beq .wrong
- bl get_poke /*这里是原版秘传技能运行脚本的程序,我直接抄过来了,可以不用管这一段*/
- ldr r1,.oe_state
- lsl r0,r0,#0x18
- lsl r0,r0,#0x18
- str r0,[r1]
- bl jump_1 /*改动原版程序后,r3是我们面前npc的id编号,如果不改它只会在r0上返回1或0*/
- cmp r3,#0x10 /*如果面前没人,也使用了这个程序,r3将是0x10*/
- beq .no_id /*面前没有人的处理情况,运行一段脚本*/
- /*所有检查完了以后,为了可以在脚本里灵活使用,我们只要运行程序到这里*/
- [font=微软雅黑][size=3]/*接上一段*/
- /*都会将变量0x800d设定为一个特殊值*/
- ldr r0,.var /*将0x800d的值设定为0xffa0,一个特殊值*/
- ldr r1,.oa_state
- strh r1,[r0]
- mov r0,r3 /*把r3的id移动回r0,为下一步做准备*/
- bl fun_get_script_by_id /*r0就是返回的脚本地址*/
- bl run_script /*最后运行该脚本*/
- pop {r0}
- bx r0
- jump_1:
- ldr r0,.jump1
- bx r0
- run_script:
- ldr r2,.run
- bx r2
- fun_get_script_by_id:
- ldr r3,.get_script
- bx r3
- get_poke:
- ldr r2,.get_pokemon
- bx r2
- .no_id:
- ldr r0,.no_id_ev
- bl run_script
- pop {r0}
- bx r0
- .check_flag:
- ldr r2,.flag_check
- bx r2
- .wrong:
- ldr r0,.no_use /*flag 0xc00不存在,不能使用*/
- bl run_script
- pop {r0}
- bx r0
- .align 2
- .jump1:
- .word 0x080c97a9
- .run:
- .word 0x08069ae5
- .get_script:
- .word 0x0805fc39
- .get_pokemon:
- .word 0x0811Fb0d
- .oe_state:
- .word 0x020386e0
- /*面前没有人时候的对话显示.word后是一个脚本指针,用来提示面前没人*/
- .no_id_ev:
- .word 0x08B00072
- /*用来触发的flag 0xc00*/
- .flag:
- .word 0x00000c00
- .flag_check:
- .word 0x0806e6d1
- /*不能使用时候的对话显示.word后是一个脚本指针,用来提示现在不能使用*/
- .no_use:
- .word 0x08B000B8
- /*0x800d是一个特殊值*/
- .oa_state:
- .word 0x0000ffa0
- .var:
- .word 0x020270B6 + (0x800D * 2)
复制代码
代码实在是太渣了,大神们就不要吐槽了,那么,我加入了一些东西以至于可以很好的在脚本里使用
因为这是直接获取npc的脚本并执行,这个直接点击npc运行脚本没两样,有人说这有什么用?
加入了将0x800d的值设定为0xffa0,以及检查flag 0xc00的程序,这就说明,直接点击npc运行脚本,0x800d的值不会是0xffa0,也不会检查0xc00这个flag
只有在精灵界面使用该技能后才可以触发这两个效果,但是运行的脚本是一样的,所以脚本里的检查,必不可少
脚本里这样用
一上来先检查0x800d的值是否是0xffa0
- compare 0x800d 0xffa0
- if 0x1 goto 特殊的脚本
- 正常情况下点击人物所运行的脚本
复制代码 有了这个检查,两种运行方式所处理的脚本截然不同,但是要注意的是,在脚本的最后一定要将0x800d值设定为0(当然其他值也行,只要不是0xffa0)
- #org 特殊的脚本
- ...
- ...
- ...
- ...
- setvar 0x800d 0x0
- end
复制代码 脚本里这样用没错,但是flag的作用不容无视,因为这个flag关系到这个功能否使用,每当我们setflag 0xc00的时候,这个功能就开启了,clearflag 0xc00的时候,这个功能就关闭了
当然,也不一定非要是0xc00,在源码里自己设置吧
最后呈上效果图
|
评分
-
查看全部评分
|