life-rest 发表于 2008-10-12 08:39:02

给想学习插件编写朋友的一篇很好的文章

转自百度空间,原地址:
http://hi.baidu.com/liujiaming306/blog/item/4ce68855a9a9dfc7b645aeef.html




菜单的编写(技术型)在CS中创建一个菜单系统,我们把它分解成两步.
 首先必须建立并在屏幕上显示一个菜单

 其次要注册菜单,这样才能让插件(AMXMOD)知道该怎么做!

 当一个菜单的内容被设计好时

::::::::::::::::::::菜单系统范例:::::::::::::::::::::::

 菜单标题

 1. 操作1
 2. 操作2
 3. 操作3
 4. 操作4
 5. 操作5
 6. 操作6
 7. 操作7
 8. 操作8
 9. 操作9

 0. 退出
 ::::::::::::::::::::菜单范例结束:::::::::::::::::::::

 ::步骤1::

 我们首先要建立一个长字符串类型的变量来保存我们的菜单,并将我们菜单中的内容以文本的方式赋予这个变量;例如:操作1,操作2,操作3,等等...

 这个变量的建立看起大约像这样:

  代码

  new szMenuBody

 这个大小256可以替换成你想要的任意大小,但是它必须能够储存你的菜单内容+1个字符数(一个中文等于两个字符),这个名字"szMenubody"也可以替换成你想要的任意的一个名字.

 现在已经知道如何建立一个字符串变量了,接下来就是如何把菜单内容赋予这个变量,这里有几种方法可以这样做到:

 我们可以用format() 函数, copy() 函数, 或则add() 函数来完成这个赋值过程.

 在实际的运用中,我发现format()函数是最好用的.现在我们将format()来建立我们的菜单.

 首先我们要将菜单的标题输入到变量中去,稍候我们将用这个标题来注册我们的菜单,在我们上面的例子里这个标题被叫做“菜单标题”。

 这段代码看起来应该像这样:

 代码

 new nLen = format( szMenuBody, 255, "\y菜单标题:^n" )

 这里建立了一个新的变量叫做"nLen",它将储存文本(字符)的实际长度,因此我们可以知道变量szMenuBody还剩下多少空间和已经用了多少空间,以上代码的意思是把"\y菜单标题:^n"拷贝到变量szMenuBody中去,其中\y的意思的文本的颜色是黄色(还有很多中颜色如:\w表示白色等等),^n表示回车换行的意思(当菜单被显示时将建立一个新的空白行).format函数的第二个参数表示szMenuBody可以储存255-1个字符串(254)(最后一个字符保留).format函数返回一个当前储存了多少个字符的数字.

 现在已经把标题输入到变量中去了,现在我们要把操作(操作1,操作2...操作9和退出)输入到变量中去,接下来我们还是用format函数来完成.

 代码:

 nLen += format( szMenuBody, 255-nLen, "^n\w1. 操作1" )
 nLen += format( szMenuBody, 255-nLen, "^n\w2. 操作2" )
 nLen += format( szMenuBody, 255-nLen, "^n\w3. 操作3" )
 nLen += format( szMenuBody, 255-nLen, "^n\w4. 操作4" )
 nLen += format( szMenuBody, 255-nLen, "^n\w5. 操作5" )
 nLen += format( szMenuBody, 255-nLen, "^n\w6. 操作6" )
 nLen += format( szMenuBody, 255-nLen, "^n\w7. 操作7" )
 nLen += format( szMenuBody, 255-nLen, "^n\w8. 操作8" )
 nLen += format( szMenuBody, 255-nLen, "^n\w9. 操作9" )
 nLen += format( szMenuBody, 255-nLen, "^n^n\w0. 退出" )

 上面的代码本质上是一样的,nLen+表示自加,意思是format返回的数字与nLen变量原先所储存的数字相加在赋予nLen变量.当一行代码完成后,我们可以知道我们已经添加的菜单(内容)的实际长度为nLen,因此我们通过szMenuBody(format函数的第一个参数)可以安全的继续添加菜单内容,而不用担心后面添加的内容会覆盖前面的内容.format函数的第二个参数255-nLen则表示szMenuBody还剩下多少空间可以储存字符.

 现在做完这些我们已经成功地完成了菜单的设计,接下来我们要准备为每一个操作分配键(key),在分配键之前,首先要建立一个有规则的数字类型的变量来定向到"bits",键盘上的每一个键位都有一个"bits"与之一一对应,键位1对应bit0,键位2对应bit1,键位3对应bit2...键位9对应bit8,键位0对应bit9

 创建这个数字变量看起来应该像这样.

 代码:

 new keys

 然后分配bits.

 代码:

 keys = (1<<0|1<<1|1<<2|1<<3|1<<4|1<<5|1<<6|1<<7|1<<8|1<<9)

 (1<<0) = bit 0 = key 1
 (1<<1) = bit 1 = key 2
 (1<<2) = bit 2 = key 3
 ...
 ...
 (1<<8 ) = bit 8 = key 9
 (1<<9) = bit 9 = key 0

 现在我们已经知道如何的建立一个菜单了.

 ---------------------------------------------------------------------
 我们把上面的代码合在一起看起来应该像这样
 ---------------------------------------------------------------------

