mythkina 发表于 2008-7-6 16:17:41

set_task的详细使用方法讨论

现在论坛搜索功能有问题,即使点了搜索主题还是会去搜索整个帖子,结果列出14页,不想挨个看了...

已知的:
Syntax:

   set_task ( Float:time, const function[], id = 0, parameter[]="", len = 0, flags[]="", repeat = 0 )
Type:

    Native
Notes:

The parameters break down as such:

* Float:time - Interval of timer in second. (minimum 0.1 seconds)
* function[] - A string that contains the public function to run on the timer.
* id - A unique id to assign to the task.
* parameter - An array contain data to send to the timer function.
* len - Size of the array to send to the timer function.
* flags - One of the following:
-- "a" - Repeat task a specified number of times
-- "b" - Loop task infinitely
-- "c" - do task on time after a map timeleft
-- "d" - do task on time before a map timeleft
* repeat - If flags is "a", specifies the number of times to repeat the task.


Remember that functions executed by set_task needs be public.


Example of executing a task once:

set_task(15.0,"MyFunction")




这些是我目前了解的
// This will call the Function 'MyFunction' 5 Times
// (NOT 6 Times) every 60 Seconds and send the Variable 'id':

public test1(id)
{
    set_task(60.0,"MyFunction",id,"",0,"a",5)
}


// This will call the Function 'MyFunction'
// every 30 Seconds and send the Variable 'id':

public test2(id)
{
    set_task(30.0,"MyFunction",id,"",0,"b")
}

问题:
set_task ( Float:time, const function[], id = 0, parameter[]="", len = 0, flags[]="", repeat = 0 )
1.一个插件2个任务的id冲突了,比如都是语句 id = 0 会出现什么情况
2.Float:time既然是间隔(interval) 那么当执行到
public plugin_cfg() {
       set_task(5.0,....)时是马上执行task标识的fun()一次还是50秒后才执行
}
3.如果 func1() {
new arg;
arg = 1;arg = 2;
set_task(time,func2,id = 0,arg,len = 0,...)
} 会出现什么情况? 也就是说我不太清楚这里len和arg的相互影响关系是怎样的?
4.如果设置了 "b",然后repeat = 0 会出现什么情况? "c","d"都是怎样用的呢?
-- "b" - Loop task infinitely
-- "c" - do task on time after a map timeleft
-- "d" - do task on time before a map timeleft
5.如果我只设置 set_task(2.0,func)会是什么样的执行表现呢? 也就是说在不设置flags和repeat的情况下这个task会怎样的去执行func呢?
再有,如果我都用这种默认的,比如:
set_task(2.0,func1)
set_task(2.0,func2)
那么是否会出现taskid冲突导致amxx或者hlds崩溃呢?
6.暂时问这么多,给大家带来的不便请见谅,请各位多指教,最近在看代码``

jim_yang 发表于 2008-7-6 18:23:01

回复: set_task的详细使用方法讨论

答案就是三个字,动手试

不过我可以简要概括一下task的原理,希望对你有帮助。

task的原理是:
amxx在服务器每一帧来计算当前的游戏时间(halflift time),存入一个变量,每次加0.1秒(也就是interval的最小单位),然后和上次存入的变量进行比较,如果超过了0.1秒,也就是说明在当前服务器这一帧的时间到了0.1秒,因此set_task的方法确定的时间是不准确的,当然在秒一级的单位还是准确的,因为通常服务器一桢的时间间隔会小于0.1,也就是说在0.1秒内服务器多次对这个时间变量进行比较。

jim_yang 发表于 2008-7-6 18:29:07

回复: set_task的详细使用方法讨论

当你设定的任务间隔时间加设置任务时的初始时间大于当前时间时,即任务到达时间,这个任务就要被执行了。
任务设置时amxx会自动非配任务id,如果你没有特殊声明的话。
任务id只在移除和改变任务时才有作用,其他情况下可以省略。
任务在内存中的形式是由开辟新的内存空间来对已知函数重载得到的一个新函数,所以即使你不设置任务号,amxx也会正确执行。

jim_yang 发表于 2008-7-6 18:33:31

回复: set_task的详细使用方法讨论

要是服务器运行顺畅,应尽量减少task的次数,能不用就不用,因为一旦你设置了任务,amxx就会将其加入任务队列,之后每隔0.1秒就会循环一遍所有任务,检查是否到了时间,所以你设置的任务越多,cpu的工作量就越大。

