搜索
查看: 8755|回复: 21

【教程】关于message(重要课程!)

[复制链接]
发表于 2005-7-15 10:51:22 | 显示全部楼层 |阅读模式 来自 辽宁沈阳
教程(一)深入研究message
在AMX AMXX的娱乐插件里,您是否曾经被光环,爆炸,闪电,激光,烟雾,火焰等等的效果震撼呢?您试否曾经见过您的屏幕突然变白,突然变黑,突然开始振颤,甚至您看到屏幕右上角一个活人把一个死人杀死若干次的标志呢?这些,全都离不开message(消息),
消息如此的有用处,大家可能还不太理解,简单的message_begin, message_end, write_byte, write_coord 等等命令如何实现这样的功能。下面我就来教大家,自认为message是AMX AMXX脚本编写最有用处的命令之一。
支持AMX AMXX

技术难度系数:★★★☆
理解难度系数:★★★★☆


深入研究message,我将这分成两部分。
第一部分,message对效果的操作和第二部分,message对事件的操作。

第一部分,message对效果的操作。学习这部分,您需要有一定英文基础,至少您应该会查英汉词典。在附件的const.h里用得着。
所谓对效果的操作,就是用message创建诸如爆炸,闪电等等效果。首先,我们先熟悉一下用message创建效果的通用格式
①        创建所有人都能看见的效果
  1. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  2. write_byte(效果索引号码)
  3. write_***
  4. ………
  5. message_end()
复制代码

②        创建只有一个人能看见的效果
  1. message_begin(MSG_ONE, SVC_TEMPENTITY,{0,0,0},玩家id)
  2. write_byte(效果索引号码)
  3. write_***
  4. ………
  5. message_end()
复制代码

通用格式就是这么两个,玩家id就是玩家索引号码,效果索引号码存在于附件const.h中。下面,我来举几个例子。
实战(一)创建爆炸效果。
我们打开const.h,稍向下翻,实体索引号码通常都是
  1. #define TE_效果名称 效果索引号码
复制代码

并且,紧挨着他的下面通常有几行注释,以爆炸效果为例:(这个出自const.h)
  1. #define        TE_EXPLOSION                3                // additive sprite, 2 dynamic lights, flickering particles, explosion sound, move vertically 8 pps
  2. // coord coord coord (position)
  3. // short (sprite index)
  4. // byte (scale in 0.1's)
  5. // byte (framerate)
  6. // byte (flags)
  7. //
  8. // The Explosion effect has some flags to control performance/aesthetic features:
  9. #define TE_EXPLFLAG_NONE                0        // all flags clear makes default Half-Life explosion
  10. #define TE_EXPLFLAG_NOADDITIVE        1        // sprite will be drawn opaque (ensure that the sprite you send is a non-additive sprite)
  11. #define TE_EXPLFLAG_NODLIGHTS        2        // do not render dynamic lights
  12. #define TE_EXPLFLAG_NOSOUND                4        // do not play client explosion sound
  13. #define TE_EXPLFLAG_NOPARTICLES        8        // do not draw particles
复制代码

其中出现#define        TE_EXPLOSION                3,就是我说刚才说的形式,EXPLOSION(爆炸)是效果名,3是效果索引。但注意,下边还有什么 #define TE_EXPLFLAG_**** 数字 一些东西,这些就不是实体索引,因为紧挨着他们下边没有注释。
#define TE_EXPLOSION 3 下面的注释是非常有用的。我们来看看。
  1. // coord coord coord (position)
  2. // short (sprite index)
  3. // byte (scale in 0.1's)
  4. // byte (framerate)
  5. // byte (flags)
复制代码

这些注释告诉您,write_byte(效果索引) 下边该写什么,例如这里,//coord coord coord (position) 告诉您,write_byte(效果索引)下边应该写3个write_coord 表示创造爆炸效果的位置。//short (sprite index) 表示再写一个write_short表示spr索引,//byte (scale in 0.1's): 下边再写一个write_byte表示spr显示大小,按0.1倍计算,//byte (framerate) 下边再写一个write_byte表示每秒钟贞数,// byte(flages) 下边再写一个write_byte 表示标识。注意,这些的顺序是绝对不能颠倒的!然后,他就在下边给您解释标识如何使用:
  1. // The Explosion effect has some flags to control performance/aesthetic features:
  2. #define TE_EXPLFLAG_NONE                0        // all flags clear makes default Half-Life explosion
  3. #define TE_EXPLFLAG_NOADDITIVE        1        // sprite will be drawn opaque (ensure that the sprite you send is a non-additive sprite)
  4. #define TE_EXPLFLAG_NODLIGHTS        2        // do not render dynamic lights
  5. #define TE_EXPLFLAG_NOSOUND                4        // do not play client explosion sound
  6. #define TE_EXPLFLAG_NOPARTICLES        8        // do not draw particles