CODE:


new szMenuBody
new keys

new nLen = format( szMenuBody, 255, "\y菜单标题:^n" )

nLen += format( szMenuBody, 255-nLen, "^n\w1. 操作1" )
nLen += format( szMenuBody, 255-nLen, "^n\w2. 操作2" )
nLen += format( szMenuBody, 255-nLen, "^n\w3. 操作3" )
nLen += format( szMenuBody, 255-nLen, "^n\w4. 操作4" )
nLen += format( szMenuBody, 255-nLen, "^n\w5. 操作5" )
nLen += format( szMenuBody, 255-nLen, "^n\w6. 操作6" )
nLen += format( szMenuBody, 255-nLen, "^n\w7. 操作7" )
nLen += format( szMenuBody, 255-nLen, "^n\w8. 操作8" )
nLen += format( szMenuBody, 255-nLen, "^n\w9. 操作9" )
nLen += format( szMenuBody, 255-nLen, "^n^n\w0. 退出" )

keys = (1<<0|1<<1|1<<2|1<<3|1<<4|1<<5|1<<6|1<<7|1<<8|1<<9)


 ----------------------------------------------------------------------

 接下来当这个菜单被请求时,我们要把他显示在屏幕上.

 请求菜单并把它显示在屏幕上,我们可以通过控制台命令(像amx_showmenu)或者say-chat命令(像say /menu),无论那种方法都可以由自己来决定,现在我们用say-chat命令来请求我们的菜单.
 
 首先我们要显示一个菜单,就要建立一个文本字符和一个整数数字,然后调用show_menu()函数来显示菜单.

 这个函数在amxmod.inc库里的原形是这样的:
 
 native show_menu(index,keys,const menu[], time = -1)

 前面提到的文本字符和整数数字我们在前面的代码中已经建立了就是szMenuBody和keys,在我们的代码中,它看起应该像这样:

 代码:

 show_menu( id, keys, szMenuBody, -1 )

 这里的id表示是玩家编号,也就是在哪个玩家的屏幕上显示菜单.第4个参数表示显示的时间,这里用-1表示显示时间是永远.

 我们把上面的代码合在一起看起来应该像这样

CODE


