Công cụ thành viên

Công cụ trang web


script:feature:mini_world_api:how_to_get_trigger_variables

Lấy biến Trigger bằng cách sử dụng script

Danh sách thuộc tính hành động (ActionAttr)

Tên (Name) Giá trị (Value) Mô tả (Description)
Position 1 Vị trí
AreaIns 2 Khu vực
Number 3 Giá trị
String 4 Chuỗi
Boolean 5 Đúng/Sai (Boolean)
Player 6 Người chơi
PlayerGrout 7 Nhóm người chơi
BlockType 8 Loại khối
ItemType 9 Loại vật phẩm
Creature 10 Sinh vật
ActorID 11 Loại nhân vật
CreatureGroup 12 Nhóm sinh vật
Timer 13 Hẹn giờ
EffectType 14 Loại hiệu ứng đặc biệt
SiteGroup 15 Nhóm vị trí
AreaGroup 16 Nhóm khu vực
NumberGroup 17 Nhóm giá trị
StringGroup 18 Nhóm chuỗi
BooleanGroup 19 Nhóm đúng/sai
BlockTypeGroup 20 Nhóm loại khối
ItemTypeGroup 21 Nhóm loại vật phẩm
CreatureTypeGroup 22 Nhóm loại sinh vật
TimerGroup 23 Nhóm hẹn giờ
EffectTypeGroup 24 Nhóm loại hiệu ứng

Tại sao bạn lại muốn lấy các biến trigger?

Nếu bạn đang theo dõi hướng dẫn này, rất có thể bạn muốn tạo game bằng cách kết hợp cả script và trigger – tận dụng ưu điểm của cả hai. Và thực tế, có những phương pháp giúp chúng ta làm được điều đó.
Việc lấy biến trigger cũng rất hữu ích vì bạn có thể sử dụng chúng như biến dùng chung giữa các script. Mini World không hỗ trợ phương thức require, vì vậy đây là một giải pháp thay thế tuyệt vời, cho phép bạn truy cập và sử dụng các biến có thể dùng chung trong mọi script.

Cách lấy biến toàn cục (global variables)

Để lấy các biến toàn cục thì rất dễ vì chúng ta có các phương thức để làm điều đó.

getGlobalVarByName: như bạn có thể đoán từ tên gọi, cho phép bạn lấy giá trị của một biến toàn cục.

setGlobalVarByName: cho phép bạn thay đổi giá trị của một biến toàn cục.

getGlobalVarByName

Hãy nói về phương thức này trước. Phương thức này nhận vào hai tham số:

  • actionattr: số (Kiểu của biến)
  • msg: chuỗi (Tên của biến)

Và trả về:

Chúng ta sẽ làm một ví dụ sử dụng sau khi giải thích phương thức tiếp theo.

setGlobalVarByName

Phương thức này thay đổi giá trị của biến trigger mà chúng ta đã cung cấp. Nó nhận vào ba tham số:

  • actionattr: số (Kiểu của biến)
  • msg: chuỗi (Tên của biến)
  • val: (phụ thuộc vào actionattr)

Và trả về:

Ví dụ sử dụng

Giả sử chúng ta muốn rằng khi một sinh vật bị đánh bại, một biến sẽ tăng lên 1. Chúng ta sẽ làm phần đó bằng trigger. Và khi biến đó lớn hơn hoặc bằng năm, chúng ta sẽ gửi một tin nhắn đến tất cả người chơi với nội dung “Bạn đã thắng!”, sau đó đặt lại biến đó về 0. Chúng ta sẽ làm phần đó bằng script.

Trigger


Script

Chúng ta bắt đầu bằng cách tạo một hàm, trong hàm này không cần tham số, rồi thêm Listener với sự kiện Actor.Die (Sinh vật chết) và hàm mà chúng ta vừa tạo. Mình sẽ không đi sâu chi tiết phần này vì nó đã được giải thích trong hướng dẫn về sự kiện Sử dụng sự kiện Mini World API.

Đoạn mã sẽ trông như thế này:

function CreatureDefeated()
 
end
 
ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated)

Sau đó, chúng ta thêm vào hàm phương thức getGlobalVarByName(actionattr, msg), như đã giải thích ở đầu hướng dẫn này.Tham số actionattr là kiểu của biến mà chúng ta muốn lấy. Có thể bạn sẽ thắc mắc làm sao biết được kiểu đó, và câu trả lời là bảng này chứa tất cả các kiểu biến có thể có cùng với giá trị của chúng.

