Topic hỏi đáp (tập 4) về cách làm map

Status
Không mở trả lời sau này.
Có thể tạo 1 skill fake cleave với 0% damage cleave, cho animation của skill là attack 1
 
^Không khả quan, nó choáng mất một ô, nêu làm như cách bạn trên thì nên báe từ skill lightning attack của viên ngọc sét ấy mà chỉnh lại các thông số về không hết, vì chiêu này ko có icon nên cũng dễ ;))
 
ngọc sét để làm gì ?
---
cách giải quyêt mà không edit model là:

Mã:
Blademaster Attack
    Events
        Unit - A unit Is attacked
    Conditions
        (Unit-type of (Attacking unit)) Equal to Blademaster
    Actions
        --------  play animation index của [B](Attacking unit)[/B] --------
play animation index thế nào thì xem: Bật Animation một cách chính xác
 
Chỉnh sửa cuối:
^ cái skill của ngoc sét hình như chỉnh được mà a ;))
Skill đó ko có icon :D
 
chỉnh được cái gì ?

"hình như" một câu nữa là 3pts spam :)>-
 
^ thì chỉnh được cái animation attack 1 đó a ;))
Làm cách đó thì dễ hơn viết trigger :D
 
Đây là Fake miss của anh Tom nhưng mình thay cái ABCT = cái Key Timer. Đây là 1 skill khi cast thì add buff vào, hero có buff này thì bị đánh không mất máu. Lỗi ở đây là khi hero có buff thì phát đầu tiên bị đánh sẽ làm nó giảm máu xuống hơn 1 nữa. Ai rành kiểm tra giùm

Key Timers 2 System:

Mã:
scope DamageRestoring
    globals
        private integer LifeBonusId = 'A000'
    endglobals
    private struct data
        unit u
        real percent
    endstruct

    private function RestoreE takes nothing returns boolean
        local data d = KT_GetData()
        call UnitRemoveAbility(d.u, LifeBonusId)
        call SetUnitState( d.u,UNIT_STATE_LIFE, GetUnitState(d.u,UNIT_STATE_MAX_LIFE)*d.percent )
        call data.destroy(d)
        return true
    endfunction
    
    function RestoreDamage takes unit u, real damagetaken, real restoreamount returns nothing
        local real maxlife = GetUnitState(u,UNIT_STATE_MAX_LIFE)
        local real curlife = GetUnitState(u,UNIT_STATE_LIFE)
        local data d
        if curlife - (damagetaken - restoreamount) <= 0 then
        //the restore amount can't help this unit to survive, it will die so doesn't need to do anything anymore
            return
        endif
        if maxlife - curlife >= restoreamount then
            call SetUnitState( u,UNIT_STATE_LIFE,curlife + restoreamount )
            return
        endif
        set d = data.create()
        set d.u = u
        set d.percent = ( curlife - (damagetaken - restoreamount) ) / maxlife
        call UnitAddAbility( u , LifeBonusId )
        call SetUnitState( u,UNIT_STATE_LIFE, maxlife )
    endfunction
endscope

Kế tiếp là 2 trigger add unit vao TakeDamGroup giống của anh Tom (2 cái đó ngắn chắc không có gì)
Mã:
Event:
   Time - Elapsed game time is 0.00 seconds
Conditions:
Actions:
   Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
    Loop - Actions
        Unit Group - Add (Picked unit) to TakeDamageGroup
        Trigger - Add to TakeDamage <gen> the event (Unit - (Picked unit) Takes damage)

Mã:
TakeDamage
    Events
    Conditions
    Actions
        Trigger - Turn off (This trigger)
        -------- Action --------
        Set TempUnit1 = (Triggering unit)
        Set TempLoc1 = (Position of TempUnit1)
        Set TempUnit2 = (Damage source)
        Set TempLoc2 = (Position of TempUnit2)
        Set Angle = (Angle from TempLoc1 to TempLoc2)
        Set Damage = (Damage taken)
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                (TempUnit1 has buff Iron Skin ) Equal to True
            Then - Actions
                Custom script:   call RestoreDamage( udg_TempUnit1 , udg_Damage, udg_Damage )
                Special Effect - Create a special effect at (TempLoc1 offset by 100.00 towards Angle degrees) using Abilities\Spells\Human\Defend\DefendCaster.mdl
                Special Effect - Destroy (Last created special effect)
            Else - Actions
        -------- End --------
        Custom script:   call RemoveLocation (udg_TempLoc1)
        Custom script:   call RemoveLocation (udg_TempLoc2)
        Trigger - Turn on (This trigger)

