[Tutorial] How to make custom Auto-Cast spells

Mình cho create special effect creat on right hand of unit sentry using <missile của frost wyrm> nó toàn bị mất hình,lúc hiện ra lúc không,quái vật thì bị mất đầu mất thân bó tay luôn.

Còn chiêu monsoon thì mặt đất phát sáng,lúc có mưa lúc không và không có sét giật vào đầu lũ quái :(

Ôi cái thời còn tập tành trigger :>

Chiêu của silencer nè.

scope GlaivesofWisdom

globals
private integer abil_id = 'A00I' // Glaives of Wisdom ability rawcode
private integer buff_id = 'B004' // Glaives of Wisdom buff rawcode
endglobals
private function Damage takes integer lvl, unit u returns real
return .15*I2R(lvl*GetHeroInt(u,true)) // Bonus damage done
endfunction
private function Steal takes integer lvl returns integer
return 1 // Intel stolen when heroes are killed
endfunction

private struct data
unit u
unit targ
trigger trig

method onDestroy takes nothing returns nothing
call DestroyTrigger(.trig)
endmethod
endstruct

private function Conditions takes nothing returns boolean
if(GetTriggerEventId()==EVENT_PLAYER_UNIT_ATTACKED)then
return GetUnitAbilityLevel(GetAttacker(),abil_id)>0
elseif(GetTriggerEventId()==EVENT_PLAYER_UNIT_SPELL_EFFECT)then
return GetSpellAbilityId()==abil_id
endif
return false
endfunction
private function Effects takes nothing returns boolean
local real r
local data d = GetData(GetTriggeringTrigger())

if GetUnitAbilityLevel(GetTriggerUnit(),buff_id)>0 and d.u==GetEventDamageSource() and GetEventDamage()>.1 then
call DisableTrigger(d.trig)
set r = Damage(GetUnitAbilityLevel(d.u,abil_id),d.u)
call TextTagUnit("+"+I2S(R2I(r)),GetTriggerUnit(),3,216,216,216,.03,1.)
call UnitDamageTarget(d.u,GetTriggerUnit(),r,false,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_DIVINE,null)
endif

return false
endfunction
private function Actions takes nothing returns nothing
local data d = data.create()

set d.trig = CreateTrigger()
if(GetTriggerEventId()==EVENT_PLAYER_UNIT_SPELL_EFFECT)then
set d.targ = GetSpellTargetUnit()
set d.u = GetTriggerUnit()
else
set d.targ = GetTriggerUnit()
set d.u = GetAttacker()
endif
call TriggerRegisterUnitEvent(d.trig,d.targ,EVENT_UNIT_DAMAGED)
call TriggerAddCondition(d.trig,Condition(function Effects))
call SetData(d.trig,d)

call PolledWait2(2.)
call d.destroy()
endfunction

private function Steal_Intel takes nothing returns nothing
local unit u = GetKillingUnit()
local unit targ = GetTriggerUnit()
local integer i

if GetUnitAbilityLevel(u,abil_id)>0 and IsUnitType(targ,UNIT_TYPE_HERO) then
set i = Steal(GetUnitAbilityLevel(u,abil_id))
call SetHeroInt(targ,GetHeroInt(targ,false)-i,true)
call SetHeroInt(u,GetHeroInt(u,false)+i,true)

call TextTagUnit("+"+I2S(i)+" Int",u,255,0,0,230,.03,3.)
call TextTagUnit("-"+I2S(i)+" Int",targ,255,0,0,230,.03,3.)
endif

set u = null
set targ = null
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
local trigger trig = CreateTrigger( )

call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_DEATH)
call TriggerAddAction(trig,function Steal_Intel)

set trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_ATTACKED)
call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(trig,Condition(function Conditions))
call TriggerAddAction(trig,function Actions)
endfunction

endscope
 
Em đang làm skill giống các bác :D...Nhưng mà toàn bộ skill em làm đều base trên cái skill cơ bản của 1 melee map nên nhiều khi lặp lại rất nhàm.trigger em biết dùng 1 chút..
Nhân tiện em muốn hỏi 1 số thứ:
1/cái bẫy nước của kunkka:cho em xin trigger và làm thế nào để mấy thằng dính bắn lên không trung mà không bị stun.
Trong melee map em đang làm,có skill Impale của Cript Lord là có thể bắn lên không trung nhưng nếu sửa đi thì bị mất unit trong tg nhỏ và bị buff stun.Nói chung vấn đề 1 em muốn được gt là làm thế nào để có thể đẩy,ném,bắn unit lên giời như của Ivoker,tiny và kunkka
2/cái trigger để đánh creep ra tiền là gì ạ?
Em có dùng cái Player-turn on flag..mà vẫn không có gì hết.
3/Magina vừa chém vừa hút mana rất hay,các bác dạy em làm giống được không :D
em cảm ơn
 