复制代码
这个就得您自己翻译了,所以我说,需要一定英文基础的。于是我们知道,创建正常的爆炸,标识为0就可以了。
于是,按照const.h里所给的格式,我们就可以写出以下内容:
  1. message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
  2. write_byte(3)
  3. write_coord()
  4. write_coord()
  5. write_coord()
  6. write_short()
  7. write_byte()
  8. write_byte()
  9. write_byte()
  10. message_end()
复制代码


当然,仅仅这样是不能创建效果的。因为,每个write_byte write_coord write_****(其他) 的后面必须含有一个值,下面,我先把spr索引讲一下。想获得spr索引,您必须作如下工作,申请储存spr索引的全局变量(就是在#include 区的下边输入new 变量名),我们不妨把变量名定为exp,然后,在插件plugin_precache过程中敲入exp = precache_model("sprites/zerogxplode.spr")这样,zerogxplode.spr(这是一个比较不错的爆炸spr文件)的spr索引就存储在了exp变量里。下面,我们开始完善这个message:
  1. message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
  2. write_byte(3)
  3. write_coord(x坐标)
  4. write_coord(y坐标)
  5. write_coord(z坐标)
  6. write_short( exp )
  7. write_byte(20)
  8. write_byte(10)
  9. write_byte(0)
  10. message_end()
复制代码

这样,一个爆炸效果将在坐标(x,y,z)处被创建,并以每秒10贞,2倍于自身spr大小的形式播放。为了让大家更完整的看到源代码,我把整个过程写出来,规则是这样:当玩家在控制台中输入expme,则自己瞄准的地方会产生一个爆炸效果,当然,是不伤人的。
  1. #include <amxmod>
  2. new exp   //申请全局变量exp

  3. public plugin_init(){
  4.   register_plugin(" 创建爆炸 ","0.1","Hydralisk")  //注册插件
  5.   register_clcmd("expme","h_expme") //注册控制台命令"expme", 当有人输入这个命令,则执行脚本中的 h_expme过程
  6.   return PLUGIN_CONTINUE
  7. }

  8. public plugin_precache(){     //这个就是我刚才说的plugin_precache过程
  9.   exp = precache_model("sprites/zerogxplode.spr") //预存储spr文件 zerogxplode.spr并将spr索引存储在exp变量里。
  10. }

  11. public h_expme(id){    //当有人输入"expme"时,这个过程将被触发,玩家的索引将被保存在头变量id里
  12.   new ori[3] //申请3位数组变量ori
  13.   get_user_origin(id,ori,3) //获取玩家正在瞄准的位置,并按 x坐标,y坐标,z坐标存储在ori变量里
  14.   message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
  15. write_byte(3)
  16. write_coord(ori[0])  //x坐标
  17. write_coord(ori[1])  //y坐标
  18. write_coord(ori[2])  //z坐标
  19. write_short( exp )   //spr索引
  20. write_byte(20)     //20×0.1 = 2倍于原spr文件 的爆炸的大小
  21. write_byte(10)     //每秒钟播放贞数
  22. write_byte(0)      //标识为:正常爆炸
  23. message_end()
  24. }
复制代码

第二部分,message对事件的操作。学习这部分,您最好也需要有一定的英文基础,不过本部分对英文的要求没有前面那部分对英文的要求那么多。如果您不会英文,也可以参看别人的源代码。
所谓对事件的操作,就是CS内部集成了很多事件,例如死亡消息DeathMsg(一个人把另外一个人打死后,屏幕右上角显示的消息)、屏幕震动ScreenShake、屏幕渐变ScreenFade(例如闪光弹爆炸后,玩家屏幕变成白色)、视场改变SetFov(例如AWP开镜后,远处的东西变大,就是改变了视场)、左侧图标StatusIcon(屏幕左侧“购物手推车”、“C4”、“人质释放点”、“VIP逃逸点”等图标都由此控制)……
其中绿色的部分为“事件名”,所有的CS事件名以及其内容都可以在nwb13曾经发的 【分享】关于事件等内容的参考资料 中找到。

我们先熟悉一下用message对事件操作的格式:
①        创建单人事件、

  1. message_begin(MSG_ONE,get_user_msgid("事件名"),{0,0,0}, 玩家id)
  2. write_...
  3. ….
  4. message_end()
复制代码

② 创建全局事件

  1. message_begin(MSG_ALL,get_user_msgid("事件名"))
  2. write_...
  3. ….
  4. message_end()
复制代码

所谓单人事件,就是这个事件是对单个人操作的事件。CS编写者定义事件的时候,已经确定了这个事件是单人事件还是全局事件。所以我们不能随便更改事件的性质,否则会引起服务器崩溃(“崩溃”只得是CS的服务器突然退出CS,对计算机没有太大影响)。我们一般可以凭感觉确定某一个事件是单人事件还是全局事件。例如,屏幕渐变,只对某个人的屏幕进行操作,使他的屏幕变白或者变黄或者变黑,所以这个事件就是单人事件;再例如,死亡消息,这个事件任何人都能看得到,所以这个事件就是一个全局事件。如果实在无法确认,那么就得自己试了。
下面我们举个例子,在这个例子中,当OP在控制台中输入"hy_fakekill 玩家名"<回车>后,那个被定义的玩家将会被OP“杀死”5次,其中用ak47爆头1次,m4a1杀死一次,刀爆头3次,当然,这个“杀死”不是真的杀死,那个玩家并不会死掉,只是屏幕的右上角显示被杀他被OP死5次。
首先,我们在前面所说的nwb13文章中的cs_event.xls文件中找到了DeathMsg的用法:

Message: DeathMsg
Argument Order: byte byte byte string
Description of Arguments: 1: Killer ID, 2: Victim ID, 3: Headshot, 4:Weapon Name


Message就是事件名, Argument Order 决定了message_begin和message_end之间的write_类型,Description of Arguments 表示第n个事件中的参数的作用。例如DeathMsg的事件内容为
  1. write_byte()
  2. write_byte()
  3. write_byte()
  4. write_string()
复制代码

第一个byte代表杀人者的ID,第二个byte代表受害者的ID,第三个byte代表是否爆头,第四个代表string是武器名称。这样,DeathMsg的内容就应该是:

  1. message_begin(MSG_ALL,get_user_msgid("DeathMsg"))
  2. write_byte(killer)
  3. write_byte(victim)
  4. write_byte(0) // 或者是1
  5. write_string("武器名")
  6. message_end()
复制代码

我们来把整个过程写完。

  1. #include <amxmod>
  2. #include <amxmisc>

  3. public plugin_init(){
  4.   register_plugin("Kill","0.1","Hydralisk")
  5.   register_clcmd("hy_fakekill","fakekill",ADMIN_LEVEL_D," <victim name or #id>")
  6.   return PLUGIN_CONTINUE
  7. }

  8. public fakekill(id, level, cid){
  9.   if (!cmd_access(id,level,cid,2)) return PLUGIN_HANDLED   //检查执行权限
  10.   new arg[33]
  11.   read_argv(1,arg,32)  // 获得 “玩家名” 参数
  12.   new player = cmd_target(id,arg,3) // 获得 受害者的 id
  13.   if (!player) return PLUGIN_HANDLED //检测是否有这个玩家
  14.   // 开始操作事件
  15. message_begin(MSG_ALL,get_user_msgid("DeathMsg"))
  16. write_byte(id)
  17. write_byte(player)
  18. write_byte(1)
  19. write_string("ak47")
  20. message_end()

  21. message_begin(MSG_ALL,get_user_msgid("DeathMsg"))
  22. write_byte(id)
  23. write_byte(player)
  24. write_byte(0)
  25. write_string("m4a1")
  26. message_end()
  27. for (new i=0; i<3; i++){
  28. message_begin(MSG_ALL,get_user_msgid("DeathMsg"))
  29. write_byte(id)
  30. write_byte(player)
  31. write_byte(1)
  32. write_string("knife")
  33. message_end()
  34. }

  35.   return PLUGIN_HANDLED
  36. }
复制代码

如果有语句不通、错别字、不理解的地方,敬请提出

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注个册吧

×
 楼主| 发表于 2005-7-15 10:58:18 | 显示全部楼层 来自 辽宁沈阳
有点问题。。Test.
回复

使用道具 举报

发表于 2005-7-15 13:15:16 | 显示全部楼层 来自 广东佛山

不是一下子就能看懂
回复

使用道具 举报

 楼主| 发表于 2005-7-15 13:50:52 | 显示全部楼层 来自 辽宁沈阳
有不懂得地方尽管提。而且我还没写完。
回复

使用道具 举报

发表于 2005-7-15 15:31:30 | 显示全部楼层 来自 陕西西安
message_begin(MSG_ONE, SVC_TEMPENTITY,{0,0,0},玩家id)
中SVC_TEMPENTITY和{0,0,0}的意思是?
回复

使用道具 举报

 楼主| 发表于 2005-7-15 15:35:55 | 显示全部楼层 来自 辽宁沈阳
SVC_TEMPENTITY代表消息类型为“临时实体”其实所有的效果都是临时创建的实体,然后效果的寿命到了以后,实体就被删除。{0,0,0} 这个,因为那个参数没有用,所以就用{0,0,0}占一下位

明天我继续写message和事件(event)的关系。:)
回复

使用道具 举报

发表于 2005-7-15 20:56:07 | 显示全部楼层 来自 北京海淀
:spiderman 偶只是飘过
回复

使用道具 举报

 楼主| 发表于 2005-7-15 21:02:47 | 显示全部楼层 来自 辽宁沈阳
。。。。。。
回复

使用道具 举报

发表于 2005-7-20 20:33:12 | 显示全部楼层 来自 广西玉林
支持拉啊`不错
回复

使用道具 举报

发表于 2005-7-26 04:28:33 | 显示全部楼层 来自 广东深圳
如雾里看花,似懂非懂!
回复

使用道具 举报

游客
回复
您需要登录后才可以回帖 登录 | 注个册吧

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