P/s: Cái newgen mỗi lần muốn test là phải save map lại trước àh ??
 
^ thì chỉnh được cái animation attack 1 đó a ;))
Làm cách đó thì dễ hơn viết trigger :D

chỉnh thử đi, up map demo lên xem nào

Đây là Fake miss của anh Tom nhưng mình thay cái ABCT = cái Key Timer. Đây là 1 skill khi cast thì add buff vào, hero có buff này thì bị đánh không mất máu. Lỗi ở đây là khi hero có buff thì phát đầu tiên bị đánh sẽ làm nó giảm máu xuống hơn 1 nữa. Ai rành kiểm tra giùm

dùng KeyTimer làm gì, dùng TimerUtils ấy.

[spoil]
Mã:
library TimerUtils initializer init
//*********************************************************************
//* TimerUtils (red+blue+orange flavors for 1.24b+)
//* ----------
//*
//*  To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//*  To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass)   More scripts: htt://www.wc3c.net
//*
//* For your timer needs:
//*  * Attaching
//*  * Recycling (with double-free protection)
//*
//* set t=NewTimer()      : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t)       : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2)     : Attach value 2 to timer
//* GetTimerData(t)       : Get the timer's value.
//*                         You can assume a timer's value is 0
//*                         after NewTimer.
//*
//* Multi-flavor:
//*    Set USE_HASH_TABLE to true if you don't want to complicate your life.
//*
//* If you like speed and giberish try learning about the other flavors.
//*
//********************************************************************

