Friday, June 6, 2014

set_tasks: when they are and when they aren't necessary

Hướng dẫn này là để dành cho người mới bắt đầu scripters độ trung cấp. 

set_task đôi khi có thể là một chức năng cực kỳ hữu ích, nhưng đôi khi nó thực sự là quá mức cần thiết. Những gì ít người biết là nó là một hoạt động rất tốn kém, CPU phải theo nghĩa đen mỗi chu kỳ kiểm tra nếu nó là thời gian cho các set_task được thực thi. Thông thường, có những cách xung quanh một set_task. 

set_task cũng có những hạn chế của việc không thể được gọi là nhiều hơn mỗi 0,1 giây. Điều này có nghĩa rằng nếu bạn vượt qua 0.01 trong tham số 1, nó sẽ được kẹp ở mức 0.1. 

Nhưng những gì chúng ta có thể làm gì để tránh nó? Đôi khi bạn thực sự phải sử dụng một set_task, chẳng hạn như ở đây:

Code:
#include <amxmodx> #include <amxmisc> #include <engine> public plugin_init() {     register_plugin("ROFL","1.0","Hawk552")         register_event("ResetHUD","EventResetHUD","be") } public EventResetHUD(id)     set_task(1.0,"DelayedResetHUD",id)     public DelayedResetHUD(id)     DispatchSpawn(id)

Nhưng tại sao? Không có cách nào thực sự để thoát khỏi trì hoãn hàm một lần mà không làm một cái gì đó CPU chuyên sâu hơn hoặc không đáng tin cậy. Chúng ta có thể tạo ra một ent và làm cho nó nghĩ rằng trong 1 giây (mà sẽ được đề cập sau), nhưng đó không phải chỉ cho biết thêm một unnecissary đẻ trứng cho một điều nhỏ như vậy, nó cũng là không đáng tin cậy hơn (ví dụ như máy chủ có thể sụp đổ do có quá nhiều ENT , hoặc nó có thể được không được sinh ra và các chức năng đơn giản là phải kết thúc ở đó).

Nhưng có những lúc khác, nơi mà thoát khỏi một set_task không chỉ dễ dàng hơn, nhưng tiêu thụ ít tài nguyên.

Một trong những cách thường được gọi để làm điều này là client_PreThink về phía trước / FM_PlayerPreThink. Chuyển tiếp này được gọi là mỗi khung hình trên một khách hàng trước khi vẽ vật lý. Ở phía trước này, bạn sẽ làm những điều mà thường phải được cập nhật liên tục, như tốc độ hoặc thay đổi rendering.

Đây là một ví dụ:

Code:
#include <amxmodx> #include <amxmisc> #include <engine> public plugin_init()     register_plugin("ROFL","1.0","Hawk552") public client_PreThink(id) {     static Float:Velocity[3]     entity_get_vector(id,EV_VEC_velocity,Velocity)         Velocity[2] = -floatabs(Velocity[2])         entity_set_vector(id,EV_VEC_velocity,Velocity) }

Tại sao là một set_task không phù hợp đây? Vì hai lý do: 1) engine hlaf life sẽ cho phép bạn có giờ nào (ở một mức độ khác nhau), và 2) nó sẽ trông rất glitchy vì nếu khách hàng có 60 FPS, máy chủ chỉ kiểm tra tất cả 10 khung hình nếu vận tốc của họ là những gì nó cần.

Một trong những cách ít được tập luyện để tránh set_tasks là để tạo ra một thực thể, thiết lập nextthink để bất cứ điều gì bạn muốn, và register_think / FM_Think nó. Nhưng khi điều này là cần thiết? Khá nhiều bất cứ khi nào bạn sử dụng "b" lá cờ trong set_task, nó tốt hơn để sử dụng phương pháp này. Nó cũng ưa thích khi bạn đã sinh ra một thực thể (chẳng hạn như một NPC) và muốn làm cho nó nói, biến mất, trong x giây.

Đây là một ví dụ:
Engine:
Code:
#include <amxmodx> #include <amxmisc> #include <engine> new g_Classname[] = "roflmao" public plugin_init() {     register_plugin("ROFL","1.0","Hawk552")         new Ent = create_entity("info_target")     entity_set_string(Ent,EV_SZ_classname,g_Classname)     entity_set_float(Ent,EV_FL_nextthink,20.0)         register_think(g_Classname,"RoflmaoThink") } public RoflmaoThink(Ent) {     log_amx("ROFLMAO thinks.")         entity_set_float(Ent,EV_FL_nextthink,20.0) }

Fakemeta:

Code:
#include <amxmodx> #include <amxmisc> #include <fakemeta> new g_Classname[] = "roflmao" public plugin_init() {     register_plugin("ROFL","1.0","Hawk552")         new Ent = engfunc(EngFunc_CreateNamedEntity,engfunc(EngFunc_AllocString,"info_target"))     set_pev(Ent,pev_classname,g_Classname)     set_pev(Ent,pev_nextthink,20.0)         register_forward(FM_Think,"ForwardThink") } public ForwardThink(Ent) {     static Classname[33]     pev(Ent,pev_classname,Classname,32)         if(!equal(Classname,g_Classname))         return FMRES_IGNORED         log_amx("ROFLMAO thinks.")         set_pev(Ent,pev_nextthink,20.0)         return FMRES_IGNORED }

Điều này rất hữu ích, như đã nói, cho thoát việc sử dụng lá cờ "b" trên set_task, hoặc thực hiện set_task vào cuối hàm gọi.

Cách cuối cùng để thoát khỏi một set_task là khi sử dụng thời gian hồi chiêu. Ví dụ, bạn muốn có một người chơi để có thể sử dụng một cuộc tấn công đặc biệt mỗi 30 giây.

Code:
#include <amxmodx> #include <amxmisc> #include <fakemeta> // this is how often you want your players to be able to use your attack #define ATTACK_COOLDOWN 20.0 new Float:g_LastAttack[33] // optimization new Float:g_Cooldown = ATTACK_COOLDOWN public plugin_init() {     register_plugin("ROFL","1.0","Hawk552")         register_clcmd("myattack","CmdMyAttack") } public CmdMyAttack(id) {     // to use engine instead, use this:     /* new Float:Time = halflife_time() */     new Float:Time     global_get(glb_time,Time)            if(!is_user_alive(id) || Time - g_Cooldown < g_LastAttack[id])         return         g_LastAttack[id] = Time         // your code here }

Tôi sẽ không để đẩy này nữa, vì vậy nếu bạn có bất kỳ câu hỏi về nó sau đó cảm thấy tự do để yêu cầu.

0 nhận xét:

Post a Comment