Tom sẽ hướng dẫn lại cách tạo 1 auto cast spell. Cụ thể là spell Impetus (DotA)

Impetus: hero làm mục tiêu mất nhiều máu hơn, phụ thuộc vào khoảng cách giữa hero và mục tiêu

---
Đầu tiên, vào Object Editor:
- Buffs/Effects: tạo 1 custom buff, base từ Poison (stacking). Đổi tên, đổi icon...
- Abilities: tạo 1 custom ability, base từ Poison Arrows (tìm thấy trong abilities của Neutral Hostile). Chỉnh lại các dữ liệu của Poison Arrows như sau:
Icon: ReplaceableTextures\CommandButtons\BTNImpalingBolt.blp
attachment.php


Sau đó vào Trigger Editor:

Tôi sẽ nói sơ qua cách làm như sau: Ta phải có 1 trigger mà trigger này sẽ hoạt động khi 1 unit "take damage" (nhận sát thương). Và nếu unit đó có buff Impetus thì sẽ deal thêm damage, phụ thuộc vào khoảng cách giữa unit đó và thằng deal dam (Damage Source).
Chú ý: Cho dù spell này đc cast hay để auto (attack ấy) thì nếu đánh trúng thì unit sẽ có buff, cho nên ko lo lỗi gì cả, mà hoàn toàn MUI. Vì khi có buff, ta sẽ remove buff đó luôn, và có Damage Source rõ ràng nên ko lo 2 unit đánh 1 unit sẽ nhầm lẫn.

Vì trigger ko có event: "Generic unit take damage" chỉ có "Specific unit take damage". Nên ta sẽ pick từng unit rồi add event cho trigger cần dùng, pick unit là "specific" rồi đó.

Trigger thứ 1:
attachment.php

Ta cần 2 biến unit group, TempGroup và TakeDamGroup. Khi 1 unit đã có event take damage rồi thì phải add vào TakeDamGroup (để biết là nó "đã có event") nếu add event 2 lần thì sẽ lỗi, unit đó sẽ take 2 lần damage.
Trigger này để add event cho các unit đã đc đặt sẵn.

attachment.php

Trigger này là khi 1 unit "đi" vào bản đồ, cho dù là đc summon, create (trigger),... Tất nhiên vẫn phải kiểm tra xem unit này đã ở trong TakeDamGroup chưa, nếu chưa thì mới add. (cẩn thận vẫn hơn)

attachment.php


Trigger này là trigger chính đây.
Variable:
TempUnit, TempUnit2 - unit,
TempLoc, TempLoc2 - point
TempInt - integer
TempReal - real

Trigger này chưa có event, nhưng event đã đc add nhờ 2 trigger trên. Bây giờ có "event a unit takes damage" rồi.
Đối với event này thì có: (Triggering unit) là unit bị mất máu (một trong những unit đã add event ấy). (Damage source) là unit deal damage.

Trước hết phải turn off trigger này, rồi turn on sau khi xong. Ko turn off sẽ có chuyện ko hay xảy ra.
Sau đó kiểm tra xem Damage source có ability Impetus ko (level > 0), rồi kiểm tra Triggering unit có buff ko. (thật ra chỉ cần điều kiện này thôi, ko cần nhiều)
Nếu Trigger unit có buff, tức là bị Damage source làm mất máu khi dùng Impetus. Vậy ta sẽ cho Damage source deal thêm damage theo khoảng cách giữa 2 unit này. Có số damage rồi thì dùng floating text để show và dùng Unit - Damage Target để deal damage thôi. Nhớ là pure damage thì nên dùng ATTACK_TYPE_CHAOS và DAMAGE_TYPE_UNIVERSAL.

Đến đây thì đã xong rồi, từ cách làm này các bạn có thể tạo các auto cast spell mà mình muốn. Hoặc vài spell như trong DotA: Glaive of Wisdom (deal damage = % Int ) Arcane Orb (deal damage = % current mana)
----



-----
BONUS SPELLS:

Thêm 1 spell nữa nhá. Ai chơi DotA 6.53 rồi sẽ biết Magina ( Anti Mage ) có cái blink rất "ảo" (nhiều người cho rằng rất "cool", tôi cũng nghĩ thế, chỉ hơi thiếu tí sound thôi)

Ta cần các biến sau:
InstantMovementCaster, InstantMovementDummy - unit //caster và dummy
InstantMovementFade - real //đây là biến đếm cho việc "mờ" của dummy và caster
InstantMovementBlink - boolean //biến này để kiểm tra xem caster đã cast xong chưa, xong rồi thì mới hiện dummy và bắt đầu "mờ" dummy, caster.