//================================================================
    globals
        //How to tweak timer utils:
        // USE_HASH_TABLE = true  (new blue)
        //  * SAFEST
        //  * SLOWEST (though hash tables are kind of fast)
        //
        // USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = true  (orange)
        //  * kinda safe (except there is a limit in the number of timers)
        //  * ALMOST FAST
        //
        // USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = false (red)
        //  * THE FASTEST (though is only  faster than the previous method
        //                  after using the optimizer on the map)
        //  * THE LEAST SAFE ( you may have to tweak OFSSET manually for it to
        //                     work)
        //
        private constant boolean USE_HASH_TABLE      = false
        private constant boolean USE_FLEXIBLE_OFFSET = false

        private constant integer OFFSET     = 0x100000
        private          integer VOFFSET    = OFFSET
              
        //Timers to preload at map init:
        private constant integer QUANTITY   = 256
        
        //Changing this  to something big will allow you to keep recycling
        // timers even when there are already AN INCREDIBLE AMOUNT of timers in
        // the stack. But it will make things far slower so that's probably a bad idea...
        private constant integer ARRAY_SIZE = 8190

    endglobals

    //==================================================================================================
    globals
        private integer array data[ARRAY_SIZE]
        private hashtable     ht
    endglobals

    //It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
    function SetTimerData takes timer t, integer value returns nothing
        static if(USE_HASH_TABLE) then
            // new blue
            call SaveInteger(ht,0,GetHandleId(t), value)
            
        elseif (USE_FLEXIBLE_OFFSET) then
            // orange
            static if (DEBUG_MODE) then
                if(GetHandleId(t)-VOFFSET<0) then
                    call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
                endif
            endif
            set data[GetHandleId(t)-VOFFSET]=value
        else
            // new red
            static if (DEBUG_MODE) then
                if(GetHandleId(t)-OFFSET<0) then
                    call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
                endif
            endif
            set data[GetHandleId(t)-OFFSET]=value
        endif        
    endfunction

    function GetTimerData takes timer t returns integer
        static if(USE_HASH_TABLE) then
            // new blue
            return LoadInteger(ht,0,GetHandleId(t) )
            
        elseif (USE_FLEXIBLE_OFFSET) then
            // orange
            static if (DEBUG_MODE) then
                if(GetHandleId(t)-VOFFSET<0) then
                    call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
                endif
            endif
            return data[GetHandleId(t)-VOFFSET]
        else
            // new red
            static if (DEBUG_MODE) then
                if(GetHandleId(t)-OFFSET<0) then
                    call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
                endif
            endif
            return data[GetHandleId(t)-OFFSET]
        endif        
    endfunction

    //==========================================================================================
    globals
        private timer array tT[ARRAY_SIZE]
        private integer tN = 0
        private constant integer HELD=0x28829022
        //use a totally random number here, the more improbable someone uses it, the better.
    endglobals

    //==========================================================================================
    function NewTimer takes nothing returns timer
        if (tN==0) then
            //If this happens then the QUANTITY rule has already been broken, try to fix the
            // issue, else fail.
            debug call BJDebugMsg("NewTimer: Warning, Exceeding TimerUtils_QUANTITY, make sure all timers are getting recycled correctly")
            static if( not USE_HASH_TABLE) then
                debug call BJDebugMsg("In case of errors, please increase it accordingly, or set TimerUtils_USE_HASH_TABLE to true")
                set tT[0]=CreateTimer()
                static if( USE_FLEXIBLE_OFFSET) then
                    if (GetHandleId(tT[0])-VOFFSET<0) or (GetHandleId(tT[0])-VOFFSET>=ARRAY_SIZE) then
                        //all right, couldn't fix it
                        call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
                        return null
                    endif
                else
                    if (GetHandleId(tT[0])-OFFSET<0) or (GetHandleId(tT[0])-OFFSET>=ARRAY_SIZE) then
                        //all right, couldn't fix it
                        call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
                        return null
                    endif
                endif
            endif
        else
            set tN=tN-1
        endif
        call SetTimerData(tT[tN],0)
     return tT[tN]
    endfunction

    //==========================================================================================
    function ReleaseTimer takes timer t returns nothing
        if(t==null) then
            debug call BJDebugMsg("Warning: attempt to release a null timer")
            return
        endif
        if (tN==ARRAY_SIZE) then
            debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")

            //stack is full, the map already has much more troubles than the chance of bug
            call DestroyTimer(t)
        else
            call PauseTimer(t)
            if(GetTimerData(t)==HELD) then
                debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
                return
            endif
            call SetTimerData(t,HELD)
            set tT[tN]=t
            set tN=tN+1
        endif    
    endfunction

    private function init takes nothing returns nothing
     local integer i=0
     local integer o=-1
     local boolean oops = false
     
        static if( USE_HASH_TABLE ) then
            set ht = InitHashtable()
            loop
                exitwhen(i==QUANTITY)
                set tT[i]=CreateTimer()
                call SetTimerData(tT[i], HELD)
                set i=i+1
            endloop
            set tN = QUANTITY
        else
            loop
                set i=0
                loop
                    exitwhen (i==QUANTITY)
                    set tT[i] = CreateTimer()
                    if(i==0) then
                        set VOFFSET = GetHandleId(tT[i])
                        static if(USE_FLEXIBLE_OFFSET) then
                            set o=VOFFSET
                        else
                            set o=OFFSET
                        endif
                    endif
                    if (GetHandleId(tT[i])-o>=ARRAY_SIZE) then
                        exitwhen true
                    endif
                    if (GetHandleId(tT[i])-o>=0)  then
                        set i=i+1
                    endif
                endloop
                set tN = i
                exitwhen(tN == QUANTITY)
                set oops = true
                exitwhen not USE_FLEXIBLE_OFFSET
                debug call BJDebugMsg("TimerUtils_init: Failed a initialization attempt, will try again")               
            endloop
            
            if(oops) then
                static if ( USE_FLEXIBLE_OFFSET) then
                    debug call BJDebugMsg("The problem has been fixed.")
                    //If this message doesn't appear then there is so much
                    //handle id fragmentation that it was impossible to preload
                    //so many timers and the thread crashed! Therefore this
                    //debug message is useful.
                elseif(DEBUG_MODE) then
                    call BJDebugMsg("There were problems and the new timer limit is "+I2S(i))
                    call BJDebugMsg("This is a rare ocurrence, if the timer limit is too low:")
                    call BJDebugMsg("a) Change USE_FLEXIBLE_OFFSET to true (reduces performance a little)")
                    call BJDebugMsg("b) or try changing OFFSET to "+I2S(VOFFSET) )
                endif
            endif
        endif

    endfunction

endlibrary
[/spoil]