Bảng

Tên Giá trị Mô tả
Position 1 Vị trí
AreaIns 2 Khu vực
Number 3 Giá trị
String 4 Chuỗi
Boolean 5 Giá trị đúng/sai (Boolean)
Player 6 Người chơi
PlayerGrout 7 Tập hợp người chơi
BlockType 8 Loại khối
ItemType 9 Loại vật phẩm
Creature 10 Sinh vật
ActorID 11 Loại nhân vật
CreatureGroup 12 Tập hợp sinh vật
Timer 13 Bộ hẹn giờ
EffectType 14 Loại hiệu ứng đặc biệt
SiteGroup 15 Nhóm vị trí
AreaGroup 16 Nhóm khu vực
NumberGroup 17 Nhóm giá trị
StringGroup 18 Nhóm chuỗi
BooleanGroup 19 Nhóm giá trị đúng/sai
BlockTypeGroup 20 Nhóm loại khối
ItemTypeGroup 21 Nhóm loại vật phẩm
CreatureTypeGroup 22 Nhóm loại sinh vật
TimerGroup 23 Nhóm bộ hẹn giờ
EffectTypeGroup 24 Nhóm loại hiệu ứng

Biến của tôi là kiểu số, nên actionattr là 3. Nhưng sau khi xem bảng, có thể bạn sẽ thắc mắc, còn tham số msg thì sao? Nó chính là tên của biến mà chúng ta muốn lấy. Biến mà tôi tạo có tên là “MyTestVal”, nên msg tôi phải dùng là “MyTestVal”. Nhưng nếu tên biến của bạn khác, thì bạn phải dùng tên biến của bạn làm msg.

Các lỗi thường gặp:

function CreatureDefeated() 
    local result = VarLib2:getGlobalVarByName(3,"MyTestVal")
end
 
ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated)

Lỗi này khá phổ biến, vì getGlobalVarByName trả về 2 giá trị (mã lỗi và giá trị) thay vì chỉ trả về giá trị. Nếu bạn cố gắng dùng biến kết quả result thì sẽ nhận được hoặc là 0 (ErrorCode.OK – không có lỗi), hoặc là 1001 (ErrorCode.FAILED – có lỗi xảy ra). Cách sửa là bạn phải khai báo thêm một biến nữa, ví dụ: local result, value = VarLib2:getGlobalVarByName(3, “MyTestVal”)

Mẹo: Nếu bạn không dùng một biến nào đó được trả về bởi bất kỳ phương thức nào, bạn có thể dùng dấu gạch dưới _ thay cho tên biến đó. Dấu “_” báo cho Lua biết biến đó sẽ không được sử dụng. Bạn có thể dùng “_” nhiều lần, ví dụ:

_, _, PlayerList = World:getAllPlayers(-1)

Còn nếu bạn không dùng “_” thì phải khai báo như thế này:

result, PlayerNum, PlayerList = World:getAllPlayers(-1)

Đoạn mã sẽ trông như thế này:

function CreatureDefeated() 
    local result, value = VarLib2:getGlobalVarByName(3,"MyTestVal")
end
 
ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated)

Hoặc

function CreatureDefeated() 
    local _, value = VarLib2:getGlobalVarByName(3,"MyTestVal")
end
 
ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated)

Cả hai cách đều giống nhau, nhưng cách trước tốt hơn nếu bạn muốn xử lý các lỗi có thể xảy ra. Sau đó, chúng ta thêm một câu lệnh if kiểm tra xem value có lớn hơn hoặc bằng 5 không, nếu đúng thì gửi tin nhắn cho người chơi với nội dung “You won!” và đồng thời đặt lại biến của chúng ta về 0. Phương thức setGlobalVarByName cũng có actionattr và msg, nên ta có thể sao chép từ getGlobalVarByName, nhưng tham số cuối cùng (val) là giá trị mà ta muốn biến đó có, trong trường hợp này là 0.

Đoạn mã sẽ trông như thế này:

function CreatureDefeated() 
    local result, value = VarLib2:getGlobalVarByName(3,"MyTestVal")
    if value >= 5 then
 
        Chat:sendSystemMsg("You won!", 0)
        VarLib2:setGlobalVarByName(3,"MyTestVal",0)
 
    end
end
 
ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated)

Hoặc

function CreatureDefeated() 
    local _, value = VarLib2:getGlobalVarByName(3,"MyTestVal")
    if value >= 5 then
 
        Chat:sendSystemMsg("You won!", 0)
        VarLib2:setGlobalVarByName(3,"MyTestVal",0)
 
    end
