广告广告
  加入我的最爱 设为首页 风格修改
首页 首尾
 手机版   订阅   地图  繁体 
您是第 3817 个阅读者
 
发表文章 发表投票 回覆文章
  可列印版   加为IE收藏   收藏主题   上一主题 | 下一主题   
xhsu
个人文章 个人相簿 个人日记 个人地图
路人甲
级别: 路人甲 该用户目前不上站
推文 x2 鲜花 x6
分享: 转寄此文章 Facebook Plurk Twitter 版主评分 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片
推文 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。参见多种伤害类型并存应该怎么做,原理一样)
这样,我们的事件就算注册完了!

(抱歉,刚刚写一半断电了,赶紧先发第一部分。。)

此文章被评分,最近评分记录
财富:200 (by amore12) | 理由: 赞..^^



献花 x2 回到顶端 [楼 主] From:欧洲 | Posted:2014-07-29 11:03 |
xhsu
个人文章 个人相簿 个人日记 个人地图
路人甲
级别: 路人甲 该用户目前不上站
推文 x2 鲜花 x6
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

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 回到顶端 [1 楼] From:欧洲 | Posted:2014-07-29 11:11 |
xhsu
个人文章 个人相簿 个人日记 个人地图
路人甲
级别: 路人甲 该用户目前不上站
推文 x2 鲜花 x6
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

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 回到顶端 [2 楼] From:欧洲 | Posted:2014-07-29 11:20 |
xhsu
个人文章 个人相簿 个人日记 个人地图
路人甲
级别: 路人甲 该用户目前不上站
推文 x2 鲜花 x6
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

顺便说一下对本论坛的看法(个人)
1.插件都不开源……Allied Modders 的插件都必须开源,不开源还可能删帖……(而且也无权限)
2.教学文都要威望……我有点怀疑这几位是否真心想让新人学习插件(哪怕是教怎么用if,else,new的教学文也是如此)
3.能下载的插件都有一行讨厌的字飘来飘去,下载者如果要做版本会直接pass,如果个人娱乐玩也愉快不到哪去,最终很可能会没人用……当初你写这个插件是让大家都不用,还是希望广为流传?
4.似乎以上都是为了防止盗文啊?嗯……无论各位怎么珍爱自己的劳动成果,这毫无错误。但是我要表明我的态度:我的插件没有版权,欢迎改PLUGIN_AUTHOR或者显示一行字说是某某人写的;我的文章没有版权,欢迎四处转载不标明出处……

以上


献花 x3 回到顶端 [3 楼] From:欧洲 | Posted:2014-07-29 11:31 |
i-c0112
个人头像
个人文章 个人相簿 个人日记 个人地图
小有名气
级别: 小有名气 该用户目前不上站
推文 x6 鲜花 x194
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

要不要再补齐一下 提醒大家 要发布 forward 的 宣告标头.inc??
如果能再稍微花时间排版 整齐点 让有心学习的人能更快看懂

除此之外 这篇已经确实发挥教学效果了 真的感谢分享
愿意花时间帮助他人~~

至于插件和教学文 存在不低的门槛 这样的问题
说真的原因其实是缺乏正式管道让创作人保护自己的权利
所以才会靠这种 不分好坏 一概把 有意获得源码的人 排挤在外 这种下下策
其实大家没有一个不喜欢讨论自己的成果 尤其各位应该都是满腔热血的在coding吧


献花 x0 回到顶端 [4 楼] From:台湾中华电信股份有限公司 | Posted:2014-08-01 20:49 |
xhsu
个人文章 个人相簿 个人日记 个人地图
路人甲
级别: 路人甲 该用户目前不上站
推文 x2 鲜花 x6
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

抱歉忘了这一段~关于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 回到顶端 [5 楼] From:欧洲 | Posted:2014-08-04 09:05 |
xuqiang52133
个人文章 个人相簿 个人日记 个人地图
初露锋芒
级别: 初露锋芒 该用户目前不上站
推文 x1 鲜花 x32
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

我有一个代码,能帮我加个东西吗?我的 QQ373734484。加我可以吗/我想问你点问题


我要暴你头。。。。。
献花 x0 回到顶端 [6 楼] From:没有资料 | Posted:2014-11-26 21:51 |

首页  发表文章 发表投票 回覆文章
Powered by PHPWind v1.3.6
Copyright © 2003-04 PHPWind
Processed in 0.028301 second(s),query:16 Gzip disabled
本站由 瀛睿律师事务所 担任常年法律顾问 | 免责声明 | 本网站已依台湾网站内容分级规定处理 | 连络我们 | 访客留言