前言

我们这一章节将会再深入了解amxx插件的开发,内容包括判断玩家是否存活、判断玩家是否持有武器等等,主要针对if判断语句、数组、预编译的处理。有疑问可以在文章底部留言。

判断if()

在插件中我们可以做上一些指定的条件来完成判断,根据判断结果来实现不同的功能

代码为if (条件),其中条件是我们需要填写的内容,我们还可以在通过这个判断后添加return,让其代码不往下执行。

示例并实践:

判断玩家是否存活

需调用模块: amxmodx.inc

需要用到的代码是is_user_alive(index)

返回值:如果存活返回1,否则 返回0

这里,我们还需要一个基础代码if ( ),中文是如果的意思,其中括号填入 需要判断的条件

index代表目标索引,意义为我们需要判断谁。

示例:

1
2
3
if( is_user_alive(id) ) //如果玩家存活
{
}

如果我们需要判断这个玩家是否已经死亡,这里我们需要学到!反义标识(惊叹号),在判断条件的前面加入。

示例:

1
2
3
if(!is_user_alive(id)) //如果玩家已经死亡
{
}

判断玩家持有武器

需调用模块: amxmodx.inc

我们可以判断玩家的当前手上的武器

武器对应ID我们需要参考编译器/include/amxconst.inc文件中。在此文件中有一个代码部分叫CSW_,这就是武器CSW ID号,比如:武器AK47的CSW_是CSW_AK47

判断玩家持有的武器,我们需要用到get_user_weapon(index)

该代码可以获取玩家持有的武器CSW序号,在这里我们 可以通过两个判断符来实现判断

1
2
==     //绝对等于
!= //不等于

我们分别来看示例以及说明:

不同的判断方式

绝对等于(==)

他由两个等号组成(注意中间没有空格),我们需要做的是在条件和判断中间加上==即可

示例:

1
2
3
4
if( get_user_weapon(id) == CSW_AK47)
{
client_print(id, print_chat, "Your are Weapon AK47")
}

这样我们就判断了,如果玩家手上当前持有的是CSW_AK47那么继续括号中的client_print函数内容(发送信息给索引目标)

不等于(!=)

在一些情况下,我们可能需要判断 如果玩家手上的武器不是那个武器,这种情况下我们需要用到不等于 != 来实现目的,和绝对等于一样,插入的代码位置不变化。

示例:

1
2
3
4
if(get_user_weapon(id) != CSW_AK47) //如果玩家手上的武器不是AK47
{
client_print(id, print_chat, "i Current Weapon Not Using Ak47")
}

判断玩家所属阵营

需调用模块: amxmodx.inc

在一些情况下,我们需要判断 目标索引(index)所属的当前阵营是什么

这时候我们需要用到的代码是get_user_team(index)

该代码的返回值不止一个,他们分别是:

1
2
3
4
返回 0 //玩家没有选择阵营
返回 1 //阵营是T阵营
返回 2 //阵营是CT阵营
返回 3 //阵营是观察者

和判断玩家持有武器一样,我们需要添加代码的也是==或者!=

示例:(如果玩家是CT阵营)

1
2
3
if( get_user_team(id) == 2)
{
}

多重判断

有时候我们需要判断多个条件,这时候我们就需要用到多重判断。

将的表达式代码&&(并且)或||(或者)添加到两个条件中来实现多重判断。(需要添加到两个条件中间)

像这种有目标指向性的思路,一般有两种或者多种写法。

比如: (CT或者T)或者(不是观察者 并且 不是没有选择阵营)

方式(1)

1
2
3
if( get_user_team(id) == 1 || get_user_team(id) == 2)
{
}

方式(2)

1
2
3
if(get_user_team(id) != 0 && get_user_team(id) != 3)
{
}

以上两种示例,都可达成共同的目的,可根据个人习惯来改变写法

数组([])

被定义的变量后面有[]并且里面含有数值的代码称之为 数组,比如:

1
thismodel[33]

数组默认中是没有数值的,也就是0

我们可以在后期给数组定义上去,其中[]中的内容代表需要给谁定义,也就是索引(index)。

比如玩家数量最大是32,我们就需要在数组中写上33,需要预留一位才行。

示例:

1
iSave[33]

数组可以帮我们做许多事情,比如开关

现在,我们来讲一下开关的写法

开关(on/off)

听上去是个很常见的东西,可是在代码中是怎么样的呢

开关:可以打开也可以关闭。即:触发一次打开再触发一次关闭

示例:

1
2
3
if(switch[id])
{
}

是0话怎么样?这种情况下我们就需要动脑子了,仔细想想就明白了:思路 — 如果是0改成1,如果是1改成0

那么代码就是这样的:

1
2
3
4
if(!switch[id])
{
switch[id] = 1
}

清晰易懂对吧?那么现在已经实现了如果关闭就打开,那接下来的应该就是如果打开就关闭

示例:

1
2
3
4
5
6
7
8
if(!switch[id])
{
switch[id] = 1
}
if(switch[id])
{
switch[id] = 0
}

如果我们以如上的代码思路来写,我们会遇到一个问题
是什么问题呢?我们翻译一下代码

  1. 如果关闭就打开
  2. 如果打开就关闭