这个道理同样适用于注册 命令,事件,消息
register_clcmd register_event register_message

jim_yang 发表于 2008-7-6 18:37:59

回复: set_task的详细使用方法讨论

另外,你会看到amxx的api提供的函数原型会有一些确实参数,比如这个函数里的
set_task ( Float:time, const function[], id = 0, parameter[]="", len = 0, flags[]="", repeat = 0 )

id = 0, parameter[]="", len = 0, flags[]="", repeat=0
实际上你调用一个函数
set_task(1.0, "function")
相当于
set_task(1.0, "function", 0, "", 0, "", 0)

而amxx会对这些缺省的参数值进行判断处理

Cr@zyTreE 发表于 2008-7-6 21:02:04

回复: set_task的详细使用方法讨论

这样讲的话sxei_required2岂不是很耗费资源?
看你的小鸡炸弹插件,也就是换炸弹模型。
我想这么写个插件:主要功能-我现在用sxe_req是将没开sxe的玩家只能拿刀.我想去掉这个插件。写一个插件检测玩家没开sxe的话就变成小鸡。
定期检测还是会比较耗费资源哦。
所以我这样想:
玩家加入服务器(状态:活着)或者每局开始的时候把当前武器变成刀,
随后判断玩家武器,如过玩家切换武器且id中有标识的话,就把玩家的模型换成小鸡。这样的话就不用set_task了。是不是好些。
不知道有没有更好的方法。



#include <amxmodx>
#include <fakemeta>
#define PLUGIN "Test"
#define AUTHOR "Jim"
#define VERSION "1.0"
new const chick[] = "models/chick.mdl"

public plugin_precache()
{
precache_model(chick)
}

public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
register_forward(FM_SetModel, "fwd_setmodel")
}
public fwd_setmodel(ent, const m[])
{
if(pev_valid(ent) && pev(ent, pev_owner)
&& m == 'w' && m == '_' && m == 'h')
{
set_pev(ent, pev_model, chick)
return FMRES_SUPERCEDE
}
return FMRES_IGNORED
}

mythkina 发表于 2008-7-6 22:02:49

回复: set_task的详细使用方法讨论

非常感谢jim_yang给小弟的hint~
诚如您所说,确实是自己调试是最直观的解决方式~
不过能了解一下实现细节也是很幸福滴``
没仔细看过pawn,以为它和c很像,没想到还有c++的重载机制...
不知道这些重载函数的栈是amxx提供的自己的数据结构还是操作系统的栈
感觉多task的时候放栈里,很难做到哪个到了运行哪个重载函数并pop的机制吧..不解

ps:对于task的实现细节不知jim大是从那里看到的呢,偶也想进一步了解一下的说``

jim_yang 发表于 2008-7-6 22:07:04

回复: set_task的详细使用方法讨论

写的时候没仔细检查,发现我的回复有好多错词,将就着看吧。

要想不费cpu几乎是不可能的,具体问题需要你自己权衡。
如果感觉服务器运行不顺畅,就要考虑精简和优化组合插件了。

现在来简要介绍一下register_clcmd的原理:
其实amxx同样是将所有注册的命令放入一个队列,由一个类实现。
然后通过hook引擎函数client_command,每一次客户端向服务器发送一个命令,比如 weapon_knife,amxx就要查找队列里的所有注册的命令字符串,比较是不是当前命令,如果是就执行注册命令时给定的函数。
所以,你注册的命令越多,cpu负荷越大,虽然比较字符串这种操作对于现有运算数量级来说不算什么,但是由于client_command操作频繁,因此还是有必要精简一下。

注册命令的返回值有 plugin_continue,返回给metamod 表示此时这个command没有做实际的工作,plugin_handled表示做了工作,命令到此结束,不再继续向metamod其他插件传送。

jim_yang 发表于 2008-7-6 22:11:01

回复: set_task的详细使用方法讨论

实现机制确实是amxx内核来完成的工作,当然是c++来实现的
想具体了解请看amxx源代码

52yz 发表于 2008-7-6 22:53:50

回复: set_task的详细使用方法讨论

受教了,收藏了:super:
页: [1] 2
查看完整版本: set_task的详细使用方法讨论