public ShowMenu( id )
{
new szMenuBody
 new keys

 new nLen = format( szMenuBody, 255, "\y菜单标题:^n" )

 nLen += format( szMenuBody, 255-nLen, "^n\w1. 操作1" )
 nLen += format( szMenuBody, 255-nLen, "^n\w2. 操作2" )
 nLen += format( szMenuBody, 255-nLen, "^n\w3. 操作3" )
 nLen += format( szMenuBody, 255-nLen, "^n\w4. 操作4" )
 nLen += format( szMenuBody, 255-nLen, "^n\w5. 操作5" )
 nLen += format( szMenuBody, 255-nLen, "^n\w6. 操作6" )
 nLen += format( szMenuBody, 255-nLen, "^n\w7. 操作7" )
 nLen += format( szMenuBody, 255-nLen, "^n\w8. 操作8" )
 nLen += format( szMenuBody, 255-nLen, "^n\w9. 操作9" )
 nLen += format( szMenuBody, 255-nLen, "^n^n\w0. 退出" )

 keys = (1<<0|1<<1|1<<2|1<<3|1<<4|1<<5|1<<6|1<<7|1<<8|1<<9)


show_menu( id, keys, szMenuBody, -1 )

return PLUGIN_CONTINUE
}

 

 现在菜单已经可以显示在玩家的屏幕上了,接下来我们就要告诉插件,当执行一个命令的时候要让菜单显示在屏幕上,这里我们要用'register_clcmd'函数(注册客户端命令),这段代码看起来应该像这样.

 代码:
 
 public plugin_init()
 {
 register_clcmd( "say /menu","ShowMenu", -1, "Shows The menu" )

 return PLUGIN_CONTINUE
 }

 这里plugin_init()是一个触发事件,意思为当插件加载运行时就执行这段代码.register_clcmd函数有4个参数,第1个参数就是我们要连接到菜单的命令,第2个参数表示当我们键入say/menu是将要执行什么函数.第3个参数是管理权限,由于这个菜单是所有玩家都可以调用,所以我们把它设置成-1(-1=无权限认证),第4个参数是描述这个命令是干什么的,可以被忽略.

 好了现在我们的第一步工作已经全部玩成了,接下来我们要开始第2步了

 ::步骤 2::

 现在我们已经注册了一个命令并把它连接到了一个函数上,当一个玩家键入命令后,这个菜单就可以显示在他的屏幕上了,但是这并不能做什么!当一个玩家选择一个操作后,这个菜单不能做任何事情,因为我们还没有注册菜单,我们仅仅只是注册了命令而已,只有当我们注册了一个菜单并把它连接到一个函数上去后,我们才能让菜单起作用.

 我们要注册一个菜单并把它连接到一个函数上去,要用到2个不同的函数,第一个函数是注册菜单id(编号)函数,在cs中菜单有很多,注册菜单id的目的就是当菜单被激活后要让插件(amxmod)知道是那个菜单被激活,这样它才能找到并执行相应的连接函数.

 注册菜单id用register_menuid()函数,这个函数它只有一个字符串参数 ,这个字符串实际上应该与一个以被用过的菜单标题相统一的(毕竟不可能有2个一样的菜单标题),所以我们的参数应该是这样"\y菜单标题:".

 我们的代码应该像这样.

 代码:

 register_menuid("\y菜单标题:")

 这个函数返回的是一个整数数字(实际上就是菜单的id),在接下来我们要用的函数中就要用到这个菜单id,以便告诉amxmod是哪个菜单连接到哪个函数.

 接下来的函数就是'register_menucmd' ,把菜单和键连接到我们自定义的函数上去

 这第2个函数看起来像这样:

 register_menucmd( menuID, keys, "MenuCommand" )

 这里的第一个参数就是菜单的id,第二个参数就是我们在步骤1中所建立的keys,第3个参数就是我们要连接的函数

 所以我们建立的代码应该像这样

 代码

 register_menucmd(register_menuid("\y菜单标题:"), (1<<0|1<<1|1<<2|1<<3|1<<4|1<<5|1<<6|1<<7|1<<8|1<<9), "MenuCommand" )

 注意:这里的keys参数可以用1023代替,并能正常工作!

 接下来就差最后一步了,就是定义MenuCommand(菜单连接到的函数)

 代码

 public MenuCommand( id, key )
 {
  client_print( id, print_console, " Key=%d", key )
 client_print( id, print_chat, " Key=%d", key )

  switch( key )
 {
  case 0: client_print( id, print_chat, "操作#1" )
 case 1: client_print( id, print_chat, "操作 #2" )
  case 2: client_print( id, print_chat, "操作 #3" )
 case 3: client_print( id, print_chat, "操作 #4" )
  case 4: client_print( id, print_chat, "操作 #5" )
  case 5: client_print( id, print_chat, "操作 #6" )
  case 6: client_print( id, print_chat, "操作 #7" )
  case 7: client_print( id, print_chat, "操作 #8" )
  case 8: client_print( id, print_chat, "操作 #9" )
  case 9: client_print( id, print_chat, "菜单操作退出" )
  }

 return PLUGIN_CONTINUE
 }


 ---------------------------------------------------------------------
  总代码
 ---------------------------------------------------------------------

