Topic post, bàn luận, đóng góp ý kiến, thắc mắc, giải đáp, bình phẩm về Custom Spell.

  • Thread starter Thread starter raivor
  • Ngày gửi Ngày gửi

raivor

Dragon Quest
Lão Làng GVN
Tham gia ngày
24/7/09
Bài viết
1,422
Reaction score
2,843
Đầu tiên, xin các bạn chú ý cho vài điều:
1. Các bạn đừng hỏi những vấn đề về Terrain hay ... những vấn đề khác không liên quan đến spell.
2. Các bạn post spell lên thì nên giải thích những phần chính về spell của mình như:
+ Giới thiệu về spell.
+ Vài hình ảnh.
+ Nếu giải thích từng đoạn code trong trigger thì càng tốt.
+ Trigger của spell nên bỏ vào thẻ
Mã:
[/COLOR][/INDENT]
 [B][COLOR="DarkGreen"]3. Mình không ép các bạn phải post cả trigger lên topic, điều đó là tự nguyện.
 4. Các bạn phải post map demo của spell đó. Và nếu ai có thời gian thì giúp post lại trigger đó lên giúp (nhớ ghi lại tên của người làm spell) và có giải thích càng tốt.
 5. Spell post lên đây [SIZE="1"]không nhất thiết phải đẹp[/SIZE] nhưng đẹp vẫn tốt hơn phải không nào (tuy nhiên xin lưu ý là ĐẸP không phải là choáng hết cả màn hình nhé, đơn giản mà đẹp, đó mới đáng nể), bời vậy phải cố gắng, chỉ cần có sự sáng tạo, đơn giản càng tốt. Viết trên topic càng dài càng tốt, để mọi người không lười mà lướt qua (phải đọc hết chứ) ;)).[/B] (và đây là ý kiến của bác WE mong các bạn chú ý để làm spell thật tốt : "Quan trọng là custom spell đòi hỏi phải sáng tạo nữa chứ đẹp mắt vẫn chưa phải là hay ( giả sử như spell đẹp nhưng chỉ có 1 kiểu: phóng ra gây damage --> thà dùng shock wave cho nhanh )
Vd như chúng ta có thể nghĩ ra một custom spell có thể làm unit chạy nhanh hơn max speed là 522, hoặc spell invisiblity có thể đi xuyên địa hình mà khi có true sight ( dust, gem ) thì vẫn không hiện hình..( chỉ hiện bóng, attack đc nhưng ko target đc ) 
Khuyên các bạn nên làm spell hay, sáng tạo, đẹp nhưng không quá nhiều effect --> gây lag trong các pha combat)"
 [B]6. Sẽ có phần đánh giá về spells, người đánh giá spells sẽ là những người đã xem spells (tất nhiên là trừ chủ nhân của spells đó, tuy nhiên bạn sẽ được đánh giá spells của người khác), các bạn sẽ đánh giá theo mẫu sau (có gì thiếu sót mong các bạn góp ý để mình thêm vào):
+Về ý tưởng: tốt, không tốt (0.5-2đ) (các bạn ghi điểm sau mỗi phần nhận xét nhé)
+Về thẩm mĩ: đẹp, không đẹp. (0.25 - 1đ) 
+Về code: tốt, không tốt. (các bạn nhận xét về cả trình bày, những thiếu sót code, các code thừa,... nha) (0.25 - 1đ)
+Về phần giải thích: dễ hiểu, khó hiểu (0.25 - 5đ)
+Về nhận xét riêng của bạn: thích hay không thích (1đ)
Tổng điểm: <cộng các điểm mà bạn đã chấm> max là 10đ
Số giám khảo sẽ không giới hạn trong tuần đầu tiên này (từ hôm nay đến chủ nhật tuần sau), sau 1 tuần, mình sẽ chọn ra 5 giám khảo tốt nhất. Sau 1 tháng sẽ tiến hành test giám khảo lại từ đầu (để tránh tình trạng spam thì lưu ý các bạn, các bạn chỉ chấm duy nhất 1 lần, không chấm lại, khi giám khảo đã chấm thì các bạn chỉ được quyền bổ sung thêm nếu nhận thấy các giám khảo chấm còn thiếu sót, nếu ai cố tình spam thì mong Mod xử hộ). Và sau 1 tuần mình sẽ cộng tất cả các điểm của mỗi bạn lại rồi chia cho số spell các bạn post (cho công bằng thôi, chứ không post nhiều thì lợi rồi), rồi lập bảng xếp hạng những bạn có số điểm cao nhất, còn về giải thưởng thì để mình xem xét.(Các điều trên được áp dụng với tất cả thành viên kể cả mod và mình)
 7. Sẽ có những cuộc thi làm spell theo đề bài và những người có quyền ra đề: mình Raivor, ShadowThanatos.
 8. Thành phần ban giám khảo : đang tuyển....
 9. Đây là topic post spell, tuy nhiên vì để cung cấp thêm ý tưởng giúp các bạn làm spell mà không bị vướng phần ý tưởng này nên mình đã ra đề thi để các bạn có thể làm. Nhưng, tiêu đề topic là như vậy và mục đích của topic cũng là như vậy, dù mình có thêm vài cái đề thi, hay gì gì đó thì các bạn vẫn có thể post spell của mình làm và chấm điểm như thường.
 10. Cuối cùng mong các bạn tích cực tham gia topic để topic cũng như cộng đồng WE phát triển.[/COLOR][/B][/INDENT]
 [B]Xin cám ơn![/B][/QUOTE]
[B][COLOR="DarkRed"][SIZE="3"][U]Chúng ta sẽ tìm hiểu vài điều về Trigger của 1 spell:[/U][/SIZE][/COLOR][/B]
[COLOR="DarkGreen"] [B][U]- Gồm 3 phần:[/U][/B][/COLOR] 
[INDENT][COLOR="SeaGreen"]+Events (sự kiện) : 1 việc gì đó sẽ diễn ra khi có 1 sự kiện sảy đến.
+Actions (có thể nói là sao ta? ) : những việc sẽ sảy ra khi sự kiện nào đó xuất hiện và các điều kiện được thỏa mãn.
+Conditions (điều kiện) : những yêu cầu cần được thỏa mãn để chúng ta có thể "chế biến" sự kiện kia khi nó tới.[/COLOR]
[INDENT]VD: [spoil][INDENT]Events:[INDENT]Cậu bạn của bạn đi đến trước nhà của bạn.[/INDENT]
              Conditions:[INDENT]Cửa mở.
Bạn ở nhà.[/INDENT]
              Actions: 
[INDENT]Cậu bạn đó đi vào nhà.
Nói chuyện với bạn.
Nếu[INDENT]Đến 12h AM[/INDENT]
Thì[INDENT]Cậu bạn đó đi về.[/INDENT]
Còn không thì[INDENT]không có gì xảy ra (tức cậu bạn đó vẫn ở nhà bạn và nói chuyện với bạn).[/INDENT][/INDENT][/INDENT][/spoil][/INDENT][/INDENT]
 [B][U][COLOR="DarkGreen"]- Về cách làm 1 spell mà theo mình là đơn giản nhất:[/COLOR][/U][/B]
      [COLOR="SeaGreen"]Giống như vẽ 1 bức tranh.
      I.Hình dung trong đầu về bức tranh đó. => Spell đó như thế nào ?
      II. Những phụ kiện cần thiết để vẽ tranh (bút, màu...) => Các biến cần phải dùng, events, conditions, actions....
      III. Vẽ phác. => bước này rất quan trọng, các bạn sẽ làm như kiểu từ 1 cái thân cây mọc ra nhiều cành và lá ấy.
      IV. Đi nét. => Kiểm tra, thêm thắt các biến, các đoạn code...
      V. Tô màu. => Thêm các hiệu ứng để spell sinh động hơn.
      VI. Hoàn tất bức tranh. => Test spell (và...............post lên đây :P)
       [INDENT] VD:[/COLOR] [Spoil][COLOR="RoyalBlue"]I. ....................
              II. Cái này thực ra thì đầu tiên chỉ cần các biến quan trọng ( từ từ nó mọc ra theo nhu cầu ấy mà). Các biến đó như là : +Caster(Triggering Unit) =>là cái tên đã gây ra vụ việc đó và để lại hậu quả mà ta cần đạo diễn ấy. [INDENT]+Dummy(Unit) => 1 diễn viên trong bộ phim kể về hậu quả của việc mà tên Caster gây ra. 
+Point => địa điểm trường quay. 
+(MUI(Integer)) không nhất thiết nhưng cần phải có nếu spell MUI, tên khác cũng được => nhiều bộ phim giống nhau sẽ không ảnh hưởng đến chất lượng của phim. (khỏi cạnh tranh để bên này thì chết bên kia gần chết). [/INDENT]
             III. Sườn của trigger. => Set biến, dùng các đoạn code để xây dựng sườn.[INDENT]VD: 