这样乍看上去好像没什么不对,但是这里就是一个逻辑问题了,这种开关做上去就会出现这种问题:一旦开关刚刚打开马上就被关闭了

这种情况肯定是我们不想遇到的吧。那么应该怎么解决呢?

这里我们可以用到else if或者else来完成目的。

这两个的写法几乎一样,他和双重if的区别是只会被执行一次,而不是多次触发

方式 1:

1
2
3
4
5
6
7
8
if(!switch[id])
{
switch[id] = 1
}
else if(switch[id])
{
switch[id] = 0
}

方式 2:

1
2
3
4
5
6
7
8
if(!switch[id])
{
switch[id] = 1
}
else
{
switch[id] = 0
}

这样我们就完成开关了
else if和else这两种有额外的搭配写法,这里暂时不说

随机数

有一些情况下我们需要做一种特殊效果,他带有一种随机性,可以由插件自身来决定是否 可以继续执行

随机值分三种:

  1. 随机整数 (1)
    1
    random(2)  //随机整数:最大值
  2. 随机整数(2)
    1
    random_num(1, 2)  //随机整数:(最小值, 最大值)
  3. 随机浮点数
    1
    random_float(20.0, 140.0) //随机浮点数(最小值,最大值), 括号中需要填写浮点数

那么我们应该如何搭配呢?

示例: (1)

1
2
3
4
if( random_num( 20, 60 ) > 45)
{
//如果在 (20, 60) 之间的随机结果大于 45
}

示例:(2)

1
2
3
4
if( random(25) == 14)
{
//如果在 (0, 40) 之间的随机结果刚好等于 14
}

注意:random(最大值)中的最小值取0

预编译

预编译#define,在代码中可以将一个值表示为另一个值

例如:我们可以定义ABC = 1,或ABC = 一串信息

1
#define ABC 123 //定义(标识,数据)

那这有什么用?

示例:

1
2
3
4
5
6
#include <amxmodx>
#define ShowInfo "这是一些信息"
public Show_Print(id)
{
client_print(id, print_chat, "ShowInfo: %s", ShowInfo)
}

游戏时间

函数:get_gametime()

我们可以获取游戏时间(即:我们在游戏中呆了多久时间,按秒计算)。并且使用游戏时间可以帮助我们解决许多问题

代码是:get_gametime(),获取到的值是浮点数

比如我们在游戏中玩了5分钟,那么通过get_gametime()获取到的值就是300.0秒

我们甚至还可以配合数组存储来完成不可思议的效果

冷却间隔时间(CD)

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <amxmodx>
new Float:SaveTime[33]
public plugin_init()
{
register_plugin("插件演示", "1.0", "Hui")
register_clcmd("say /test", "func_test")
}
public test(id)
{
new Float:LeftTime = SaveTime[id] - get_gametime()
if(LeftTime > 0.0)
{
client_print(id, print_chat, "冷却时间剩余: %.0f秒", LeftTime)
}
SaveTime[id] = get_gametime() + 2.0
}

小技巧:
我们可以通过游戏时间来判断是否大于或小于等于
如果是小于或等于即代表时间到了,反之 就代表时间还没到。

1
2
3
4
5
6
7
8
if( SaveTime[id] <= get_gametime() ) 
{
//时间到了
}
else
{
//时间没到
}

注册客户端命令

我们可以为客户端注册一些命令,以触发一些特定函数

注册的代码为register_clcmd("注册什么命令", "触发什么函数")

示例:

1
2
3
4
5
6
7
8
public plugin_init()
{
register_clcmd("say /abc", "the_func")
}
public the_func(id)
{
client_print(id, print_chat, "触发函数成功")
}

上例中即代表 按控制台输入say /abc触发了the_func函数

注意:

  1. 当所填写的被触发函数名不存在的时候,插件会出现runtime error错误(因为找不到被触发函数,所以插件不会继续正常工作)
  2. 在注册什么命令的地方必须添加""引号包围起来
  3. 在注册什么命令的地方设定的命令即控制台输入的命令。若是需要按Y键输入的命令则需要将命令最前面改为say
  4. 若是一个之前被其他插件注册过的命令,却又重新注册一遍,此时你注册的新命令将不会工作,而只能使用之前被插件注册过的命令(简单说:无法在已经注册过的命令上重新注册一遍)

让客户端执行命令

我们可以让客户端执行一些指定的命令,比如丢弃武器drop, 切换到指定武器,甚至还可以让玩家发送一些Y键的文字信息让对方说话,如果不爽对方还可以让对方客户端强制退出游戏。

可是,这一切应该怎么实现?

这里我们需要用到client_cmd这个代码

他由三个参数组成:

  1. 让谁执行命令(index索引)
  2. 执行的命令是什么
  3. 附加的获取方式

一般我们用不到参数3, 写法如下

示例:

1
client_cmd(id, "drop") //让玩家执行控制台的drop命令(丢弃武器,默认G键)

那如果配合参数3应该怎么用?

一般我们用参数3是用来获取的一些数据,比如说:

1
2
//踢出这个ID的玩家
client_cmd(id, "kick #%d", get_user_userid(id))

注意:client_cmd只能给有效的客户端玩家执行,如果给非玩家(比如地图本身)那么就会出现控制台错误,无效的实体。

参考文献

Lv.2 普通 - AMXX插件编写教程