end
 
ScriptSupportEvent:registerEvent([=[Actor.Die]=], CreatureDefeated)

Cách lấy biến (biến riêng) của người chơi

Giống như với biến toàn cục, với biến riêng của người chơi cũng có các phương thức cho phép ta lấy giá trị được lưu trong đó. Các phương thức này đều theo cùng một cấu trúc như phương thức với biến toàn cục, chỉ có khác là ta phải chỉ định trước id của người chơi mà ta muốn lấy biến riêng của họ.

getPlayerVarByName

Lần này chúng ta sẽ nói về phương thức tương tự của getGlobalVarByName nhưng dành cho biến riêng. Phương thức này nhận ba tham số:

  • objid: number (UID của người chơi mà ta sẽ lấy giá trị biến)
  • actionattr: number (Kiểu của biến)
  • msg: string (Tên của biến)

Và trả về:

Chúng ta sẽ làm ví dụ sử dụng sau khi giải thích phương thức tiếp theo.

setPlayerVarByName

Phương thức này thay đổi giá trị của biến riêng mà ta đã chỉ định cho người chơi có UID mà ta cung cấp. Nó nhận bốn tham số:

  • objid: number (UID của người chơi mà ta sẽ thay đổi giá trị biến)
  • actionattr: number (Kiểu của biến)
  • msg: string (Tên của biến)
  • val (Tùy thuộc vào actionattr)

Và trả về:

Ví dụ sử dụng

Lần này chúng ta sẽ làm một điều khác, với các script ta sẽ làm tương tự, khi một người chơi đánh bại một con quái vật, ta sẽ cộng thêm 1 vào số quái vật mà người chơi đó đã đánh bại, và khi người chơi đánh bại được một số lượng quái vật, giả sử là 5, ta sẽ hiển thị thông báo “{PlayerNickname} đã lên cấp” trong đó {PlayerNickname} là chỗ dành sẵn cho tên của người chơi.

Trigger


Script

Bây giờ, để làm điều này, chúng ta sẽ cần hiểu rõ hơn một chút về các kiến thức cơ bản vì chúng ta sẽ sử dụng một thứ gọi là vòng lặp for dạng số (thêm thông tin tại trang Lua numeric for page) và vòng lặp while (thêm thông tin tại trang while loop).

Chúng ta bắt đầu giống như ví dụ trước, tạo một hàm không cần đối số, thêm Listener và thêm một vòng lặp while true bên trong hàm đó. Mã sẽ trông giống như sau:

function CreatureDefeated() 
    while true do
 
    threadpool:wait(1)
 
    end
end
 
ScriptSupportEvent:registerEvent([=[Game.Start]=], CreatureDefeated)

Hàm threadpool:wait(seconds) rất quan trọng vì nếu chúng ta không thêm nó, trò chơi có thể bị treo. Sau đó, chúng ta thêm vào trong vòng lặp while hàm World:getAllPlayers(-1) — -1 có nghĩa là tất cả người chơi — và chúng ta thêm ba biến vì phương thức này trả về:

  • Số lượng người chơi
  • Một danh sách chứa tất cả ID của người chơi

Nhưng chúng ta chỉ cần danh sách ID. Sau đó, chúng ta thêm một vòng lặp for dạng số với i = 1, PlayerListLength và bên trong vòng lặp đó, chúng ta thêm phương thức getPlayerVarByName. Chúng ta đã biết cách lấy actionattr và msg, vì vậy sau khi hiện đoạn mã, chúng ta sẽ truyền objid.
Mã sẽ trông giống như sau:

function CreatureDefeated() 
    while true do
    local _,_,PlayerList = World:getAllPlayers(-1)
 
 
    for i=1, #PlayerList do 
        local result, value = VarLib2:setPlayerVarByName(PlayerList[i],3,"MyPrivateTestVar") 
        Chat:sendSystemMsg(value)
    end
 
    Trigger:wait(1)
 
    end
end
 
ScriptSupportEvent:registerEvent([=[Game.Start]=], CreatureDefeated)

Sau khi xem đoạn mã, bạn có thể thắc mắc, tại sao chúng ta lại dùng PlayerList[i], câu trả lời nằm ở cách vòng lặp for hoạt động. Vòng lặp for hoạt động như sau: for initialvalue, endvalue, increment, trong đó:

  • initialvalue là giá trị ban đầu mà chúng ta gán cho i
  • endvalue là giá trị mà i sẽ tăng đến, và khi chạm đến giá trị này thì vòng lặp sẽ dừng
  • increment là phần tùy chọn, nếu không khai báo thì mặc định sẽ là 1

