令人蛋疼的AMXX插件第二弹!!用PAWN语言制作你的第一个插件!!

社区服务
高级搜索
猴岛论坛CSGO反恐精英CS个性化修改专区令人蛋疼的AMXX插件第二弹!!用PAWN语言制作你的第一个插件!!
发帖 回复
正序阅读 最近浏览的帖子最近浏览的版块
8个回复

令人蛋疼的AMXX插件第二弹!!用PAWN语言制作你的第一个插件!!

楼层直达
Shit~淡去

ZxID:11925994

等级: 少将
慢慢的淡去~活在世上已无乐趣~

举报 只看楼主 使用道具 楼主   发表于: 2011-04-03 0
AMX Mod X Documentation
Scripting Tutorial – Basic Plugins
Translated by Shaman.Kaler (again- -b)
前言
你想做个AMXX插件?那首先你应该对Pawn的工作方式有很好的了解,所以确信你已经认真的阅读了《介绍》和《Pawn语言基础》。现在你应该坐在电脑前,看着这部分内容,开着文本编辑器,并且手头就有Small编译器。(老外的废话是那么的多--小克注)你不必急着去编WC3、Matrix Mod或者CSDM那样的插件,不过这至少说明你编插件的心有多么急切……有个很好的AMX Pawn文本编辑器叫Crimson Editor,你可以试一试:http://www.crimsoneditor.com/(Still available!不过个人还是偏好AMXX Studio滴--小克注)
你应该很熟悉插件的编译方法,也应该懂得如何安装编译完成的插件。在这里方法不再赘述,请阅读前面的部分(我这里没有的说,详见官方文档Plugins部分—小克注)
AMXX插件的结构
AMXX插件主要有四种类型的函数。第一种是Public函数,这是AMXX引擎直接可见的函数。第二种是Native函数,是模块或AMXX内核声明的函数。第三种是用户定义的函数,没有特殊额外声明。第四种是Forward函数,只有当某个特殊事件发生时才被调用(同时也是Public函数)。一个AMXX插件开头必须有一个函数来注册这个插件:
//这使得你可以使用AMXX核心的函数。
//包括(include) includes\amxmodx.inc中定义的所有native函数.
#include <amxmodx>
//声明三个字符串(同样也可以使用预处理命令#define)
new PLUGIN[]="AMXX Demo"
new AUTHOR[]="BAILOPAN"
new VERSION[]="1.00"
//这是个Public函数. 
//在AMXX插件中这是必需的注册函数.
//它不需要参数,在地图载入后自动执行.
public plugin_init()
{
    //这个函数需要三个字符串.
    //这会注册你的插件到AMXX中,同时会设定一些基础信息.
    register_plugin(PLUGIN, VERSION, AUTHOR)
}
现在可以尝试编译上面的脚本了,编译出的amxx会非常小——因为没有任何作用。不过,如果你安装并载入了这个插件,然后在控制台输入amxx plugins,你会看到一个叫AMXX Demo的插件的。
建立管理员命令
AMXX提供了一种简单的建立OP控制台命令的方法,通过把命令“register”(注册)成控制台命令来实现。当你注册一个命令的时候需要四个参数:控制台命令、引发的过程函数、OP级别和命令描述。
在这个演示中,我们将建立一个修改玩家HP的插件及其命令”amx_hp”。
我们要做两件事:一是注册控制台命令,二是要在命令上绑定一个Public函数。
#include <amxmodx>
#include <amxmisc> //包含一些有用函数
#include <fun>    //包含改HP的函数
new PLUGIN[]="Change Health"
new AUTHOR[]="BAILOPAN"
new VERSION[]="1.00"
public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR)
    register_concmd("amx_hp", "cmd_hp", ADMIN_SLAY, " ")
}
public cmd_hp(id, level, cid)
{
    return PLUGIN_HANDLED
}
第一个新函数是”register_concmd”,需要四个参数。第一个是玩家要输入控制台的命令,第二个是将被调用的Public函数,第三个是执行命令的权限,最后一个可以写一些指导性文字(在amx_help命令中用到)。
下面,我们已经建立了一个Public函数用来执行”amx_hp”的功能(cmd_hp),注意我们给了这个函数三个参数,每个参数都代表着一些OP命令需要的特殊数据:id 代表执行命令的玩家id,level 代表该玩家的执行权限,cid 代表命令的内部id。
同时也要注意下PLUGIN_HANDLED。你必须了解有两个主要的返回数据,PLUGIN_CONTINUE代表“一切正常,继续执行”;PLGUIN_HANDLED代表“到此为止,不再继续”。它们的区别虽简单却重要。比如绑定一个命令的时候,你就不该返回PLUGIN_CONTINUE(没得continue,命令执行完就该结束掉—小克注),但是绑定到“say”命令上时,PLUGIN_HANDLED却会完全阻止玩家这句话的显示。不同的情况下你必须小心选择,不过大多数情况下没有什么影响(比如task、event和其他的一些等等)。
现在让我们继续,怎样才能判断一个玩家是不是有ADMIN_SLAY权限呢?
public cmd_hp(id, level, cid)
{
    if (!cmd_access(id, level, cid, 3))
        return PLUGIN_HANDLED
    return PLUGIN_HANDLED
}
上面的cmd_access函数会检查一个命令的信息(命令的使用者,使用者的权限和id)。这个命令会确保两件事:一是使用者有权限,二是OP命令给出的参数达到了最低数量。这里我们把最小值设为3,因为完整的命令会像这样”amx_hp xx 100”,OP命令本身也算做一个参数。如果cmd_access函数不通过,那么我们就让OP命令直接停止。
下一步要解决的问题就是后面的两个参数。我们要读出并解码。HP数量参数很容易,直接从字符串转换到数值即可。另一个就有点难度,因为我们至少要能选出三种不同的人:
• @CT or @T - CTs 或 Ts
• @ALL – 每个人
• Xx -- 玩家的部分名字