E:A unit ....
A:Set Caster = (Triggering Unit)[INDENT]Creat 1 Footman......[/INDENT]
E:Every .... seconds ....[INDENT]Move Footman (Intantly) to.....[/INDENT][/INDENT]
             IV. Bổ sung các biến, đoạn code để trigger hoạt động. => Thêm các biến để xác định vị trí ( để remove leak), thêm biến dạng số (nguyên[Integer], thực[real]) để làm điều kiện kết thúc trigger, để đếm, lập công thức tính hoặc thay đổi giá trị.....
[INDENT]VD:
[INDENT]Set Dem(Integer) = 10[/INDENT]
[INDENT]E:Every 1 seconds....
A:Set Dem = (Dem - 1)[INDENT]If
[INDENT]Dem equal to 0[/INDENT]
Then
[INDENT]Turn off (this trigger).[/INDENT][/INDENT][/INDENT][/INDENT]
              V. Bổ sung các hiệu ứng cho spell. => Special Effect, di chuyển hình vòng tròn, hình vuông, tạo ra hình ngôi sao, bay lên, lặn xuống, lăn qua lăn lại.....
              VI. Remove Leak, kiểm tra bug, turn off các trigger cần thiết...[/COLOR][/INDENT][/spoil]
Spell đầu tiên nhé.
[B][U]Tên Spell:[/U][/B] SThunder Clap
[B][U]Mô tả:[/U][/B] Hero cast thunder clap và
[spoil][IMG]http://i786.photobucket.com/albums/yy146/raivor1996/Spell/SThunderClap2.jpg[/IMG]
[IMG]http://i786.photobucket.com/albums/yy146/raivor1996/Spell/SThunderClap3.jpg[/IMG]
[IMG]http://i786.photobucket.com/albums/yy146/raivor1996/Spell/SThunderClap4.jpg[/IMG]
[IMG]http://i786.photobucket.com/albums/yy146/raivor1996/Spell/SThunderClap1.jpg[/IMG] Cái này cast 2 lần liên tiếp. [/spoil]
[B][U]Các biến:[/U][/B]
-<Tên biến [có Array(kiểu mảng)]>:<Loại biến>
- [COLOR="DimGray"]Caster[Array][/COLOR],[COLOR="Sienna"]Unit[/COLOR]: Unit
- [COLOR="DimGray"]Point[Array][/COLOR],[COLOR="Green"]Point2[Array][/COLOR]: Point
- [COLOR="Navy"]Integer[Array][/COLOR], [COLOR="DimGray"]MUI[/COLOR]: Integer
- [COLOR="DimGray"]Group[/COLOR], [COLOR="Sienna"]DmgAoE[Array][/COLOR]: Unit Group
- [COLOR="Green"]Move[Array], Speed[Array][/COLOR], [COLOR="Navy"]Speed2[Array][/COLOR]: Real 
(Màu xám là những biến ta tạo đầu tiên (đừng tạo hết nha, làm từ từ thôi) tiếp tục là màu xanh lá, đến xanh dương rồi cuối cùng là màu nâu đối với các đoạn code luôn)
Trigger 1
[Code]Events
      [COLOR="DimGray"]Unit - A unit Starts the effect of an ability //khi hero cast spell[/COLOR]
Conditions
      [COLOR="DimGray"](Ability being cast) Equal to Thunder Clap //spell đó phải là thunder clap[/COLOR]
Actions
     [COLOR="DimGray"] Set MUI = (MUI + 1) //có nghĩa là ban đầu MUI = 0, sau 1 lần cast thì MUI = 0 + 1, khi đó MUI = 1, tiếp tục lần thứ 2 MUI = (MUI = 1) + 1 thì MUI = 2, rồi lần thứ 3 MUI = (MUI = 2(1 + 1 = 2)) + 1, lần thứ 4 MUI = (MUI = 3(2+1 = 3)) + 1, rồi lần thứ 5 MUI = 4 + 1 = 5, rồi lần thứ 6 MUI = 5 + 1 = 6....................
      If (All Conditions are True) then do (Then Actions) else do (Else Action)
         If - Conditions
             MUI Greater than or equal to 500 //khi MUI >= 500
         Then - Actions
             Set MUI = 0 //thì Set MUI = 0 và quá trình trên kia lại tiếp diễn
         Else - Actions
      Set Caster[MUI] = (Triggering unit) //Biến Caster là hero cast spell (tên gây ra hậu quả đấy)
      Set Point[MUI] = (Position of Caster[MUI]) //Biến Point được đặt là vị trí của "Caster".[/COLOR]
     [COLOR="Green"] Set Speed[MUI] = 30.00 //Tốc độ ban đầu là 30 (km/h :D).[/COLOR]
      [COLOR="Navy"]Set Speed2[MUI] = 0.00 //Tốc độ giảm dần.[/COLOR]
      [COLOR="DimGray"]Unit - Create 1 Dummy for (Owner of Caster[MUI]) at Point[MUI] facing Default building facing degrees //tạo 1 Dummy cho Caster tại vị trí của hắn để MUI thôi.
      Unit Group - Add (Last created unit) to Group //Cho dummy vào nhóm "tự kỉ vì MUI"
      Unit - Set the custon value of (Last created unit) to MUI //đặt giá trị "tự biên" bằng MUI, bằng cách này ta có thể giữ MUI lại mà không bị các MUI khác chen lấn làm có bạn chết có bạn bị thương => Spell bug, không MUI được.
      Trigger - Turn on Trigger 2 //Bật Trigger 2
Trigger 2
Mã:
Events
      [COLOR="DimGray"]Time - Every 0.04 second of game time //mỗi 0.04s của game[/COLOR]
