amxx插件开发新手教程3-普通
条评论前言
我们这一章节将会再深入了解amxx插件的开发,内容包括判断玩家是否存活、判断玩家是否持有武器等等,主要针对if判断语句、数组、预编译的处理。有疑问可以在文章底部留言。
判断if()
在插件中我们可以做上一些指定的条件来完成判断,根据判断结果来实现不同的功能
代码为if (条件),其中条件是我们需要填写的内容,我们还可以在通过这个判断后添加return,让其代码不往下执行。
示例并实践:
判断玩家是否存活
需调用模块: amxmodx.inc
需要用到的代码是is_user_alive(index)
返回值:如果存活返回1,否则 返回0
这里,我们还需要一个基础代码if ( ),中文是如果的意思,其中括号填入 需要判断的条件
index代表目标索引,意义为我们需要判断谁。
示例:
1 | if( is_user_alive(id) ) //如果玩家存活 |
如果我们需要判断这个玩家是否已经死亡,这里我们需要学到!反义标识(惊叹号),在判断条件的前面加入。
示例:
1 | if(!is_user_alive(id)) //如果玩家已经死亡 |
判断玩家持有武器
需调用模块: amxmodx.inc
我们可以判断玩家的当前手上的武器
武器对应ID我们需要参考编译器/include/amxconst.inc文件中。在此文件中有一个代码部分叫CSW_,这就是武器CSW ID号,比如:武器AK47的CSW_是CSW_AK47
判断玩家持有的武器,我们需要用到get_user_weapon(index)
该代码可以获取玩家持有的武器CSW序号,在这里我们 可以通过两个判断符来实现判断
1 | == //绝对等于 |
我们分别来看示例以及说明:
不同的判断方式
绝对等于(==)
他由两个等号组成(注意中间没有空格),我们需要做的是在条件和判断中间加上==即可
示例:
1 | if( get_user_weapon(id) == CSW_AK47) |
这样我们就判断了,如果玩家手上当前持有的是CSW_AK47那么继续括号中的client_print函数内容(发送信息给索引目标)
不等于(!=)
在一些情况下,我们可能需要判断 如果玩家手上的武器不是那个武器,这种情况下我们需要用到不等于 != 来实现目的,和绝对等于一样,插入的代码位置不变化。
示例:
1 | if(get_user_weapon(id) != CSW_AK47) //如果玩家手上的武器不是AK47 |
判断玩家所属阵营
需调用模块: amxmodx.inc
在一些情况下,我们需要判断 目标索引(index)所属的当前阵营是什么
这时候我们需要用到的代码是get_user_team(index)
该代码的返回值不止一个,他们分别是:
1 | 返回 0 //玩家没有选择阵营 |
和判断玩家持有武器一样,我们需要添加代码的也是==或者!=
示例:(如果玩家是CT阵营)
1 | if( get_user_team(id) == 2) |
多重判断
有时候我们需要判断多个条件,这时候我们就需要用到多重判断。
将的表达式代码&&(并且)或||(或者)添加到两个条件中来实现多重判断。(需要添加到两个条件中间)
像这种有目标指向性的思路,一般有两种或者多种写法。
比如: (CT或者T)或者(不是观察者 并且 不是没有选择阵营)
方式(1)
1 | if( get_user_team(id) == 1 || get_user_team(id) == 2) |
方式(2)
1 | if(get_user_team(id) != 0 && get_user_team(id) != 3) |
以上两种示例,都可达成共同的目的,可根据个人习惯来改变写法
数组([])
被定义的变量后面有[]并且里面含有数值的代码称之为 数组,比如:
1 | thismodel[33] |
数组默认中是没有数值的,也就是0
我们可以在后期给数组定义上去,其中[]中的内容代表需要给谁定义,也就是索引(index)。
比如玩家数量最大是32,我们就需要在数组中写上33,需要预留一位才行。
示例:
1 | iSave[33] |
数组可以帮我们做许多事情,比如开关
现在,我们来讲一下开关的写法
开关(on/off)
听上去是个很常见的东西,可是在代码中是怎么样的呢
开关:可以打开也可以关闭。即:触发一次打开再触发一次关闭
示例:
1 | if(switch[id]) |
是0话怎么样?这种情况下我们就需要动脑子了,仔细想想就明白了:思路 — 如果是0改成1,如果是1改成0
那么代码就是这样的:
1 | if(!switch[id]) |
清晰易懂对吧?那么现在已经实现了如果关闭就打开,那接下来的应该就是如果打开就关闭
示例:
1 | if(!switch[id]) |
如果我们以如上的代码思路来写,我们会遇到一个问题
是什么问题呢?我们翻译一下代码
- 如果关闭就打开
- 如果打开就关闭
这样乍看上去好像没什么不对,但是这里就是一个逻辑问题了,这种开关做上去就会出现这种问题:一旦开关刚刚打开马上就被关闭了
这种情况肯定是我们不想遇到的吧。那么应该怎么解决呢?
这里我们可以用到else if或者else来完成目的。
这两个的写法几乎一样,他和双重if的区别是只会被执行一次,而不是多次触发
方式 1:
1 | if(!switch[id]) |
方式 2:
1 | if(!switch[id]) |
这样我们就完成开关了else if和else这两种有额外的搭配写法,这里暂时不说
随机数
有一些情况下我们需要做一种特殊效果,他带有一种随机性,可以由插件自身来决定是否 可以继续执行
随机值分三种:
- 随机整数 (1)
1
random(2) //随机整数:最大值
- 随机整数(2)
1
random_num(1, 2) //随机整数:(最小值, 最大值)
- 随机浮点数
1
random_float(20.0, 140.0) //随机浮点数(最小值,最大值), 括号中需要填写浮点数
那么我们应该如何搭配呢?
示例: (1)
1 | if( random_num( 20, 60 ) > 45) |
示例:(2)
1 | if( random(25) == 14) |
注意:
random(最大值)中的最小值取0
预编译
预编译#define,在代码中可以将一个值表示为另一个值
例如:我们可以定义ABC = 1,或ABC = 一串信息
1 |
那这有什么用?
示例:
1 |
|
游戏时间
函数:get_gametime()
我们可以获取游戏时间(即:我们在游戏中呆了多久时间,按秒计算)。并且使用游戏时间可以帮助我们解决许多问题
代码是:get_gametime(),获取到的值是浮点数
比如我们在游戏中玩了5分钟,那么通过get_gametime()获取到的值就是300.0秒
我们甚至还可以配合数组存储来完成不可思议的效果
冷却间隔时间(CD)
示例:
1 |
|
小技巧:
我们可以通过游戏时间来判断是否大于或小于等于
如果是小于或等于即代表时间到了,反之 就代表时间还没到。
1 | if( SaveTime[id] <= get_gametime() ) |
注册客户端命令
我们可以为客户端注册一些命令,以触发一些特定函数
注册的代码为register_clcmd("注册什么命令", "触发什么函数")
示例:
1 | public plugin_init() |
上例中即代表 按控制台输入say /abc触发了the_func函数
注意:
- 当所填写的
被触发函数名不存在的时候,插件会出现runtime error错误(因为找不到被触发函数,所以插件不会继续正常工作)- 在
注册什么命令的地方必须添加""引号包围起来- 在
注册什么命令的地方设定的命令即控制台输入的命令。若是需要按Y键输入的命令则需要将命令最前面改为say- 若是一个之前被其他插件注册过的命令,却又重新注册一遍,此时你注册的新命令将不会工作,而只能使用之前被插件注册过的命令(简单说:无法在已经注册过的命令上重新注册一遍)
让客户端执行命令
我们可以让客户端执行一些指定的命令,比如丢弃武器drop, 切换到指定武器,甚至还可以让玩家发送一些Y键的文字信息让对方说话,如果不爽对方还可以让对方客户端强制退出游戏。
可是,这一切应该怎么实现?
这里我们需要用到client_cmd这个代码
他由三个参数组成:
- 让谁执行命令(index索引)
- 执行的命令是什么
- 附加的获取方式
一般我们用不到参数3, 写法如下
示例:
1 | client_cmd(id, "drop") //让玩家执行控制台的drop命令(丢弃武器,默认G键) |
那如果配合参数3应该怎么用?
一般我们用参数3是用来获取的一些数据,比如说:
1 | //踢出这个ID的玩家 |
注意:client_cmd只能给有效的客户端玩家执行,如果给非玩家(比如地图本身)那么就会出现控制台错误,无效的实体。