public cmd_hp(id, level, cid)
{
    if (!cmd_access(id, level, cid, 3))
        return PLUGIN_HANDLED
    new Arg1[24]
    new Arg2[4]
    //从控制台获得命令参数(amx_hp后面的部分)
    read_argv(1, Arg1, 23)
    read_argv(2, Arg2, 3)
    //把health转换成数值
    new Health = str_to_num(Arg2)
    //第一个字母是@吗?
    if (Arg1[0] == '@')
    {
          new Team = 0
          //确定指定的是哪个队伍.
          //注意我们是从空间 [1] 开始, 这是可以的
          //这只是意味着我们省掉了”@”
          if (equali(Arg1[1], "CT"))
          {
              Team = 2
          } else if (equali(Arg1[1], "T")) {
              Team = 1
          }
          new players[32], num
          // 这个函数会把玩家id填充进 players[32] 变量
          // num代表玩家的数目
          get_players(players, num)
          new i
          for (i=0; i<num; i++)
          {
              if (!Team)
              {
                    //设定玩家的HP
                    set_user_health(players, Health)
              } else {
                    if (get_user_team(players) == Team)
                    {
                        set_user_health(players, Health)
                    }
              }
          }
    } else {
          //找到部分名字相同的玩家
          //1意味着玩家如果有禁止被选中的权限将不被选中
          new player = cmd_target(id, Arg1, 1)
          if (!player)
          {
              //给使用这条命令的玩家发送信息。
              //这个命令的格式称为 "format()",
              //根据给定的参数显示一定格式的信息。
              //  %s 代表字符串
              //  %d 或 %i 代表整数integer
              //  %f 代表浮点数float
              // 因此 "Hello %s, I am %d years old" 后面需要
        // 两个参数,一个字符串,一个整数。
              console_print(id, "Sorry, player %s could not be found or targetted!", Arg1)
              return PLUGIN_HANDLED
          } else {
              set_user_health(player, Health)
          }
    }
    return PLUGIN_HANDLED
}
最后,这个插件应该是这样的:
#include <amxmodx>
#include <fun>

new PLUGIN[]="Change Health"
new AUTHOR[]="BAILOPAN"
new VERSION[]="1.00"

