Tom_Kazansky
<b><font color="RoyalBlue"><font face="Lucida Cons
- 28/12/06
- 3,454
- 462
Trong tutorial này, tôi (Andrewgosu) sẽ giới thiệu cơ bản về sử dụng struct. Làm thế nào để tạo, xóa, "gắn" (attach = gắn) và các thao tác với struct.
Để tiếp tục, bạn cần:
- World Editor
- Jass NewGen Pack
- Hiểu biết ở mức trung bình về Jass
Các bước mà tôi định dạy:
- Struct là gì và làm thế nào để khai báo một struct
- Thêm các "component" ( "thành phần", nghe ko hay lắm, hay dịch là "phần tử" đi) cho một struct
- Tạo một struct trong một hàm và truy nhập các phần tử của một struct
- "gắn" struct vào một "handle" dùng các hệ thống "gắn" để nhận lại struct đã "gắn"
- Xóa một struct
- Kết thúc
Bước 1 - Struct là gì và làm thế nào để khai báo một struct
- struct là gì ?
To put it simple, structs are parallel globals arrays with a nice indexing system. No game cache involved, whatsoever.
Because structs are globals arrays, they have an instance limit, 8191, if to be exact (Fancy trivia, god I love it). But don't be frightened, as you will normally not meet this limit.
Khai báo struct thì rất đơn giản: đầu tiên, bạn cần gõ từ khóa "struct", sau đó gõ tên struct và cuối cùng đóng struct với từ khóa "endstruct"
Ví dụ:
Thế là ta đã có struct tên là structname
Bước 2 - Thêm các "phần tử" cho một struct
Một struct mà trống thì chả sử dụng đc gì.
Sau khi khai báo struct, bạn phải thêm các phần tử cho nó - là những thứ mà bạn muốn "lưu"
Và việc này còn dễ hơn khai báo struct
Các phần tử của struct có thể có giá trị khởi tạo:
Về "mảng" trong một struct, ko có vấn đề gì, nhg thật ra có một
Khi khai báo "mảng" trong một struct, bạn phải đặt "array index limit" (giới hạn chỉ số của mảng)
Điều này có nghĩa là bạn chỉ có thể sử dụng level với chỉ số mảng từ 0 -> 99, nếu bạn dùng với 100 hoặc hơn thì khi kiểm tra code, sẽ có lỗi đc báo.
Bước 3 - Tạo một struct trong một hàm và truy nhập các phần tử của một struct
Để tạo một struct, sẽ có cũ pháp vJass. Nhưng ko nên thấy lo và nhầm lẫn
Tôi chắc là "local" quá quen thuộc với bạn rồi, nhg sao "structname" lại là type của local variable này vì ko có type "structname" mà chỉ có unit, integer, real,..
Đúng, nhg bây giờ thì có rồi.
Tên của struct mà bạn khai báo, bạn phải dùng tên nó như là type của variable khi tạo nó trong một hàm.
Ví dụ:
"pandamonium", "thehelper" và "apple" là tên struct, và "data", "info", "worm" chỉ là tên của struct đc tạo ra.
Sau khi tạo struct, bạn có quyền truy nhập vào các phần tử của nó. Và hãy chú ý đến cũ pháp:
Bạn dùng struct có tên "data" (tên này do bạn đặt, là gì cũng đc) để truy nhập các phần tử của struct có tên là "structname"
Thêm vài ví dụ:
Bước 4 - "gắn" struct vào một "handle" dùng các hệ thống "gắn" để nhận lại struct đã "gắn"
Đã có nhiều "hệ thống gắn/liên kết". Tôi sẽ sử dụng các hệ thống thông dụng
Tôi sẽ "gắn" struct vào một timer tên là "callback", timer này có "function callback" là callbackfunc
Kattana's Handle Variables
Vexorian's CSData
Cohadar's ABC
Cũng ko quá khó.
Bước 5 - Xóa một struct
Struct phải bị xóa, (location phải bị remove, group phải bị destroy,... )
Ko xóa struct, đơn giản là leak
Cú pháp để xóa một struct:
Vài ví dụ nữa:
Bước 6 - Kết thúc
Sau khi đã biết cơ bản về struct, bạn đã biết làm thế nào để tạo, gắn, nhận lại và xóa struct
Ví dụ cuối:
Credit:
Thanks to Andrewgosu for making this tutorial, this is his original post: http://world-editor-tutorials.thehelper.net/cat_usersubmit.php?view=79426
------------------------------
Đến đây, Tom sẽ dùng struct tạo một hàm Knockback (Tom chọn Knockback vì nó dễ hiểu :) )
Ta cần(nên dùng) CSData và CSSafety của Vexorian.
Tom có struct sau:
Và hàm để "gọi" knockback, hàm này sẽ lấy unit bị knockback, khoảng cách knockback (tổng khoảng cách), góc knock, effect và duration để xác định số tick và xác định khoảng cách mỗi lần "move"
Có struct rồi, tạo struct, nhập giá trị cho các phần tử thôi:
Bây giờ ta tạo callback function cho một timer, tạo timer rồi dùng CSData "gắn" struct vừa tạo vào timer này
Sang "callback function" tên là KnockBackE, ta sẽ nhận lại struct đã "gắn", tất nhiên là dùng CSData
Rồi, cuối cùng ta sẽ có:
Sử dụng hàm Knockback trên, đơn giản, gọi function KnockBack thôi
Tạo lại cái skill Storm Hammer trong map demo Slide
---
Một ví dụ đơn giản, dễ hiểu, hy vọng đến đây các bạn (những ai đọc Tutorial này) đã hiểu đôi chút về struct, biết cách sử dụng.
Happy Mapping
P/S: có map demo Tom gửi kèm ở dưới
Để tiếp tục, bạn cần:
- World Editor
- Jass NewGen Pack
- Hiểu biết ở mức trung bình về Jass
Các bước mà tôi định dạy:
- Struct là gì và làm thế nào để khai báo một struct
- Thêm các "component" ( "thành phần", nghe ko hay lắm, hay dịch là "phần tử" đi) cho một struct
- Tạo một struct trong một hàm và truy nhập các phần tử của một struct
- "gắn" struct vào một "handle" dùng các hệ thống "gắn" để nhận lại struct đã "gắn"
- Xóa một struct
- Kết thúc
Bước 1 - Struct là gì và làm thế nào để khai báo một struct
- struct là gì ?
To put it simple, structs are parallel globals arrays with a nice indexing system. No game cache involved, whatsoever.
Because structs are globals arrays, they have an instance limit, 8191, if to be exact (Fancy trivia, god I love it). But don't be frightened, as you will normally not meet this limit.
Khai báo struct thì rất đơn giản: đầu tiên, bạn cần gõ từ khóa "struct", sau đó gõ tên struct và cuối cùng đóng struct với từ khóa "endstruct"
Ví dụ:
Mã:
struct structname
endstruct
Thế là ta đã có struct tên là structname
Bước 2 - Thêm các "phần tử" cho một struct
Một struct mà trống thì chả sử dụng đc gì.
Sau khi khai báo struct, bạn phải thêm các phần tử cho nó - là những thứ mà bạn muốn "lưu"
Và việc này còn dễ hơn khai báo struct
Mã:
struct structname
unit whichPanda
real facing
real x
real y
integer level
endstruct
Các phần tử của struct có thể có giá trị khởi tạo:
Mã:
struct structname
real fullAngle = 90.
integer maxNumber = 69
endstruct
Về "mảng" trong một struct, ko có vấn đề gì, nhg thật ra có một
Khi khai báo "mảng" trong một struct, bạn phải đặt "array index limit" (giới hạn chỉ số của mảng)
Mã:
struct structname
integer array level[100]
endstruct
Điều này có nghĩa là bạn chỉ có thể sử dụng level với chỉ số mảng từ 0 -> 99, nếu bạn dùng với 100 hoặc hơn thì khi kiểm tra code, sẽ có lỗi đc báo.
Bước 3 - Tạo một struct trong một hàm và truy nhập các phần tử của một struct
Để tạo một struct, sẽ có cũ pháp vJass. Nhưng ko nên thấy lo và nhầm lẫn
Mã:
function functionname takes nothing returns nothing
local structname data = stuctname.create()
endfunction
Tôi chắc là "local" quá quen thuộc với bạn rồi, nhg sao "structname" lại là type của local variable này vì ko có type "structname" mà chỉ có unit, integer, real,..
Đúng, nhg bây giờ thì có rồi.
Tên của struct mà bạn khai báo, bạn phải dùng tên nó như là type của variable khi tạo nó trong một hàm.
Ví dụ:
Mã:
function functionname takes nothing returns nothing
local pandamonium data = pandamonium.create()
local thehelper info = thehelper.create()
local apple worm = apple.create()
endfunction
"pandamonium", "thehelper" và "apple" là tên struct, và "data", "info", "worm" chỉ là tên của struct đc tạo ra.
Sau khi tạo struct, bạn có quyền truy nhập vào các phần tử của nó. Và hãy chú ý đến cũ pháp:
Mã:
function functionname takes nothing returns nothing
local structname data = stuctname.create()
local unit caster = GetTriggerUnit()
set data.whichPanda = caster
set data.facing = GetUnitFacing(caster)
set data.x = GetUnitX(caster)
set data.y = GetUnitY(caster)
set data.level = GetHeroLevel(caster)
endfunction
Bạn dùng struct có tên "data" (tên này do bạn đặt, là gì cũng đc) để truy nhập các phần tử của struct có tên là "structname"
Thêm vài ví dụ:
Mã:
function functionname takes nothing returns nothing
local haxxor gamer = haxxor.create()
set gamer.realX = 270.
set gamer.RealY = 90.
endfunction
function functionname takes nothing returns nothing
local sheep grass = sheep.create()
set grass.killer = GetKillingUnit()
endfunction
Bước 4 - "gắn" struct vào một "handle" dùng các hệ thống "gắn" để nhận lại struct đã "gắn"
Đã có nhiều "hệ thống gắn/liên kết". Tôi sẽ sử dụng các hệ thống thông dụng
Tôi sẽ "gắn" struct vào một timer tên là "callback", timer này có "function callback" là callbackfunc
Kattana's Handle Variables
Mã:
function callbackfunc takes nothing returns nothing
local structname data = GetHandleInt(callback, "whichStruct")
endfunction
function functionname takes nothing returns nothing
local structname data = structname.create()
call SetHandleInt(callback, "whichStruct", data)
endfunction
Vexorian's CSData
Mã:
function callbackfunc takes nothing returns nothing
local structname data = GetCSData(callback)
endfunction
function functionname takes nothing returns nothing
local structname data = structname.create()
call SetCSData(callback, data)
endfunction
Cohadar's ABC
Mã:
function callbackfunc takes nothing returns nothing
local structname data = GetTimerStructA(callback)
endfunction
function functionname takes nothing returns nothing
local structname data = structname.create()
call SetTimerStructA(callback, data)
endfunction
Bước 5 - Xóa một struct
Struct phải bị xóa, (location phải bị remove, group phải bị destroy,... )
Ko xóa struct, đơn giản là leak
Cú pháp để xóa một struct:
Mã:
function callbackfunc takes nothing returns nothing
call data.destroy()
endfunction
Vài ví dụ nữa:
Mã:
function callbackfunc takes nothing returns nothing
call data.destroy()
call info.destroy()
call worn.destroy()
endfunction
Bước 6 - Kết thúc
Sau khi đã biết cơ bản về struct, bạn đã biết làm thế nào để tạo, gắn, nhận lại và xóa struct
Ví dụ cuối:
Mã:
// Khai báo struct
struct sheepfall
// tạo một danh sách các phần tử
unit whichSheep
integer SheepLevel
real facing
endstruct
function callbackfunc takes nothing returns nothing
// nhận lại struct
local sheepfall data = GetCSData(GetExpiredTimer())
// Destroy the struct
call data.destroy()
endfunction
function funcname takes nothing returns nothing
local unit sheep = GetTriggerUnit()
local timer t = CreateTimer()
// tạostruct
local sheepfall data = sheepfall.create()
// đặt giá trị cho các phần tử
set data.whichSheep = sheep
set data.SheepLevel = GetHeroLevel(sheep)
set data.facing = GetUnitFacing(sheep)
// gắn struct
call SetCSData(t, data)
call TimerStart(t, 10., false, function callbackfunc)
endfunction
Credit:
Thanks to Andrewgosu for making this tutorial, this is his original post: http://world-editor-tutorials.thehelper.net/cat_usersubmit.php?view=79426
------------------------------
Đến đây, Tom sẽ dùng struct tạo một hàm Knockback (Tom chọn Knockback vì nó dễ hiểu :) )
Ta cần(nên dùng) CSData và CSSafety của Vexorian.
Tom có struct sau:
Mã:
struct knockbackdata
unit whichUnit //unit bị knockback
real angle //góc knock
integer tick //tik tak, tik tak, số lần "move" unit
real distance //khoảng cách mỗi lần "move", tức là tống khoảng cách knock là (distance * tick)
string sfx //effect knockback
endstruct
Và hàm để "gọi" knockback, hàm này sẽ lấy unit bị knockback, khoảng cách knockback (tổng khoảng cách), góc knock, effect và duration để xác định số tick và xác định khoảng cách mỗi lần "move"
Mã:
function KnockBack takes unit whichUnit, real distance, real angle, real duration, string sfx returns nothing
endfunction
Có struct rồi, tạo struct, nhập giá trị cho các phần tử thôi:
Mã:
function KnockBack takes unit whichUnit, real distance, real angle, real duration, string sfx returns nothing
local knockbackdata data = knockbackdata.create()
set data.whichUnit = whichUnit
set data.angle = angle
set data.tick = R2I( duration / 0.04 ) //ta sẽ dùng 0.04s timer, vậy tick = duration / 0.04
set data.distance = distance / data.tick //nhớ là distance trong struct sẽ là khoảng cách mỗi lần "move", vậy nó sẽ = tống khoảng cách / số tick
set data.sfx = sfx
endfunction
Bây giờ ta tạo callback function cho một timer, tạo timer rồi dùng CSData "gắn" struct vừa tạo vào timer này
Mã:
function KnockBackE takes nothing returns nothing
endfunction
function KnockBack takes unit whichUnit, real distance, real angle, real duration, string sfx returns nothing
local knockbackdata data = knockbackdata.create()
local timer ti = NewTimer() // sử dụng CSSafety, dùng NewTimer thay cho CreateTimer
set data.whichUnit = whichUnit
set data.angle = angle
set data.tick = R2I( duration / 0.04 ) //ta sẽ dùng 0.04s timer, vậy tick = duration / 0.04
set data.distance = distance / data.tick //nhớ là distance trong struct sẽ là khoảng cách mỗi lần "move", vậy nó sẽ = tống khoảng cách / số tick
set data.sfx = sfx
call SetCSData( ti , data ) //struct sẽ đc coi như một integer
call TimerStart( ti, 0.04, true, function KnockBackE )
set ti = null //local handle -> phải null
endfunction
Sang "callback function" tên là KnockBackE, ta sẽ nhận lại struct đã "gắn", tất nhiên là dùng CSData
Mã:
function KnockBackE takes nothing returns nothing
local timer ti = GetExpiredTimer()
local knockbackdata data = GetCSData( ti )
endfunction
Vậy là từ struct, ta sẽ có unit, distance, angle, sfx, tick tiến hành knockback thôi:
function KnockBackE takes nothing returns nothing
local timer ti = GetExpiredTimer()
local knockbackdata data = GetCSData( ti )
local location loc = GetUnitLoc( data.whichUnit ) //Position of whichUnit
local location loc2 = PolarProjectionBJ( loc, data.distance, data.angle ) //Point with Polar Offset
call AddSpecialEffectLocBJ( loc2, data.sfx ) //Create Special Effect
call DestroyEffectBJ( GetLastCreatedEffectBJ() ) // Destroy Special Effect
call SetUnitPositionLoc( data.whichUnit, loc2 ) //move unit
call RemoveLocation( loc )
call RemoveLocation( loc2 )
set loc = null //dùng xong các local handle thì phải null, ko thì leak đấy
set loc2 = null
set data.tick = data.tick - 1 //giảm tick
if data.tick <= 0 then // dùng <= 0 cho an toàn
call data.destroy()
call ReleaseTimer( ti ) // sử dụng CSSafety, dùng ReleaseTimer thay cho DestroyTimer
endif
set ti = null
endfunction
Rồi, cuối cùng ta sẽ có:
Mã:
struct knockbackdata
unit whichUnit
real angle
integer tick
real distance
string sfx
endstruct
function KnockBackE takes nothing returns nothing
local timer ti = GetExpiredTimer()
local knockbackdata data = GetCSData( ti )
local location loc = GetUnitLoc( data.whichUnit )
local location loc2 = PolarProjectionBJ( loc, data.distance, data.angle )
call AddSpecialEffectLocBJ( loc2, data.sfx )
call DestroyEffectBJ( GetLastCreatedEffectBJ() )
call SetUnitPositionLoc( data.whichUnit, loc2 )
call RemoveLocation( loc )
call RemoveLocation( loc2 )
set loc = null
set loc2 = null
set data.tick = data.tick - 1
if data.tick <= 0 then
call data.destroy()
call ReleaseTimer( ti )
endif
set ti = null
endfunction
function KnockBack takes unit whichUnit, real distance, real angle, real duration, string sfx returns nothing
local knockbackdata data = knockbackdata.create()
local timer ti = NewTimer()
set data.whichUnit = whichUnit
set data.angle = angle
set data.tick = R2I( duration / 0.04 )
set data.distance = distance / data.tick
set data.sfx = sfx
call SetCSData( ti , data )
call TimerStart( ti, 0.04, true, function KnockBackE )
set ti = null
endfunction
Sử dụng hàm Knockback trên, đơn giản, gọi function KnockBack thôi
Tạo lại cái skill Storm Hammer trong map demo Slide
Mã:
function StormHammerAct takes nothing returns nothing
local unit c = GetAttacker()
local unit u = GetTriggerUnit()
local integer lvl = GetUnitAbilityLevel( c , 'A000' )
local location loc
local location loc2
if lvl == 0 or ( lvl > 0 and GetRandomInt(1,100) > 17 ) then //chưa có ability hoặc có nhg chance random > 17
set c = null
set u = null
return
endif
call SetUnitAnimation(c,"attack slam")
call UnitDamageTarget( c, u, 25. * lvl, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, null )
set loc = GetUnitLoc(c)
set loc2 = GetUnitLoc(u)
//gọi hàm Knockback
call KnockBack( u, 90. + 30*lvl, AngleBetweenPoints(loc,loc2), 0.8, "Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl" )
call RemoveLocation( loc )
call RemoveLocation( loc2 )
set loc = null
set loc2 = null
set c = null
set u = null
endfunction
//===========================================================================
function InitTrig_StormHammer takes nothing returns nothing
set gg_trg_StormHammer = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_StormHammer, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddAction( gg_trg_StormHammer, function StormHammerAct )
endfunction
---
Một ví dụ đơn giản, dễ hiểu, hy vọng đến đây các bạn (những ai đọc Tutorial này) đã hiểu đôi chút về struct, biết cách sử dụng.
Happy Mapping

P/S: có map demo Tom gửi kèm ở dưới