Conditions
Actions
      [COLOR="Green"]Unit Group - Pick every unit in Group and do (Actions) //tóm tất cả unit trong nhóm "tự kỉ vì MUI"
          Loop - Actions
                Set Move[(Custom value of (Picked unit))] = (Move(Custom value of (Picked unit))] + 3.00) //[(Custom value of (Picked unit))] <<< cái gì đây??? Như ở trên, nó là giá trị tự biên được đặt = MUI, tại sao lại là Picked unit (tên bị tóm đây mà), như ở trên ta đã add "Last create unit" vào nhóm "tự kỉ vì MUI" nên khi tóm unit trong nhóm "tự kỉ vì MUI" thì dính hắn. Và ở trên có dòng "Unit - Set the [B][U]custon value of (Last created unit)[/U][/B] to MUI" đấy đấy, nó đấy. Vậy thì tóm lại, Custom value of (Picked unit) = MUI tức là cast lần đầu tiên thì Custom value of (Picked unit) = 1, lần thứ 2 thì Custom value of (Picked unit) = 2.... Vậy tại sao không dùng MUI luôn cho nó lành? Thực ra là như vầy, nếu ta dùng MUI thì trong trigger 2 MUI sẽ bị thay đổi giá trị nhanh chóng, vì ở Trigger 2 hệ thống check liên tục mỗi 0.04s, cụ thể là ở đây "Time - Every 0.04 second of game time"<<< nếu vậy thì khi cast lần thứ 2 MUI = 2 rồi :|, nhưng nếu dùng custom value of khỉgìđấy thì cast lần 2 sẽ xuất hiện 2 giá trị "tự biên" là Custom value of (Picked unit) [COLOR="White"]thứ nhất[/COLOR] = 1 và Custom value of (Picked unit) [COLOR="White"]thứ 2[/COLOR] = 2 => cả 2 cái cùng hoạt động. Vậy tại sao MUI lại không giữ được mà Custom value of khỉgìđấy lại giữ được? À, là bởi vì người ta quy định vậy đấy, biết vậy thôi, khỏi thắc mắc. Quay lại đoạn code, Move = Move + 3 (vậy thôi?)[/COLOR]
                [COLOR="Navy"]Set Speed[(Custom value of (Picked unit))] = (Speed[(Custom value of (Picked unit))] + Speed2[(Custom value of (Picked unit))]) //Biến Speed = Speed +  Speed2.
                Set Speed2[(Custom value of (Picked unit))] = (Speed2[(Custom value of (Picked unit))] - 1.00) //Biến Speed2 = Speed2 - 1 = 0 - 1, mà Speed = 30 => Speed = 30 + (0-1).[/COLOR]
                [COLOR="DimGray"]Set Point[(Custom value of (Picked unit))] = (Position of Caster[(Custom value of (Picked unit))]) //Biến Point = Vị trí của Caster. Như đã nói ở trên, do trigger chạy 1 lần trong 0.04s, vậy thì biến Point này sẽ được check 1 lần trong 0.04s tức là vị trí của caster được check 1 lần trong 0.04s.[/COLOR]
                [COLOR="Green"]For each (Integer Integer[(Custom value of (Picked unit))] from 1 to 6, do (Actions) //Vòng lặp 6 lần, tức là phần nằm trong đoạn code này chạy vòng vòng 6 lần để lấy điểm kiểm tra môn thể dục.
                      Loop - Actions //nó là Loop - Actions (người ta viết vậy thì biết vậy)
                            Set Point2[(Custom value of (Picked unit))] = (Point[(Custom value of (Picked unit))] offset by Speed[(Custom value of (Picked unit))] towards ((60.00 x (Real(Integer[(Custom value of (Picked unit))]))) + Move[(Custom value of (Picked unit))]) degrees) //Biến Point2 = biến Point cách 1 khoảng Speed có cái góc là 60 x với số vòng chạy cộng với biến Move. Tức là như vầy, à mà là sao ta?? À là như vậy nè cái Point2 đó đó là cái vị trí của Caster (được check mỗi 0.04s, tội thằng bé) + với 30km với 1 góc là 60 x với 1 vòng nè, 2 vòng nè, 3 vỏng nè, 4 vòng nè , 5 vòng nè , 6 vòng nè + với 0 nè mà Move = Move + 3 nè, tức là Move = 3 nè rồi sau 0.04s thì Move = Move + 3 = 3 + 3 = 6 để rồi qua 0.04 sau thì Move = Move + 3 = 6 + 3 rồi sau 0.04s sau thì hết hơi nói nè... Tiếp nè, ((60.00 x (Real(Integer[(Custom value of (Picked unit))]))) + Move[(Custom value of (Picked unit))]) degrees) có nghĩa là khi ta chạy vòng thứ nhất thì Point2 được đặt ở góc 2h (0h là 0 độ, 60 độ là 2h), vòng thứ 2 thì sẽ là 60 độ x 2 thì Point2 được đặt ở góc 4h (0h là 0 độ, 120 độ là 4h), vòng thứ 3 thì sẽ là 60 độ x 3 thì Point2 được đặt ở góc 6h (0h là 0 độ, 180 độ là 6h), vòng thứ 4 thì sẽ là 60 độ x 4 thì Point2 được đặt ở góc 8h (0h là 0 độ, 240 độ là 6h), vòng thứ 5 thì sẽ là 60 độ x 5 thì Point2 được đặt ở góc 10h (0h là 0 độ, 300 độ là 10h), vòng thứ 6 thì sẽ là 60 độ x 6 thì Point2 được đặt ở góc 12h (0h là 0 độ, 360 độ là 12h mà 0h = 12h => 12h = 0 độ hay 0h = 350 độ). Vậy, lấy đâu ra 60 độ vậy? Là tại vì ta cho nó chạy 6 vòng, mà 360 / 6 bằng 60 độ, vì vậy, 10 vòng thì 360/10 là 36 độ. Nhưng, sao tự nhiên lại + Move? Ta có: Move = Move + 3 và nó cứ tăng dần nên vòng thứ nhất của 0.04s đầu tiên là 60 độ x 1 + 3 = 63 độ, tương tự vòng thứ 2 là 123, vòng thứ 3 là 183 rồi 243 rồi 303 rồi 363 hay 3 độ. Trong 0.04s sau thì vòng thứ nhất là 66 độ, vòng thứ 2 là 126 độ rồi 186 rồi 246 rồi 306 rồi 366 = "1 năm nhuận" tức 6 độ. Rồi sau 0.04s sau nữa nó sẽ như vậy tức là 69, 129 rồi .... Như vậy thì các Point2 sau mỗi 0.04s sẽ xoay theo chiều nào đó ai mà biết trên 1 đường tròn. (Xoay đều xoay đều xoay). Và vì nó cứ chạy ra xa và xoay nên đường kính vòng xoay càng rộng. Còn nữa, như mình đã nói, tốc độ rộng ra của đường kính là biến Speed = 30 mà Speed = Speed + Speed2 mà thêm cái nữa Speed2 = Speed2 - 1 do đó Speed = 30 - 1 rồi sau 0.04s Speed = 30 - 2 rồi 30 -3 như vậy khi Speed2 = 30 thì đường kính không rộng ra nữa, và ta áp dụng định lí "GIẬT LÙI" do tôi mới nghĩ ra thì Speed sẽ = số âm khi Speed2 > Speed => nó sẽ chạy ngược vô lại.[/COLOR]
                             [COLOR="Sienna"]Set DmgAoE[(Custom value of (Picked unit))] = (Units within 100.00 of Point2[(Custom value of (Picked unit))] matching ((((Matching unit) is A structure) Equal to Fasle) and ((((Matching unit) is Magic Immune) Equal to False) and ((((Matching unit is dead) Equal to False) and ((((Matching unit) belong to an ally of (Owner of Caster[(Custom value of (Picked unit))]) Equal to False //vùng gây dmg cho bọn unit xung quanh 100.00km(vuông) của Point2. " and  and  and  Equal to False" Unit bị pick không phải là công trình "((((Matching unit) is A structure) Equal to Fasle)" và(and) unit bị pick không phải là unit kháng phép "((((Matching unit) is Magic Immune) Equal to False)" và(and) unit bị pick không chết tức là phải còn sống "((((Matching unit is dead) Equal to False)" và(and) unit bị pick không phải là đồng đội của "[COLOR="white"]tên đồi bại[/COLOR]" "((((Matching unit) belong to an ally of (Owner of Caster[(Custom value of (Picked unit))])"
                              Set Unit = (Picked unit) //Unit = (Picked unit) = tên tự kỉ bị tóm.[/COLOR]
                              [COLOR="Sienna"]Unit Group - Pick every unit in DmgAoE[(Custom value of (Picked unit))] and do [Actions] //chọn cái bọn bất hạnh trong vùng "GDCBUXQ100.00km(vuông)CP2"
                                     Loop - Actions
                                           Unit - Cause Caster[(Custom value of Unit)] to damage (Picked unit), dealing [B][U](10.00 x (Real(Level of Thunder Clap for Caster[(Custom value of Unit)]))))[/U][/B] damage of attack type Spells and damage type Normal //gây dmg bằng 10 x cho level của spell, level 1 thì gây 10 dmg, level 2 thì 20 dmg, level 3 bằng 30 dmg.[/COLOR]
                              [COLOR="Green"]Special Effect - Create a special effect at Point2[(Custom value of (Picked unit))] using Abilities\Weapons\VengeanceMissile\VengeanceMissile.mdl //Phần chính đây, vừa là sườn vừa tô màu. Tạo hiệu ứng ở Point2.[/COLOR]
                              [COLOR="Green"]Special Effect - Destroy (Last created special effect) //Hủy hiệu ứng, vì cái này mà chúng ta nên chỉ nên xem effect ở phần death animation.[/COLOR]
                [COLOR="Green"]If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      If - Conditions
                            Speed2[(Custom value of (Picked unit))] Less than or equal to -30.00 //Nếu Speed2 bằng -30 tức là Speed = 0 tức lả Point2 = (Point[(Custom value of (Picked unit))] = vị trí của caster .... còn phần sau mình dùng viết *gạch gạch* => bỏ, giờ nó chả còn nghĩa lí gì nữa vì nó về cùng 1 điểm thì góc này góc nọ làm gì???
                      Then - Actions
                            Unit Group - Remove (Picked unit) from Group //Tống tên bị tóm khỏi nhóm "tự kỉ vì MUI". (để lôi tên khác vào <<đừng hiểu nhầm, đã xóa rồi không biết có cần tống hắn đi không? Tội lỗi.)
                            Unit - Remove (Picked unit) from the game //Xóa tên bị tóm
                            Custom script: call RemoveLocation(udg_Point[GetUnitUserData(GetEnumUnit())])
                            Custom script: call RemoveLocation(udg_Point[GetUnitUserData(GetEnumUnit())])
                      Else - Actions
      If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                  (Number of units in group) Equal to 0 //Khi cái nhóm "tự kỉ vì MUI" không còn đứa nào vì tụi nó đã hết bệnh.
            Then - Actions
                  Trigger -  Turn off (This trigger) //thì tắt trigger RemoveLeak.
            Else - Actions
//Vậy tại sao không tắt ngay ở dòng If thứ 2 từ dưới đếm lên, mình sẽ trả lời là bởi vì mình không biết tại sao, chỉ tại khi vào test thì làm như vậy mới không có bug.[/COLOR]
Hết. Chúc thành công.
Đề bài theo tuần:
-Tuần 1: [Spoil]
Đề:
- Các bạn sẽ làm 1 spell dựa trên trò chơi Yo-Yo.
Video cho các bạn chưa biết về trò chơi này:
[spoil][video]CSm0VgGwBSo[/video][/spoil]
Những điểm bắt buộc:
- Yo-yo quay nhanh.
Mở rộng:
- Về hiệu ứng vật lí.
- Có thể tác động lên dây của Yo-yo.
- Các bạn có thể thêm các công dụng của spell, ví dụ như gây damage, hay dịch chuyển hero tới vị trí của Yo-Yo.........v.v......
Thành phần tham dự:
- Tất cả mọi người (kể cả trẻ sớ sinh mới ra đời cho tới người già cao tuổi, trừ mình thôi :D).
*Chú ý: Các bạn phải trình bày bài giới thiệu map như 1 bài hướng dẫn bình thường, và gửi map cho mình.
Phần thưởng: 1 tràng pháo tay của khán giả :D. Mong các bạn hưởng ứng nhiệt tình, trình độ tới đâu thì làm tới đó.
[/spoil]
-Tuần 2:
[spoil]
Đề:
- Các bạn sẽ làm 1 spell sử dụng các tia sáng.
Mở rộng:
- Tia sáng của các bạn có thể là cái gì cũng được và nó phải là 1 đường thẳng.
- Khi tia sáng đi tới "gương" thì góc tạo bởi tia phản xạ của tia sáng và đường thẳng vuông góc với "gương" sẽ bằng góc tạo bởi tia sáng và đường thẳng vuông góc với "gương".
- Các bạn sẽ phải làm tia sáng bị phản xạ khi chiếu tới "gương" nên số lượng "gương" là không giới hạn.
Thành phần tham dự: như trên.
*Chú ý: như trên. Thêm cái nữa là các bạn không cần hướng dẫn cũng được. Có càng tốt.
Phần thưởng: như trên.
[/spoil]​
 

Attachments

Chỉnh sửa cuối:
Ủng hộ topic... phong trào mapmaker cần có những hoạt động sôi nổi như thế này. Sẽ sớm pót spell khi làm xong :D
ps: spell = vjass có đc hem?
//Codart đang dùng tạm nick này :D
 
vjass thì phải giải thích + với hình ảnh về tác dụng của từng phần trong vjass khi vào game.
 
Ủng hộ chủ topic, anh em cùng đóng góp một số custom spell để newbie học hỏi, vd như em :) :)
 
Tên Spell: ZZBlink
Mô tả: Hero di chuyển Zic-zac đến điểm được cast spell.
[spoil]
ZZBlink.jpg

ZZBlink2.jpg
[/spoil]
Các biến:
- <Tên biến [có Array(kiểu mảng)]>:<Loại biến>
- Caster[Array]: Unit
- Group: Unit Group
- Point[Array], Point2[Array], Point3[Array], Target[Array]: Point
- Bien[Array], MUI, TempValue: Integer
- Lightning[Array]: Lightning


I. Phần chính
Trigger 1:
Mã:
Event
      Unit - A unit Starts the effect of an ability
Conditions
      (Ability being cast) Equal to Blink
Actions
      Set MUI = (MUI + 1) //có nghĩa là ban đầu MUI = 0, sau 1 lần cast thì MUI = 0 + 1, khi đó MUI = 1, tiếp tục lần thứ 2 MUI = (MUI = 1) + 1 thì MUI = 2, rồi lần thứ 3 MUI = (MUI = 2(1 + 1 = 2)) + 1, lần thứ 4 MUI = (MUI = 3(2+1 = 3)) + 1, rồi lần thứ 5 MUI = 4 + 1 = 5, rồi lần thứ 6 MUI = 5 + 1 = 6....................
      If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                  MUI Equal to 500 //khi MUI >= 500
            Then - Actions
                  Set MUI = 0 //thì Set MUI = 0 và quá trình trên kia lại tiếp diễn
            Else - Actions
      Set Caster[MUI] = (Triggering unit) //Biến Caster là hero cast spell (là tênmàumè đấy)
      Set Point[MUI] = (Position of Caster[MUI]) //Vị trí của tênmàumè
      Set Target[MUI] = (Target point of ability being cast) //Điểm mà tênmàumè di-chuyển-một-cách-màu-mè tới.
      Set Bien[MUI] = 1 //Một biến được có tên là Biến và = 1, tuy vậy nhưng nó sắp làm nên kì tích (phóng đại lên thôi :P)
      Unit - Create 1 Dummy for Owner of Caster[MUI]) at Point[MUI] facing Default building facing degrees //như đã nóiở trên dòng này để: "//tạo 1 Dummy cho Caster tại vị trí của hắn để MUI thôi."
      Unit Group - Add (Last created unit) to Group //Cho dummy vào nhóm "tự kỉ vì MUI"
      Unit - Set the custom value of (Last created unit) to MUI //đặt giá trị "tự biên" bằng MUI, bằng cách này ta có thể giữ MUI lại mà không bị các MUI khác chen lấn làm có bạn chết có bạn bị thương => Spell bug, không MUI được.
      Trigger - Turn on Untitled Trigger 002 <gen> //Bật trigger 2
Trigger 2:
Mã:
Event
      Time - Every 0.05 seconds of game time //Mỗi 0.05s của game
Conditions
Actions
      Unit Group - Pick every unit in Group and do (Actions) //tóm bọn tự kỉ trong nhóm "tự kỉ vì MUI".
            Loop - Actions
                  Set TempValue = [(Custom value of (Picked unit))] //Bác Tom bảo dùng cái này để thay cho cái dòng "[B][(Custom value of (Picked unit))][/B][COLOR="White"] <<< cái gì đây??? Như ở trên, nó là giá trị tự biên được đặt = MUI, tại sao lại là Picked unit (tên bị tóm đây mà), như ở trên ta đã add "Last create unit" vào nhóm "tự kỉ vì MUI" nên khi tóm unit trong nhóm "tự kỉ vì MUI" thì dính hắn. Và ở trên có dòng "Unit - Set the [B][U]custon value of (Last created unit)[/U][/B] to MUI" đấy đấy, nó đấy. Vậy thì tóm lại, Custom value of (Picked unit) = MUI tức là cast lần đầu tiên thì Custom value of (Picked unit) = 1, lần thứ 2 thì Custom value of (Picked unit) = 2.... Vậy tại sao không dùng MUI luôn cho nó lành? Thực ra là như vầy, nếu ta dùng MUI thì trong trigger 2 MUI sẽ bị thay đổi giá trị nhanh chóng, vì ở Trigger 2 hệ thống check liên tục mỗi 0.04s, cụ thể là ở đây "Time - Every 0.04 second of game time"<<< nếu vậy thì khi cast lần thứ 2 MUI = 2 rồi :|, nhưng nếu dùng custom value of khỉgìđấy thì cast lần 2 sẽ xuất hiện 2 giá trị "tự biên" là Custom value of (Picked unit) [COLOR="White"]thứ nhất[/COLOR] = 1 và Custom value of (Picked unit) [COLOR="White"]thứ 2[/COLOR] = 2 => cả 2 cái cùng hoạt động. Vậy tại sao MUI lại không giữ được mà Custom value of khỉgìđấy lại giữ được? À, là bởi vì người ta quy định vậy đấy, biết vậy thôi, khỏi thắc mắc. Quay lại đoạn code, Move = Move + 3 (vậy thôi?)"[/COLOR] Cám ơn bác rất nhiều, đúng là nhanh hơn thật ;))
                  Set Point[TempValue] = (Position of Caster[TempValue]) //biến Point = vị trí của tênmàumè, ta set nó ở trigger 2 để kiểm tra vị trí của hắn mỗi 0.05s vì hắn màu mè mà, chạy lung tung cả lên.
                  Set Bien[TempValue] = (Bien[TempValue] x -1) //chà, cái này khó à nha. Ta có: Biến = 1 (Giả thiết). Thay Biến = 1 vào biểu thức Biến = Biến x (-1) ta được: Biến = 1 x (-1) (sai) nhưng.... làm tiếp. Do đó Biến = -1. Lại thay Biến = -1 tiếp, ta lại được Biến = -1 x (-1) (lại sai) nhưng .... lại làm tiếp. => WE bị sai. Vậy Biến = 1 và sau 0.05s sẽ thành -1 rồi ngược lại vì 1 x (-1) = -1 rồi -1 x (-1) = 1 rồi 1 x (-1) = -1 rồi .... rất đơn giản nhưng nó sẽ tạo ra kì văn tích (phóng đại thôi) 
                  Set Point3[TempValue] = Target[TempValue] //Biến Point3 = "Điểm mà tênmàumè di-chuyển-một-cách-màu-mè tới." set tiếp để check tiếp.
                  Set Point2[TempValue] = (Point[TempValue] offset by 200 towards ((Angle from Point[TempValue] to Point3[TempValue]) + (45 x (Real(Bien[TempValue]))) degrees //Biến Point2 = điểm cách vị trí của tênmàumè 200km ở góc từ vị trí của tênmàumè đến "Điểm mà tênmàumè di-chuyển-một-cách-màu-mè tới." + 45 độ x với biến. Ở đây, do Biến luôn thay đổi từ - thành + và ngược lại nên 45 độ cũng thay đổi từ - thành + sau mỗi 0.05s. Mình sẽ cho 1 VD cụ thể về đoạn code này. Ta có : góc từ vị trí của tênmàumè đến "Điểm mà tênmàumè di-chuyển-một-cách-màu-mè tới." = 60 độ tức hướng 2h (I like it). => ta có cái hình :
Point2.jpg

Thầy dạy toán bảo phải chấm mấy cái điểm đậm lên để có gì còn ăn gian được, bời vậy đừng thắc ắc tại sao nó như vậy nhé. Đó là trên lí thuyết của đoạn code. Đây là sơ đồ thực tế (ôi kì tích \m/):
Point22.jpg

Mã:
                  Unit - Move Caster[TempValue] instantly to Point2[TempValue], facing Point3[TempValue] //cái này là lí do làm hắn chạy lung tung này.                       
                  If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        If - Conditions
                              (Distance between Point[TempValue] and Point3[TempValue]) Less than or equal to 200.00 //Nếu khoảng cách từ tênmàumè đến "Điểm mà tênmàumè di-chuyển-một-cách-màu-mè tới." nhỏ hơn hoặc bằng 200.00 thì..... xuống dưới.
                        Then - Actions
                              Unit - Move Caster[TempValue] instantly to Point3[TempValue], facing Point3[TempValue] //Ném hắn vào đúng chỗ của hắn ("Điểm mà tênmàumè di-chuyển-một-cách-màu-mè tới.") để không bị lệch.
                              Unit Group - Remove (Picked unit) from Group //xóa tên hắn trong sổ điểm *gạch gạch*.
                              Unit - Remove (Picked unit) from the game //đuổi tên tự kỉ đi vì hắn hết bệnh rồi.
                        Else - Actions
                  Custom script: call RemoveLocation(udg_Point[udg_TempValue])
                  Custom script: call RemoveLocation(udg_Point2[udg_TempValue])
                  Custom script: call RemoveLocation(udg_Point3[udg_TempValue])
                  Custom script: call RemoveLocation(udg_Target[udg_TempValue])
      If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                  (Number unit in Group) Equal to 0 //như trên, có gì xem lại #1 nhé ....//Khi cái nhóm "tự kỉ vì MUI" không còn đứa nào vì tụi nó đã hết bệnh.(Ôi! thời đại của bọn tự kỉ đã hết)
            Then - Actions
                  Trigger - Turn off (This trigger) //kết thúc cái sự màu mè. RemoveLeak không thì chúng ta sẽ được rèn luyện sự kiên nhẫn mỗi khi tênmàumè giở chứng.
            Else - Actions
Xong phần trên ta vào game test thử xem thế nào.
II. Thêm các Special Effect (Hiệu ứng đặc biệt).
Trigger 1
Mã:
Event
      Unit - A unit Starts the effect of an ability
Conditions
      (Ability being cast) Equal to Blink
Actions
      Set MUI = (MUI + 1)
      If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                  MUI Equal to 500
            Then - Actions
                  Set MUI = 0
            Else - Actions
      Set Caster[MUI] = (Triggering unit)
      Set Point[MUI] = (Position of Caster[MUI])
      Set Target[MUI] = (Target point of ability being cast)
      Set Bien[MUI] = 1
      Unit - Order Caster[MUI] to stop
      Unit - Create 1 Dummy for Owner of Caster[MUI]) at Point[MUI] facing Default building facing degrees
      Unit - Set the custom value of (Last created unit) to Group
      [B]Lightning - Creat a Lightning Attack lightning effect from source Point[MUI] to target Point[MUI] //tạo Lightning Attack (cái đường sét như chain lightning ấy) từ vị trí của tênmàumè tới vị trí của tênmàumè (các bạn biết mình rãnh cỡ nào rồi đấy)
      Set Lightning[MUI] = (Last created lightning effect) //đặt biến Lightning = cái Lightning vừa tạo để mình vác sang trigger 2[/B]
      Trigger - Turn on Untitled Trigger 002 <gen>
Trigger 2
Mã:
Event
      Time - Every 0.05 seconds of game time
Conditions
Actions
      Unit Group - Pick every unit in Group and do (Actions)
            Loop - Actions
                  Set TempValue = [(Custom value of (Picked unit))]
                  Set Point[TempValue] = (Position of Caster[TempValue])
                  Set Bien[TempValue] = (Bien[TempValue] x -1)
                  Set Point3[TempValue] = Target[TempValue]
                  Set Point2[TempValue] = (Point[TempValue] offset by 200 towards ((Angle from Point[TempValue] to Point3[TempValue]) + (45 x (Real(Bien[TempValue]))) degrees
                  Unit - Move Caster[TempValue] instantly to Point2[TempValue], facing Point3[TempValue]
                  [B]Special Effect - Create a special effect at Point[TempValue] using Abilities\Spells\Orc\MirrorImage\MirrorImageCaster.mdl //Ya, đây là cái sự màu mè của spell, tạo 1 effect ở vị trí của tênmàumè.
                  Special Effect - Destroy (Last created special effect) //Hủy effect
                  Lightning - Move Lightning[TempValue] to source Point[TempValue] and targer Point2[TempValue] //di chuyển cái lightning effect sang những vị trí khác, cái này mình cũng không hiễu rõ nữa. À là vầy, cái lightning effect này nè sẽ được chuyển từ cái chỗ mà aicũngbiếtrồiđấy để tới cái từ Point tới Point2 (vì Point2 được set trước khi Point được thay đổi nên sẽ tạo được 1 đường lightning (vì vị trí cách vị trí của tênmàumè 200.00km với 1 góc... được set trước khi vị trí của tênmàumè nên sẽ tạo được 1 đường lightning. (Đẹp, chẹp chẹp) 
                  Special Effect - Create a special effect at Point[TempValue] using Abilities\Weapons\Bolt\BoltImpact.mdl //Effect
                  Special Effect - Destroy (Last created special effect) //Hủy effect       
                  Special Effect - Create a special effect at Point2[TempValue] using Abilities\Spells\Orc\LightningBolt\LightningBoltMissile.mdl //Effect
                  Special Effect - Destroy (Last created special effect) //Hủy effect[/B]     
                  If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        If - Conditions
                              (Distance between Point[TempValue] and Point 3[TempValue) Less than or equal to 200.00
                        Then - Actions
                              [B]Lightning - Detroy Lightning[TempValue] //Hủy Lighning đi, không thì còn 1 đường sét đấy, trông vui lắm, nhưng đừng có dại mà để lại (như kiểu di chứng sau bệnh tật vậy đó, rất nguy hiểm)[/B]
                              Unit - Move Caster[TempValue] instantly to Point 3[TempValue], facing Point3[TempValue]
                              Unit - Remove (Picked unit) from the game
                              Unit Group - Remove (Picked unit) from Group
                              Custom script: call RemoveLocation(udg_Point[udg_TempValue])
                              Custom script: call RemoveLocation(udg_Point2[udg_TempValue])
                              Custom script: call RemoveLocation(udg_Point3[udg_TempValue])
                              Custom script: call RemoveLocation(udg_Target[udg_TempValue])
                        Else - Actions
      If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                  (Number unit in Group) Equal to 0
            Then - Actions
                  Trigger - Turn off (This trigger)
            Else - Actions
Hết, chúc thành công, mong các bạn post spell (Đep đẹp lên để mọi người cùng học hỏi, và cũng để (mở rộng tầm mắt, cũng như thể hiện được sự sáng tạo của người VN qua Game (Cụ thể là W3), cũng như cho thấy game là 1 phương tiện để phát triển tư duy (thiểu số thôi)) kho tàng spells VN "chất đống". Xin chân thành cảm ơn gia đình nhà trường và forum để em được như ngày hôm nay em rất tự hào về em)
 

Attachments

Chỉnh sửa cuối:
Nên cho (Custom value of (Picked unit)) vào một biến, như vậy sẽ:
- gọn hơn
- chạy nhanh hơn (vì mỗi lần (Custom value of (Picked unit)) là một lần gọi hàm, gọi nhiều lần rõ ràng chậm hơn gọi một lần)
- và lúc code thì chọn một biến chắc chắn nhanh hơn chọn custom value... =))

ngoài ra các point: Point, Target chả thấy Remove ở đâu cả -> leak

Mã:
Event
      Time - Every 0.05 seconds of game time
Conditions
Actions
      Unit Group - Pick every unit in Group and do (Actions)
            Loop - Actions
                  Set TempValue = (Custom value of (Picked unit))
                  Set Point[TempValue] = (Position of Caster[TempValue])
                  Set Bien[TempValue] = (Bien[TempValue] x -1)
                  Set Point3[TempValue] = Target[TempValue]
                  Set Point2[TempValue] = (Point[TempValue] offset by 200 towards ((Angle from Point[TempValue] to Point3[TempValue]) + (45 x (Real(Bien[TempValue]))) degrees
                  Unit - Move Caster[TempValue] instantly to Point2[TempValue], facing Point3[TempValue]                       
                  If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        If - Conditions
                              (Distance between Point[TempValue] and Point 3[TempValue]) Less than or equal to 200.00
                        Then - Actions
                              Unit - Move Caster[TempValue] instantly to Point 3[TempValue], facing Point3[TempValue]
                              Unit - Remove (Picked unit) from the game
                              Unit Group - Remove (Picked unit) from Group
                              Custom Script: call RemoveLocation( Target[TempValue] )
                        Else - Actions
                  Custom Script: call RemoveLocation( Point[TempValue] )
                  Custom Script: call RemoveLocation( Point2[TempValue] )
      If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                  (Number unit in Group) Equal to 0
            Then - Actions
                  Trigger - Turn off (This trigger)
            Else - Actions

p.s: cho vào quote làm gì :-/
 
Chỉnh sửa cuối:
Nên cho (Custom value of (Picked unit)) một biến, như vậy sẽ:
- gọn hơn
- chạy nhanh hơn (vì mỗi lần (Custom value of (Picked unit)) là một lần gọi hàm, gọi nhiều lần rõ ràng chậm hơn gọi một lần)

p.s: cho vào quote làm gì :-/
Chia làm 2 phần đấy bác, tại máy bị trục trặc chưa giải thích xong thì bấm nhầm nút gửi @@, lại còn bị crash thế là đi tong cái đống giải thích nãy giờ viết mỏi tay, em sẽ bổ sung sau. Nản quá. Bây giờ thì bận rồi, sẽ sớm edit. Mong các bác thông cảm.
 
Chỉnh sửa cuối:
t.jpg

Mã:
scope FireMassing initializer init
//>>>>>>>>>>>>>>>>>>>>>>>>>SETUP<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<//
//Đây là phần cài đặt cho spell:
globals
    private constant integer SPELL_ID = 'A001'//ID của dummy ability mà bạn dùng, phải là 1 abi target ground hoặc target unit
    private constant integer DUMMY_UNIT_ID = 'e000'//cái này hình như thừa... cứ thử bỏ đi xem. Tại spell làm lâu rồi cũng chẳng nhớ LOL
    private constant integer EFF_UNIT_ID = 'e002'//Unit đóng vai trò missle
    private constant string EFF = "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"//Hiệu ứng đặc biệt khi tên chạm enemy hoặc đã bay hết quãng đg cho phép
                                //"Abilities\\Weapons\\Rifle\\RifleImpact.mdl"
                                //"Abilities\\Spells\\Human\\SpellSteal\\SpellStealMissile.mdl"
                                //"Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl"
                                //"Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"
    
endglobals
//Advance:
private function speed takes nothing returns real
    return 0.01 //lager value, more slower (tốc độ của mũi tên, vì là time out của timer nên càng nhỏ thì mũi tên bay càng nhanh)
endfunction

private function range takes nothing returns real
    return 1500.00 //quãng đường tối đa ma mũi tên có thể bay
endfunction

private function radius takes nothing returns real
    return 100.00 //the radius for detecting collision (Bán kính phát hiện va chạm AOE/2 đó :)) )
endfunction

private function amount takes nothing returns integer
    return 10 //the numbers of arrow per cast (số lượng mũi tên)
endfunction

private function dam takes integer aLevel returns real
    return 100.00 * aLevel//dam per arrow (hàm tính dam dựa theo lvl skill)
endfunction

private function addOn takes unit trigUnit, unit dam2Unit returns nothing
    //this option is for advance user, you can add your code here to Make
    //more effect when the projectile impact to enemy. ex: knock back, dam over time... 

   // hàm này được gọi khi mũi tên va chạm với enemy, hàm này hiện để trống, muốn thêm cái gì vào đây thì thêm
   //à quên trigUnit là caster, dam2Unit là unit bị bắn trúng
endfunction

//>>>>>>>>>>>>>>>>>>>>>>>ENDSETUP<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<//

//=================Confuse zone==============//
//Dont edit this bunk of code unless you
//really wanna do
//Phần dưới này để thư thư rồi giải thích tiếp nhé :D
//===========================================//
globals
    private constant real MOVE = 10.0 //distance that the projectile will move Per
                                      //*speed()* . You should'nt change this
    private constant real deviation = 10.0 //deviation between projectile
endglobals




private struct Projectile
    unit u//projectile
    unit uT// trigger unit
    real angle
    real moved = 0
    
    boolean stop = false
    
    method control takes nothing returns nothing
        local location moveLoc = PolarProjectionBJ(GetUnitLoc(.u), MOVE, .angle)
        //valriable for collision detect:
        local group cGrp = GetUnitsInRangeOfLocAll(radius(),moveLoc)
        local unit uDam
        
        //move the unit(projectile)
        call SetUnitPositionLoc(.u,moveLoc)
        
        //collision detect and dam enemy:
        set uDam = FirstOfGroup(cGrp)
        if uDam != null then
        
            loop
                exitwhen uDam == null
                if IsUnitEnemy(uDam,GetOwningPlayer(.uT)) and IsUnitAliveBJ(uDam) then 
                    
                    call UnitDamageTargetBJ(.uT, uDam, dam(GetUnitAbilityLevel(.uT,SPELL_ID)),ATTACK_TYPE_MAGIC,DAMAGE_TYPE_MAGIC)
                    call addOn(.uT,uDam)
                    set .stop = true//need improve
                endif
                
                call GroupRemoveUnit(cGrp,uDam)
                
                set uDam = FirstOfGroup(cGrp)
            endloop
            
            
        endif
        
        
        //out of range detect:
        if .moved < range() then
            set .moved = .moved + MOVE//if still in range, then set the .moved value go up
        else 
            set .stop = true
        endif
        
        //play animation
        if .stop then
            call DestroyEffect(AddSpecialEffectLoc(EFF,moveLoc))
        endif
        
        //remove leak
        call RemoveLocation(moveLoc)
        call DestroyGroup(cGrp)
        set moveLoc = null
        set cGrp = null
        set uDam = null
    endmethod
    
    
endstruct

globals
    private integer Total = 0
    private timer T = CreateTimer()
    private Projectile array pArr
endglobals

                                  

private function timerLoop takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen(i >= Total)
     
        if pArr[i].stop then
            call KillUnit(pArr[i].u)//kill the projectile to not display it any more
            call pArr[i].destroy()//Not need this instance any more
            set Total=Total-1//degrease the Total by 1
            if Total > 0 then
                set pArr[i]=pArr[Total]
                set i=i-1//if not the loops will forget to handle the pArr[Total] ^^
            else
                call PauseTimer(T)
            endif
        else
            call pArr[i].control()
        endif
        
    
        set i = i + 1
    endloop
 
    //call BJDebugMsg("yeah")
endfunction

//extra function for formula caculate:
private function angleCalculate takes real angle, integer iAddOne returns real
    local real result = 0
    //==========for div number of *amount()*:
    local real halfDev //deviation / 2
    local real cen1
    local real cen2
    local integer cen1Index
    local integer cen2Index
    //==========for odd number of *amount()*:
    local integer cenIndex
    local real cen
    
    //div:
    if ModuloInteger(amount(),2)==0 then
        //call BJDebugMsg("so chan")
        set halfDev = deviation/2
        set cen1 = angle - halfDev
        set cen2 = angle + halfDev
        set cen1Index = amount()/2
        set cen2Index = cen1Index + 1
        
        if iAddOne == cen1Index then
            set result = cen1
        elseif iAddOne < cen1Index then
            set result = cen1 - deviation*(cen1Index - iAddOne)
        elseif iAddOne == cen2Index then
            set result = cen2
        elseif iAddOne > cen2Index then
            set result = cen2 + deviation*(iAddOne - cen2Index)
        endif
        
        
    //odd:    
    else
        //call BJDebugMsg("so le")
        set cen = angle
        set cenIndex = ((amount() - 1)/2) + 1
        
        if iAddOne == cenIndex then
            set result = angle
        elseif iAddOne > cenIndex then
            set result = cen - (deviation*(iAddOne - cenIndex))
        else
            set result = cen + (deviation*(cenIndex - iAddOne))
        endif
    endif
    
    return result
endfunction

//====================end=====================//


//Condition================================================================
private function condition takes nothing returns boolean
    return GetSpellAbilityId() == SPELL_ID
endfunction

//Actions==================================================================


private function Actions takes nothing returns nothing
    local player pT =  GetOwningPlayer(GetTriggerUnit())
    local location tar = GetSpellTargetLoc()
    local location self = GetUnitLoc(GetTriggerUnit())
    local real deg = AngleBetweenPoints(self,tar)
    local Projectile p
    //
    local integer iPlus = 1
    

    
    if Total == 0 then
        call TimerStart (T, speed(), true, function timerLoop)
    endif
   
    //
    loop
    exitwhen iPlus > amount()
        set p = Projectile.create()
        set p.u = CreateUnitAtLoc(pT,EFF_UNIT_ID,self,angleCalculate(deg,iPlus))
        set p.angle = angleCalculate(deg,iPlus)
        set p.uT = GetTriggerUnit()
        
        //call BJDebugMsg(R2S(angleCalculate(deg,iPlus)))
        //call BJDebugMsg(I2S(Total))
        
        set pArr[Total] = p
        set Total = Total + 1
    
        set iPlus = iPlus + 1
    endloop
    
    //remove leak
    set pT = null
    call RemoveLocation(tar)
    call RemoveLocation(self)
    set tar = null
    set self = null
 
endfunction

//Initializer==============================================================
private function init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( t, function Actions )
    call TriggerAddCondition(t,Condition(function condition))
endfunction

endscope

demo map: http://dl.dropbox.com/u/14083092/Maper/Hero_FireRanger.w3x

Spell đơn giản thôi, bắn 1 lượng cung tùy ý ra phía trước. Có thể thêm bất cứ hiệu ứng nào vào unit bị trúng tên (dam over time hay knock back.... tùy) :D
Có gì giải thích sau nhé h đang bận với cái project
 
Chỉnh sửa cuối:
có đọc post #1 ko? code thì phải cho vào thẻ
Mã:
 chứ? sửa lại đi

và ko giải thích được thì đừng post
test map còn ko có cơ, muốn 3pts spam ko? =))
 
Một số góp ý cho chiêu blink :
[+] Good idea
[+] Good code
[-] Nhiều hiệu ứng thừa ko cần thiết, theo mình chỉ cần để cái effect phân thân và blink thôi( hoặc giữ cái LightningBoltMissile cũng đc), thêm cái sấm sét vào nghe tiếng nó...ghê ghê thế nào.
[-] Sao cast spell xong hero lúc nào cũng quay mặt về phía bên phải thế? Mà gắn effect vào point như này có gây leak ko nhỉ?
Thêm nữa là nên để time là 0.03s thì hợp hơn, 0.05 move hơi chậm :).

P/s : Mình thích cái topic này \m/!
 
Chỉnh sửa cuối:
Vâng, mình là người yêu-cái-đẹp và ồn-ào nên bạn thông cảm.
 
Nhận xét thêm về spell ZZBlink:

  • Trigger 1:
    sao lại có thể: Unit - Set the custom value of (Last created unit) to Group đặt custom value = unit group? chỗ đó phải là biến MUI chớ nhỉ?
  • Trigger 2:
    • chưa đặt TempValue
    • đoạn remove dummy rồi remove dummy khỏi group, nên remove dummy khỏi group trước khi remove dummy.
    • xóa leak thế này ko ổn
      Set Point[TempValue] = (Position of Caster[TempValue])
      Set Point2[TempValue] = ...
      mỗi lần chạy là một lần tạo point mới, vậy mà có mỗi một lần xóa (lúc trigger này dừng hẳn vì ko còn dummy), vậy leak rất nhiều

      Point3Target do chỉ được tạo ra một lần nên chỉ cần một lần xóa, cái này không sai, và phải để trong cái If có xóa dummy mới đúng vì mỗi dummy sẽ có một "target point" ứng với nó.

      ngoài ra, cái "If" dùng để xóa point lại đặt ngoài loop - action của Unit Group - Pick... kia nên GetEnumUnit() đâu có tác dụng?
      và một lần nữa, dùng TempValue luôn có nhanh hơn ko?
 
Em đã sửa, cảm ơn bác. :|
Mình đã update phần chú ý ở #1, các bạn đọc và tích cực tham gia nhé. Cố gắng 1 ngày 1 thành viên được 1 spell.
 
Cho mình hỏi với. Khi làm các bạn thường cho biến Mui=Mui+1 mà mình không hiểu nó có tác dụng gì? Có phải để tránh lag game không?
À! Mình hiểu rồi. Cám ơn nhé skill đẹp lắm nhưng bạn để nhiều creep quá không tài nào test nổi skill. Bạn nên để nông dân còn các skill sau thì nên để 0 cd hoặc cho phép hồi cd chứ khó test skill quá :D.
 
Chỉnh sửa cuối:
Mã:
Set MUI = (MUI + 1) //có nghĩa là ban đầu MUI = 0, sau 1 lần cast thì MUI = 0 + 1, khi đó MUI = 1, tiếp tục lần thứ 2 MUI = (MUI = 1) + 1 thì MUI = 2, rồi lần thứ 3 MUI = (MUI = 2(1 + 1 = 2)) + 1, lần thứ 4 MUI = (MUI = 3(2+1 = 3)) + 1, rồi lần thứ 5 MUI = 4 + 1 = 5, rồi lần thứ 6 MUI = 5 + 1 = 6...................
Có giải thích rất kĩ trên spell đấy bạn, phải đọc thì mới hiểu chứ. Và vì đó là Spell MUI nên dùng 1 biến Integer để đếm, mỗi lần cast biến Integer đó lại thay đổi giá trị =>các đoạn code ko bị trùng nhau là hoạt động độc lập => có thể dùng spell đó nhiều lần cùng 1 lúc mà không bị bug.
 
Chỉnh sửa cuối:
MUI vậy thì các biến có array để MUI, array lên đến 500 à? Mình không quen làm MUI kiểu này (làm MUI có từng player thì mình biết) nên ai giải thích hộ.
 
Đúng rồi, lên đến 500 thì set MUI = 0. Tại thấy để 100 thì ít quá :P
 
Ké cái spell :P

Tên Spell: Rock's Dance \:D/(vũ điệu của đá)
MUI: yes
Leak + lag: ít lag và ít leak (hi vọng thế :D)
Mô tả:
ENG:
[spoil]Creates a rock that jumps forwardly and deals damage to units nearby. When arrives at the target point, the rock will jump back.

Level 1 - 180 total damage.
Level 2 - 240 total damage.
Level 3 - 300 total damage.
Level 4 - 360 total damage.[/spoil]
VN:
[spoil]Tạo 1 tảng đá "nhảy" về phía trước, gây sát thương lên các units trong tầm. Khi tới mục tiêu, tảng đá sẽ "nhảy" ngược về vị trí cũ.

Level 1 - 180 sát thương (đi 90 về 90)
Level 2 - 240 sát thương (đi 120 về 120)
Level 3 - 300 sát thương (đi 150 về 150)
Level 4 - 360 sát thương (đi 180 về 180)[/spoil]

Cách làm:
Cần các biến sau:
MUI, TempValue: integer
RD_Caster[array], RD_Unit[array]: unit
RD_CasterPoint[array], RD_TargetPoint[array], RD_TempPoint[array]: point
TempPoint, TempPoint2: point (cẩn thận với các biến point này, dễ nhầm lắm đấy)
RD_Group. DR_TargetGroup[array], TempGroup: group
Cuối cùng là thêm 1 chú dummy có model hòn đá, Leo dùng model volcano missile có sẵn trong WE, đường dẫn của model: Abilities\Spells\Other\Volcano\VolcanoMissile.mdl

Trigger:
Mã:
Rocks Dance
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to (==) Rock's Dance 
    Actions
         [COLOR="Blue"][Hàm if này dùng để MUI, Leo không nói nhé (raivor nói ở mấy bài đầu rồi)][/COLOR]
         Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                MUI Equal to (==) 100
            Then - Actions
                Set MUI = 0
            Else - Actions
                Set MUI = (MUI + 1)
        Set RD_Caster[MUI] = (Triggering unit) [COLOR="Blue"]// đặt caster vào biến, dùng để deal damage[/COLOR]
        Set TempPoint = (Position of RD_Caster[MUI]) [COLOR="Blue"]// dùng để đỡ leak[/COLOR]
        Set TempPoint2 = (Target point of ability being cast) [COLOR="Blue"]// như trên[/COLOR]
       [COLOR="Red"] Set TempPoint3 = (TempPoint offset by 20.00 towards (Angle from TempPoint to TempPoint2) degrees)[/COLOR] [COLOR="Blue"]// đây là vị trí mà dummy (tảng đá) xuất hiện[/COLOR]
        Unit - Create 1 Dummy for (Owner of RD_Caster[MUI]) at TempPoint3 facing Default building facing (270.0) degrees 
        Set RD_Unit[MUI] = (Last created unit)
        Unit - Add Crow Form to (Last created unit) [COLOR="Blue"]// add và remove ability crow form để dummy có thể bay[/COLOR]
        Unit - Remove Crow Form from (Last created unit)
        Animation - Play (Last created unit)'s birth animation [COLOR="Blue"]// vì volcano missile có animation birth là hình tảng đá nên ta chỉ dùng animation này[/COLOR]
        Unit - Set the custom value of (Last created unit) to MUI [COLOR="Blue"]// dùng để MUI[/COLOR]
        Unit Group - Add (Last created unit) to RD_Group [COLOR="Blue"]// add mấy chú đá vào group để lát "kiêu" cho dễ[/COLOR]
        Set RD_CasterPoint[MUI] = (Position of RD_Caster[MUI]) [COLOR="Blue"]// đây là point mà dummy sẽ quay lại[/COLOR]
        Set RD_TargetPoint[MUI] = (TempPoint offset by 800.00 towards (Angle from TempPoint to TempPoint2) degrees) [COLOR="Blue"]// point này là hướng đi và đích đến của dummy[/COLOR]
        Set RD_TempPoint[MUI] = (TempPoint offset by 300.00 towards (Angle from TempPoint to RD_TargetPoint[MUI]) degrees) [COLOR="Blue"]// point này là điểm chạm đất của dummy[/COLOR]
        Set RD_Damage[MUI] = (60.00 + ((Real((Level of Rock's Dance  for RD_Caster[MUI]))) x 30.00)) [COLOR="Blue"]// damage sẽ gây ra mỗi lần dummy đi qua
        [Và đây là phần xóa leak point][/COLOR]
        Custom script:   call RemoveLocation(udg_TempPoint)
        Custom script:   call RemoveLocation(udg_TempPoint2)
        Custom script:   call RemoveLocation(udg_TempPoint3)
Mã:
Rocks Dance Move
    Events
        Time - Every 0.05 seconds of game time
    Conditions
    Actions
        Unit Group - Pick every unit in RD_Group and do (Actions)
            Loop - Actions
                [COLOR="Blue"] [Hàm if kiểm tra nếu không có dummy nào tồn tại thì reset MUI, xóa leak group][/COLOR]
                 Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        (Picked unit) Equal to (==) No unit
                    Then - Actions
                        Set MUI = 0 [COLOR="Blue"]// reset MUI[/COLOR]
                        Custom script:   call DestroyGroup(udg_RD_Group) [COLOR="Blue"]// xóa leak[/COLOR]
                    Else - Actions
                        [COLOR="Blue"][Nếu có dummy tồn tại thì trigger sẽ thực hiện những lệnh sau][/COLOR]
                        Set TempPoint = (Position of (Picked unit))
                        Set TempValue = (Custom value of (Picked unit))
                        [COLOR="Blue"][Hàm if kiểm tra khoảng cách của dummy, nếu dummy đã tới RD_CasterPoint, tức là đã về nhà thì sẽ kill dummy + xóa leak][/COLOR]
                         Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            If - Conditions
                                [COLOR="Red"](Distance between TempPoint and RD_CasterPoint[TempValue]) Less than or equal to (<=) 10.00[/COLOR] // dòng này, số 10 có thể thay đổi nhưng phải nhỏ hơn khoảng cách create dummy (dòng in đỏ) ở trigger trước 
                            Then - Actions
                                Unit - Kill (Picked unit)
                                [COLOR="Blue"][Xóa leak point][/COLOR]
                                Custom script:   call RemoveLocation(udg_RD_TargetPoint[udg_TempValue])
                                Custom script:   call RemoveLocation(udg_RD_TempPoint[udg_TempValue])
                                Custom script:   call RemoveLocation(udg_TempPoint)
                            Else - Actions
                                 [COLOR="Blue"][Nếu điều kiện trên sai thì sẽ thực hiện hàm if này, nó làm cho dummy bay lên hoặc rớt xuống][/COLOR]
                                 Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    If - Conditions
                                        [COLOR="Red"](Distance between TempPoint and RD_TempPoint[TempValue]) Greater than or equal to (>=) 150.00[/COLOR] [COLOR="Blue"]// bạn có thể thay 150 = số khác, nhưng nó phải = 1 nửa khoảng cách của RD_TempPoint, ở trigger đầu, Leo cho RD_TempPoint là 300 nên ở đây sẽ là 150[/COLOR]
                                    Then - Actions
                                        [COLOR="SeaGreen"]Animation - Change (Picked unit) flying height to ((Current flying height of (Picked unit)) + 50.00) at 0.00 [/COLOR][COLOR="Blue"]// bay lên[/COLOR]
                                    Else - Actions
                                        [COLOR="SeaGreen"]Animation - Change (Picked unit) flying height to ((Current flying height of (Picked unit)) - 50.00) at 0.00 [/COLOR][COLOR="Blue"]// hạ xuống[/COLOR]
                                 [COLOR="Blue"][Hàm if này kiểm tra nếu dummy chạm đất thì tạo effect, deal damage][/COLOR]
                                 Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    If - Conditions
                                        (Distance between TempPoint and RD_TempPoint[TempValue]) Less than or equal to (<=) 10.00
                                    Then - Actions
                                        Set RD_TempPoint[TempValue] = (TempPoint offset by 300.00 towards (Angle from TempPoint to RD_TargetPoint[TempValue]) degrees) [COLOR="Blue"]// đặt lại vị trí RD_TempPoint, tức là dummy sẽ tiếp tục "nhảy"[/COLOR]
                                        [COLOR="Blue"][Phần effect này, Leo cố lắm mới nghĩ ra được 2 cái effect:D][/COLOR]
                                        Special Effect - Create a special effect at TempPoint using Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
                                        Special Effect - Destroy (Last created special effect)
                                        Special Effect - Create a special effect at TempPoint using Abilities\Spells\Other\Doom\DoomDeath.mdl
                                        Special Effect - Destroy (Last created special effect)
                                        [COLOR="Blue"][Và phần deal damage][/COLOR]
                                        Set TempGroup = (Units within 250.00 of TempPoint matching (((((Matching unit) is A structure) Equal to (==) False) and (((Matching unit) is alive) Equal to (==) True)) and ((((Matching unit) belongs to an enemy of (Owner of (Picked unit))) Equal to (==) True) and (((Matching unit) is in RD_TargetGroup[TempValue] Equal to (==) False)
                                        [COLOR="Blue"][Action trên khá dài, có 4 conditions trong đó, 1 pick unit không là structure, 2 pick unit còn sống, 3 pick unit phải là kẻ thù của dummy( caster), 4 pick unit không nằm trong RD_TargetGroup (tránh gây damage nhiều lần cho 1 unit)][/COLOR]
                                        Unit Group - Pick every unit in TempGroup and do (Actions)
                                            Loop - Actions
                                                Unit - Cause RD_Caster[TempValue] to damage (Picked unit), dealing RD_Damage[TempValue] damage of attack type Spells and damage type Normal [COLOR="Blue"]// deals damage đã đặt sẵn trong trigger trước[/COLOR]
                                                Unit Group - Add (Picked unit) to RD_TargetGroup[TempValue]
                                        Custom script:   call DestroyGroup(udg_TempGroup) [COLOR="Blue"]// xóa leak group[/COLOR]
                                    Else - Actions
                                 [COLOR="Blue"][Hàm if sau dùng để cho dummy quay đầu về và deal damage lần 2][/COLOR]
                                 Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    If - Conditions
                                        (Distance between TempPoint and RD_TargetPoint[TempValue]) Less than or equal to (<=) 10.00
                                    Then - Actions
                                        Set RD_TargetPoint[TempValue] = RD_CasterPoint[TempValue] [COLOR="Blue"]// đặt RD_TargetPoint là điểm khởi đầu của dummy, vì dummy chỉ move theo hướng của RD_TargetPoint[/COLOR]
                                        Unit Group - Remove all units from RD_TargetGroup[TempValue] [COLOR="Blue"]// xóa RD_TargetGroup để deal damage lần 2[/COLOR]
                                    Else - Actions
                                [COLOR="SeaGreen"]Set TempPoint2 = (TempPoint offset by 25.00 towards (Angle from TempPoint to RD_TempPoint[TempValue]) degrees)[/COLOR]
                                Unit - Move (Picked unit) instantly to TempPoint2 [COLOR="Blue"]// move dummy (kết hợp với action change flying height nên mới có cảm giác dummy "nhảy"
                                [Xóa leak point][/COLOR]
                                Custom script:   call RemoveLocation(udg_TempPoint)
                                Custom script:   call RemoveLocation(udg_TempPoint2)
Chú ý:
-Phần màu đỏ là phần cần chú ý nhé.
-Phần màu xanh quyết định tốc độ và độ cao của tảng đá
Trigger dài dòng vậy nhưng có thể diễn tả như sau:
- Khi cast sẽ tạo 1 dummy (tảng đá) ở vị trí unit, mục tiêu là RD_TargetPoint, dummy sẽ move dần tới đó, đoạn đường đi sẽ chia làm 3 (hay 4 nhỉ? quên rồi) đoạn ứng với những lần mà dummy sẽ nhảy, mỗi đoạn lại chia làm 2 ( 1 bay lên và 1 rớt xuống). Khi dummy đến được chỗ RD_TargetPoint, lúc này biến đó sẽ được đặt là vị trí cũ của dummy, nên nó sẽ quay về.

Và đây là kết quả ;)) (Skill không đẹp lắm do Leo không thích màu mè nhiều, các bạn thêm effect vào cho nó nổi bật hơn nhé)
spells_3726_screenshot.jpg

Bạn muốn có demo? Nó đây (khi test nhấn Esc để kiểm tra MUI nhé)

Cho Leo điểm nào :D
 
Chỉnh sửa cuối:
  • Trigger Rocks Dance:
    - chưa remove TempPoint2
    - (Angle from TempPoint to (Target point of ability being cast)) leak
  • Trigger Rocks Dance Move:
    - Muốn change fly height ngay lập tức thì "rate" để 0 chứ để số to thế kia làm gì...
    - Dùng nhiều Picked unit thì cũng nên cho vào biến

biến MUI kia có 100 là tự reset, vậy 101 lần cast cùng lúc thì lỗi à?
tất nhiên khó có thể lên đc số lần đó tuy nhiên thế ko ổn, nên đặt biến MUI = 0 khi RD_Group không còn unit nào.
ngoài ra, spell nào cũng thấy dùng biến MUI, ko sợ đánh nhau sao?
 
Theo nhận xét của bác Tom và riêng của em thì em sẽ chấm như sau:
- Ưu:
+Về ý tưởng: tốt (2đ)
-Khuyết:
+Về thẩm mĩ: khá (0.75đ) (spell không được đẹp mắt cho lắm, nhất là tảng đá X_X. Và nên làm tảng đá "nhảy" mượt hơn.)
+Về code: tàm tạm (0.5đ) (chưa remove hết leak, trình bày khá rối mắt)
+Về phần giải thích: không được cụ thể cho lắm (3đ) (cái này thì theo mình là vậy thôi)
+Về nhận xét riêng của bạn: không thích lắm (0.25đ).
Tổng điểm: 6.5đ
Mong bạn cố gắng lần sau.
 
Back
Top