引用 | 编辑
xhsu
2014-07-29 11:03 |
楼主
▼ |
||
x1
在AMXMODX1.80之后,似乎支持创建属于自己的事件触发接口了……那好,我今天就带大家学习一下怎么创造一个事件。 (抱歉各位,我是大陆人,翻墙慕名而来,语法错误敬请谅解!谢谢!) 1.什么是“事件”? 这里说的不是指ham模块或者fm模块的register forward,也不是register ham 而是inc里直接由forward xxxxxx(any:...)触发的 最常见的是啥?当然是每个插件都看得到的forward plugin_init()了 当然,plugin_native, plugin_precache等等都是 这里要教的就是,怎么用插件创造一个这样的事件。 2.Pre事件与Post事件。 这两个对于大部分人都很熟悉,我也不多说,能看懂上面文字的,也一定能明白Pre和Post事件的区别。 (简单提一下,Pre事件就是“预”,可以打断阻止其发生,Post事件打断了也没用,因为已经发生过了) 但是对于forward来说,创造pre事件或者post事件都差不多,甚至没有区别。(后面说) 3.第一步 首先肯定要#include <amxmodx>不必多说 即使是一个事件,我们也需要一个“容器”来承接返回值。 所以像这样:(先以Post事件为例) new g_fwDummyResult, Post_Gift 接下来,我们需要在plugin_init()里面创造事件! Post_Gift = CreateMultiForward("amx_event_head_shot", ET_IGNORE, FP_CELL, FP_CELL) 这就是我们需要详解的部分了! 前面的Post_Gift = CreateMultiForward()自然不必多说,获取事件返回编号值。 第一项:"amx_event_head_shot"这个字符串,就是相当于字符串plugin_init——子插件里的回调函数名,也是forward xxx(any:...)那个xxx的内容 第二项的内容,可以说是关键。让我们看看amxconst.inc里给的: #define ET_IGNORE 0 //ignore return val #define ET_STOP 1 //stop on PLUGIN_HANDLED #define ET_STOP2 2 //same, except return biggest #define ET_CONTINUE 3 //no stop, return biggest 一般来说,Post事件用ET_IGNORE,Pre事件用ET_CONTINUE 这里我的例子是Post事件,故用ET_IGNORE 第三项,则是事件给的参数。例如这个,将来我要写在子插件里的是什么? forward amx_event_head_shot(iVictim, iAttacker) 玩家是属于1-32区间内的整数,所以——我们要用FP_CELL 再看看amxconst.inc给的。 #define FP_CELL 0 //整数 #define FP_FLOAT 1 //浮点数 #define FP_STRING 2 //字符串 #define FP_ARRAY 4 //数组 根据你的forward事件的需求,一个逗号一个逗号(据说可以无限延长)的填进这些FP_XXX (注:如果要触发浮点数组,例如pev获取的坐标,向量,角度等等,怎么办呢?很简单,用FP_FLOAT | FP_ARRAY。参见多种伤害类型并存应该怎么做,原理一样) 这样,我们的事件就算注册完了! (抱歉,刚刚写一半断电了,赶紧先发第一部分。。) x2
|
引用 | 编辑
xhsu
2014-07-29 11:11 |
1楼
▲ ▼ |
4.第二步
事件注册完了,但是我们并没有规定什么时候触发啊?所以我们得触发他。 (这里我们以爆头触发为例) public plugin_init() { register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR); Post_Gift = CreateMultiForward("amx_event_head_shot", ET_IGNORE, FP_CELL, FP_CELL) register_event("DeathMsg","EventDeath","a","3=1","5=0") //这样过滤,就会仅仅触发爆头 } public EventDeath() { new iVictim = read_data(2) new iAttacker = read_data(1) fm_set_user_money(iAttacker, get_pdata_int(iAttacker, m_pdata_iMoney)+1000, 1) ExecuteForward(Post_Gift, g_fwDummyResult, iVictim, iAttacker) } 这样,我们在给爆头额外奖励的同时,也会触发一个事件。 (Post事件的特性也体现在这里——所有东西都处理完毕,才触发) 我们来讲解一下ExecuteForward() 首先第一项,就是我们在注册事件中的事件返回值了——Post_Gift = CreateMultiForward() 第二项……嗯,还记得我说过,即使一个事件也需要两个变量吗?就是这样。即使你使用了ET_IGNORE,你也需要一个容器来盛放“0”这个没用的返回值。 (g_fwDummyResult这个东西变成全局的其实也没关系,因为每触发一个事件,就会被赋值一次,不会互相干扰返回值) 然后第三项到第N项,就是我们的事件基本参数,也就是刚刚FP_CELL等等一一对应的数字。 (注意:刚刚你用了多少个FP_XXX,这里就必须给满所有参数,否则会出错。) x0 |
引用 | 编辑
xhsu
2014-07-29 11:20 |
2楼
▲ ▼ |
5.结束了?没有!Pre事件!
以上就是一个Post事件的来历。 (以下部分选修~~) 那么,有人要问,Pre事件呢? 其实对于插件来说,Pre事件和Post事件没差多少。你让不让Pre事件打断,都是你说了算的。 我们来看看: new g_fwDummyResult, Post_Gift, Pre_Gift public plugin_init() { register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR); Post_Gift = CreateMultiForward("amx_event_head_shot", ET_IGNORE, FP_CELL, FP_CELL) Pre_Gift = CreateMultiForward("amx_hook_head_shot", ET_CONTINUE) register_event("DeathMsg","EventDeath","a","3=1","5=0") } public EventDeath() { ExecuteForward(Pre_Gift, g_fwDummyResult) //执行Pre事件 if(g_fwDummyResult) return //如果Pre事件存在返回值,那么主插件也返回 new iVictim = read_data(2) new iAttacker = read_data(1) fm_set_user_money(iAttacker, get_pdata_int(iAttacker, m_pdata_iMoney)+1000, 1) ExecuteForward(Post_Gift, g_fwDummyResult, iVictim, iAttacker) } 这样一来,大家都明白了吧?在g_fwDummyResult被赋予返回值了以后,一旦不为0,那就取消主插件内事件的执行。 所以,返回值其实可以做很多事……比如你要在一个think刷速度的插件内控制速度,可以选择把速度设定为返回值最高的那个插件。 等等等等……但总而言之,如果你不写上if(g_fwDummyResult) return 那么你的Pre事件也打不断。所以,Pre到底能不能打断,全看你。 这就是forward事件的创造,学会了吗?如果还不会,可以回复我~ 以上 x0 |
引用 | 编辑
xhsu
2014-07-29 11:31 |
3楼
▲ ▼ |
顺便说一下对本论坛的看法(个人)
1.插件都不开源……Allied Modders 的插件都必须开源,不开源还可能删帖……(而且也无权限) 2.教学文都要威望……我有点怀疑这几位是否真心想让新人学习插件(哪怕是教怎么用if,else,new的教学文也是如此) 3.能下载的插件都有一行讨厌的字飘来飘去,下载者如果要做版本会直接pass,如果个人娱乐玩也愉快不到哪去,最终很可能会没人用……当初你写这个插件是让大家都不用,还是希望广为流传? 4.似乎以上都是为了防止盗文啊?嗯……无论各位怎么珍爱自己的劳动成果,这毫无错误。但是我要表明我的态度:我的插件没有版权,欢迎改PLUGIN_AUTHOR或者显示一行字说是某某人写的;我的文章没有版权,欢迎四处转载不标明出处…… 以上 x3 |
引用 | 编辑
i-c0112
2014-08-01 20:49 |
4楼
▲ ▼ |
要不要再补齐一下 提醒大家 要发布 forward 的 宣告标头.inc??
如果能再稍微花时间排版 整齐点 让有心学习的人能更快看懂 除此之外 这篇已经确实发挥教学效果了 真的感谢分享 愿意花时间帮助他人~~ 至于插件和教学文 存在不低的门槛 这样的问题 说真的原因其实是缺乏正式管道让创作人保护自己的权利 所以才会靠这种 不分好坏 一概把 有意获得源码的人 排挤在外 这种下下策 其实大家没有一个不喜欢讨论自己的成果 尤其各位应该都是满腔热血的在coding吧 x0 |
引用 | 编辑
xhsu
2014-08-04 09:05 |
5楼
▲ ▼ |
抱歉忘了这一段~关于forward的,感谢楼上提醒~
6.在inc里面: 既然事件已经存在了,那么我们怎么让别的插件调用它呢? 当然就是我们最初提到的forward啦! 我们还是以上面为例! (我原来还不会用code呢,感谢Nailaz教我!) 复制程式 forward amx_hook_head_shot() forward amx_event_head_shot(iVictim, iAttacker) 还记得我们上面的CreateMultiForward("amx_hook_head_shot", ET_CONTINUE)吗? forward里面的主要部分就是注册事件时引号内的内容,括弧里面的对应法则就是ExecuteForward里面除了返回值以外的部分,按顺序写下来~ 这样,整个事件就算是完成了~ (注:forward可以放在inc里然后用#include;当然也可以放在插件头!) x0 |
引用 | 编辑
xuqiang52133
2014-11-26 21:51 |
6楼
▲ |
我有一个代码,能帮我加个东西吗?我的 QQ373734484。加我可以吗/我想问你点问题
x0 |