Mã:
scope DamageRestoring
    globals
        private integer LifeBonusId = 'A000'
    endglobals
    private struct data
        unit u
        real percent
        [B]timer ti[/B]
    endstruct

    private function RestoreE takes nothing returns boolean
        [B]local data d = GetTimerData( GetExpiredTimer() )[/B]
        call UnitRemoveAbility(d.u, LifeBonusId)
        call SetUnitState( d.u,UNIT_STATE_LIFE, GetUnitState(d.u,UNIT_STATE_MAX_LIFE)*d.percent )
        [B]call ReleaseTimer(d.ti)[/B]
        call data.destroy(d)
        return true
    endfunction
    
    function RestoreDamage takes unit u, real damagetaken, real restoreamount returns nothing
        local real maxlife = GetUnitState(u,UNIT_STATE_MAX_LIFE)
        local real curlife = GetUnitState(u,UNIT_STATE_LIFE)
        local data d
        if curlife - (damagetaken - restoreamount) <= 0 then
        //the restore amount can't help this unit to survive, it will die so doesn't need to do anything anymore
            return
        endif
        if maxlife - curlife >= restoreamount then
            call SetUnitState( u,UNIT_STATE_LIFE,curlife + restoreamount )
            return
        endif
        set d = data.create()
        set d.u = u
        set d.percent = ( curlife - (damagetaken - restoreamount) ) / maxlife
        call UnitAddAbility( u , LifeBonusId )
        call SetUnitState( u,UNIT_STATE_LIFE, maxlife )
        [B]set d.ti = NewTimer()
        call SetTimerData( d.ti, d )
        call TimerStart( d.ti, 0.00, false, function RestoreE )[/B]
    endfunction
endscope

---
P/s: Cái newgen mỗi lần muốn test là phải save map lại trước àh ??

thế WE bình thường không save map mà vẫn test được à?
 
Chỉnh sửa cuối:
^ vừa test đúng là không chỉnh được, srr mọi người vì nói bậy ;))
Có ai có cái minion sytem không cho em xin với :((
 
@anh Tom: cái TimerUtils khi save lại báo lỗi
Line 2529: private outside library/scope definition
private constant boolean USE_HASH_TABLE = false
 
copy thiếu: library TimerUtils initializer init hả ?
 
Sữa đc lỗi trên lại thêm 1 lỗi nữa chắc anh Tom phải cho em nick Y!M mới đc, kiểu này giống spam quá :(
Line 787: Syntax error
static if(TimerUtils__USE_HASH_TABLE) then
jass helper hiện ra cái trên còn trong library ghi thế này :
static if(USE_HASH_TABLE) then
 
Cho minh` hoi xoa' leak sao vay^. Dung` call... gi` gi` chi minh` voi. Lam` trigger khong biet xoa leak
 
Ai đó làm giúp mình demo spell Shallow Grave của Dazzle không :-/
 
Dùng cái JassNewGen + Fake miss Tom post ở trên.
 
Ai chỉ giúp lại cái spell này :
Cho hỏi cách làm Skill (tạm gọi là A) thế này:
+ khi học skill A sẽ đc thêm 1 skill phụ tên B.
+ Mỗi lần cast skill A sẽ đc 1 missile (giống như là đạn, khi cast A thì đc nạp 1 đạn) đến X viên thì thôi (ví dụ max 5 viên cast tiếp cũng chỉ đc 5 viên)
+ Skill phụ B là bắn đạn ra.
Thanks

Đây là hướng dẫn của Luci
+Học a có b -->event unit learn a skill,điều kiện skill là a,add ability b cho a,đơn giản vậy mà.
+Thêm missile->Tạo hashtable,set SoDan = 0->8192 gì đấy thì tùy,vd 0
Event :start effect skill -->
ĐK : skill là A
Act: set temp_int = LoadIntegerBJ(udg_SoDan,GetHandleId(GetTriggerUnit()),udg_HashTable)
if temp_int<5->SaveIntegerBJ(udg_Temp_int +1,udg_SoDan,GetHandleId(GetTriggerUnit()),udg_HashTable)

Cast->Set temp_int = LoadIntegerBJ(udg_SoDan,GetHandleId(GetTriggerUnit()),udg_HashTable)
Loop-->cast,mỗi lần loop thì save -1 đi cho đến khi temp_int = 0.

Cái hướng dẫn này xài hastable nên hơi khó hiểu ai rành cái này thì hướng dẫn cụ thể hơn chút. Thanks
 
các anh ơi cho em hỏi là làm thế nào để lấy được model từ 1 map nào đó. Em có nhìu map spell mà không biết cách lấy model.
 
Mở map ra. Vào f12 mà lấy
mở mdxpather xem các blp liên quan là xong
 
Last edited by a moderator:
Status
Không mở trả lời sau này.
Back
Top