#include <amxmod>


public plugin_init()
{
register_clcmd( "say /menu","ShowMenu", -1, "Shows The menu" )

register_menucmd(register_menuid("\y菜单标题:"), 1023, "MenuCommand" )

return PLUGIN_CONTINUE
}

public ShowMenu( id )
{
new szMenuBody
new keys

new nLen = format( szMenuBody, 255, "\y菜单标题:^n" )

nLen += format( szMenuBody, 255-nLen, "^n\w1. 操作1" )
nLen += format( szMenuBody, 255-nLen, "^n\w2. 操作2" )
nLen += format( szMenuBody, 255-nLen, "^n\w3. 操作3" )
nLen += format( szMenuBody, 255-nLen, "^n\w4. 操作4" )
nLen += format( szMenuBody, 255-nLen, "^n\w5. 操作5" )
nLen += format( szMenuBody, 255-nLen, "^n\w6. 操作6" )
nLen += format( szMenuBody, 255-nLen, "^n\w7. 操作7" )
nLen += format( szMenuBody, 255-nLen, "^n\w8. 操作8" )
nLen += format( szMenuBody, 255-nLen, "^n\w9. 操作9" )
nLen += format( szMenuBody, 255-nLen, "^n^n\w0. 退出" )

keys = (1<<0|1<<1|1<<2|1<<3|1<<4|1<<5|1<<6|1<<7|1<<8|1<<9)

show_menu( id, keys, szMenuBody, -1 )

return PLUGIN_CONTINUE
}

public MenuCommand( id, key )
{
client_print( id, print_console, " Key=%d", key )
client_print( id, print_chat, " Key=%d", key )

switch( key )
{
case 0: client_print( id, print_chat, "操作 #1" )
case 1: client_print( id, print_chat, "操作 #2" )
case 2: client_print( id, print_chat, "操作 #3" )
case 3: client_print( id, print_chat, "操作 #4" )
case 4: client_print( id, print_chat, "操作 #5" )
case 5: client_print( id, print_chat, "操作 #6" )
case 6: client_print( id, print_chat, "操作 #7" )
case 7: client_print( id, print_chat, "操作 #8" )
case 8: client_print( id, print_chat, "操作 #9" )
case 9: client_print( id, print_chat, "菜单操作退出" )
}

return PLUGIN_HANDLED
}




本资源主要来源于djeyl.net forums \ AMX Mod \ script_ing Support / Help 。作者:xeroblood!
本人只是对此作了翻译和一些简单的加工处理 补充:用format()函数来添加菜单内容最大的好处就是能格式化不同类型的变量为字符,而add()和copy()则不行。
如以下代码:
new a
new b = 3
new c = "How are you !"
format (a,255,c+"%s",b)
最后在变量a中的内容就是"How are you !3",注意这个"3"在这里已经变为字符了,也就是电脑把它变成字符3所对应的代码了,如ASCⅡ(我还不知道amxmod用的是什么码)
如果在这里用copy或add来代替format就会出错,如以下代码:
copy(a,255,c+b)或add(a,255,c+b) 这两句都是错的
所以用format函数可以减少出错的几率!

wcy3002003 发表于 2008-10-12 16:30:42

回复: 给想学习插件编写朋友的一篇很好的文章

好东西!。。。:rolleyes:

感动鱼 发表于 2009-7-6 23:21:36

一时半会还看不懂...{:3_69:}

asa366 发表于 2009-7-12 08:38:38

好东西,来学习下

ghost4.12 发表于 2010-5-2 20:42:29

来学习的顶

MOUSE31RAT 发表于 2010-5-22 16:40:30

拿回家研究了啊
页: [1]
查看完整版本: 给想学习插件编写朋友的一篇很好的文章