Cần 4 trigger ( :| )
Mã:
InstantMovementBegin
    Events
        Unit - A unit Begins casting an ability
    Conditions
        (Ability being cast) Equal to Instant Movement 
    Actions
        Set InstantMovementCaster = (Casting unit)
        Set TempLoc = (Position of InstantMovementCaster)
        Set TempLoc2 = (Target point of ability being cast)
        Unit - Create 1 Dummy Instant Movement for (Owner of InstantMovementCaster) at TempLoc facing (Angle from TempLoc to TempLoc2) degrees
        Set InstantMovementDummy = (Last created unit)
        Animation - Play InstantMovementDummy's spell throw animation
        Animation - Change InstantMovementDummy's vertex coloring to (100.00%, 100.00%, 100.00%) with 100.00% transparency
        Custom script:   call RemoveLocation( udg_TempLoc )
        Custom script:   call RemoveLocation( udg_TempLoc2 )
Vì vấn đề animation nên ta phải tạo dummy ngay từ lúc caster bắt đầu cast. Nhưng lúc này phải cho transperency của dummy = 100% (ko nhìn thấy gì) và bắt dummy thực hiện động tác (animation) "spell throw" như caster.
Mã:
InstantMovementBlink
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to Instant Movement 
    Actions
        Set InstantMovementFade = 50.00
        Set InstantMovementBlink = True
        Animation - Change InstantMovementCaster's vertex coloring to (100.00%, 100.00%, 100.00%) with 50.00% transparency
        Animation - Change InstantMovementDummy's vertex coloring to (100.00%, 100.00%, 100.00%) with 50.00% transparency
        Trigger - Turn on InstantMovementTimer <gen>
Start effect, tức là đã caster đã cast xong (bây giờ đã move rồi). Vậy thì hiện dummy ra với 1 nữa transperency và caster cũng phải "mờ" đi 1 nửa. Bậy trigger "mờ" dummy và caster lên. Nhớ rằng biến InstantMovementBlink phải = true (vì đã cast xong)
Mã:
InstantMovementStop
    Events
        Unit - A unit Stops casting an ability
    Conditions
        (Ability being cast) Equal to Instant Movement 
    Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                InstantMovementBlink Equal to False
            Then - Actions
                Unit - Remove InstantMovementDummy from the game
            Else - Actions
stop casting là dừng cast, có thể là cast xong, có thể là bị stun chẳng hạn, nói chung là bị interrupt (gián đoạn :|, "cắt cơn" ấy :'> ) Nếu chưa cast xong thì remove dummy, ko thì thôi.
Mã:
InstantMovementTimer
    Events
        Time - Every 0.01 seconds of game time
    Conditions
    Actions
        Set InstantMovementFade = (InstantMovementFade + 1.00)
        Animation - Change InstantMovementCaster's vertex coloring to (100.00%, 100.00%, 100.00%) with (100.00 - InstantMovementFade)% transparency
        Animation - Change InstantMovementDummy's vertex coloring to (100.00%, 100.00%, 100.00%) with InstantMovementFade% transparency
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                InstantMovementFade Equal to 100.00
            Then - Actions
                Unit - Remove InstantMovementDummy from the game
                Trigger - Turn off (This trigger)
            Else - Actions
Sau khi cast xong thì bật trigger này, cứ 0.01s dummy sẽ mờ đi 1% và caster sẽ hiện rõ hơn 1%.

50 + 1 = 51 -> 100 - 50 = 49 => số này nhỏ dần, caster sẽ hiện ra dần dần

Khi InstantMovementFade = 100 tức là dummy đã mờ hẳn và caster đã hiện ra rõ hẳn.

Đến đây đã xong.

PS: à mà spell này ko MUI nhg tôi nghĩ blink chỉ trong 0.33s nên ko có vấn đề gì to lớn. Mà nếu ko chắc thì có lẽ tôi sẽ nghĩ ra cách làm cho MUI.
---
Hy vọng mọi người hiểu.

Tom đã gửi kèm map demo.

anh ơi...cái trigger đầu..
TempLoc ở đâu ạ..
nếu set..thì cái đó là biến đúng ko
 
anh ơi...cái trigger đầu..
TempLoc ở đâu ạ..
nếu set..thì cái đó là biến đúng ko

Nó là 1 biến. Sau này đừng có quote cả bài khi muốn hỏi 1 đoạn nhỏ, kéo rê rê nhức cả mắt.
 
ai co bit cach lam mot spell nhu chieu cuoi cua con nevermore trong dota nhung phung ra cai khac hok
 
Back
Top