Giá trị # tương đương với độ dài của một bảng (table), vì vậy chúng ta đang nói rằng giá trị bắt đầu của i là 1 và giá trị kết thúc là độ dài của PlayerList (số lượng người chơi hiện tại). Vậy nếu có 4 người chơi, thì độ dài của PlayerList sẽ là 4, do đó, vòng lặp sẽ chạy cho đến khi i bằng giá trị kết thúc (chạy 4 lần). Vậy [i] nghĩa là gọi phần tử ở vị trí i trong bảng.
Hãy xem một ví dụ nhỏ:

Người chơi Vị trí trong bảng
NotSoPr17 1
PvpGamesAreGreat 2
MiniWorldPlayer 3
ILoveMiniWorld 4

Vậy ta biết có 4 người chơi nên độ dài playerlist sẽ là 4, sau đó ta thực hiện câu lệnh for.

for i=1, #playerlist (we know playerlist is 4 so it will be executed and i will increment by 1 until i is equal to 4)
 
i -> 1 (NotSoPr17)
i -> 2 (PvpGamesAreGreat)
i -> 3 (MiniWorldPlayer)
i -> 4 (ILoveMiniWorld)

Vậy nói đơn giản thì PlayerList[i] chính là ID của người chơi ở vị trí thứ i trong bảng.

Sau đó, chúng ta thêm một câu lệnh if để kiểm tra xem giá trị biến của người chơi có lớn hơn hoặc bằng 5 hay không. Đoạn mã lúc này sẽ trông giống như sau:

function CreatureDefeated() 
    while true do
    local _,_,PlayerList = World:getAllPlayers(-1)
 
 
    for i=1, #PlayerList do 
        local result, value = VarLib2:setPlayerVarByName(PlayerList[i],3,"MyPrivateTestVar")
 
        if value >= 5 then
 
        end
 
    end
 
    threadpool:wait(1)
 
    end
end
 
ScriptSupportEvent:registerEvent([=[Game.Start]=], CreatureDefeated)

Sau đó, khi một người chơi đánh bại hơn 5 quái vật hoặc người chơi khác, đoạn mã bên trong câu lệnh if sẽ được thực thi. Tiếp theo, ta thêm dòng local _, playerNick = Player:getNickname(PlayerList[i]) để lấy tên hiển thị (nickname) của người chơi hiện tại, và chúng ta tạo một hàm nhận vào nội dung (content) và danh sách người chơi (playerlist) để hiển thị một thông báo cho họ. Hàm này sẽ sử dụng vòng lặp for để làm việc đó.

Hàm sẽ trông giống như thế này:

function SendToAllPlayers(content,funcplayerlist) 
 
    for i=1, #funcplayerlist do
        Chat:sendSystemMsg(content, funcplayerlist[i])
    end
 
end

Sau đó, ta thêm vào trong câu lệnh if phần kiểm tra xem giá trị có lớn hơn hoặc bằng 5 hay không, và sử dụng hàm setPlayerVarByName với objidPlayerList[i].

Nếu bạn đang cảm thấy bối rối — điều này hoàn toàn bình thường khi học một cái gì đó mới — thì dưới đây là đoạn mã ví dụ để bạn tham khảo:

function SendToAllPlayers(content,funcplayerlist) 
 
    for i=1, #funcplayerlist do
        Chat:sendSystemMsg(content, funcplayerlist[i])
    end
 
end
 
function CreatureDefeated() 
    while true do
    local _,_,PlayerList = World:getAllPlayers(-1)
 
 
    for i=1, #PlayerList do 
        local result, value = VarLib2:getPlayerVarByName(PlayerList[i],3,"MyPrivateTestVar")
 
        if value >= 5 then
 
            local _,playerNick = Player:getNickname(PlayerList[i]) 
            SendToAllPlayers(playerNick .. " has leveled up!", PlayerList)
            VarLib2:setPlayerVarByName(PlayerList[i],3,"MyPrivateTestVar",0)
        end
 
    end
 
    threadpool:wait(1)
 
    end
end
 
ScriptSupportEvent:registerEvent([=[Game.Start]=], CreatureDefeated)

script/feature/mini_world_api/how_to_get_trigger_variables.txt · Sửa đổi lần cuối: 2025/05/16 09:08 bởi leo