public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR)
    register_concmd("amx_hp", "cmd_hp", ADMIN_SLAY, "<target> <hp>")
}

public cmd_hp(id, level, cid)
{
    if (!cmd_access(id, level, cid, 3))
        return PLUGIN_HANDLED

    new Arg1[24]
    new Arg2[4]

    //获得命令参数
    read_argv(1, Arg1, 23)
    read_argv(2, Arg2, 3)

    //把字符串转换成数字
    new Health = str_to_num(Arg2)

    //第一个字符是@符号吗?
    if (Arg1[0] == '@')
    {
          new Team = 0
          if (equali(Arg1[1], "CT"))
          {
              Team = 2
          } else if (equali(Arg1[1], "T")) {
              Team = 1
          }
          new players[32], num
          get_players(players, num)
          new i
          for (i=0; i<num; i++)
          {
              if (!Team)
              {
                    set_user_health(players, Health)
              } else {
                    if (get_user_team(players) == Team)
                    {
                        set_user_health(players, Health)
                    }
              }
          }
    } else {
          new player = cmd_target(id, Arg1, 1)
          if (!player)
          {
              console_print(id, "Sorry, player %s could not be found or targetted!", Arg1)
              return PLUGIN_HANDLED
          } else {
              set_user_health(player, Health)
          }
    }

    return PLUGIN_HANDLED
}
CVAR
Cvar是服务器端的存储键,例如”mp_startmoney”存储了开局钱数的信息。你可以在plugin_init()里注册自己的Cvar。下面以mp_startmoney的作用为例:
#include <amxmodx>
public plugin_init()
{
    register_plugin("CVAR Test", "1.0", "BAILOPAN")
    //默认值为800
    register_cvar("amx_startmoney", "800")
}
//当玩家进入服务器时触发client_putinserver(Forward)
public client_putinserver(id)
{
    if (get_cvar_num("amx_startmoney") > 0)
    {
          cs_set_user_money(id, get_cvar_num("amx_startmoney"))
    } else {
    cs_set_user_money(id, get_cvar_num("mp_startmoney"))
    }
}
(这个插件可能不会工作,这只是一个演示。)你可以设置浮点、数值或字符串的Cvar,操作时就像HL中本来的Cvar一样简单。
结语
想学习更多的AMXX编程方法,你最好阅览一下各个inc文件中的函数用法。Inc文件通常遵循两个格式:用模块名或用途命名,如果有预先定义的常数或列表,会写在_const中,如果有一些有用的信息或成组的函数,就会写在_stock中。注意只有用到时stock才会被编译,所以#include一些包含很多组stock的inc文件是比较安全的。

本帖de评分: 1 条评分 DB +50
DB+50

汗!还分章节了?


Cc丶小琳

ZxID:13682314

等级: 中校
举报 只看该作者 8楼  发表于: 2011-11-06 0
不懂、
azx2249

ZxID:4428507

等级: 上等兵
举报 只看该作者 7楼  发表于: 2011-10-20 0
努力学习

际遇之神

惩罚

在论坛潜水撞到鱼雷,损失医药费DB5

yhr132

ZxID:15806936

等级: 上等兵
举报 只看该作者 6楼  发表于: 2011-08-15 0
哦是吗
、滚弹

ZxID:8249324

等级: 少将

举报 只看该作者 5楼  发表于: 2011-08-13 0
好长
88627886

ZxID:15288181

等级: 新兵
举报 只看该作者 4楼  发表于: 2011-08-08 0
这么长!!!!!
32638a

ZxID:14264630

等级: 列兵
举报 只看该作者 地板   发表于: 2011-04-05 0
晕 好长.............慢慢研究
ggawee01

ZxID:14160378

等级: 列兵
举报 只看该作者 板凳   发表于: 2011-04-04 0
救命啊~这么长!!!!!
爷们辅助

ZxID:6991542

等级: 贵宾
混蛋!我的元老呢?

举报 只看该作者 沙发   发表于: 2011-04-03 0
好长啊,不过我对编插件没什么兴趣!有兴趣的朋友看看
« 返回列表
发帖 回复