Espeon - cool
Donkey Kong
- 16/1/07
- 314
- 0
Có thể tạo 1 skill fake cleave với 0% damage cleave, cho animation của skill là attack 1
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.

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] --------





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
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)
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)
^ thì chỉnh được cái animation attack 1 đó a
Làm cách đó thì dễ hơn viết trigger![]()
Đâ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
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
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 ??


private constant boolean USE_HASH_TABLE = false
jass helper hiện ra cái trên còn trong library ghi thế này :static if(TimerUtils__USE_HASH_TABLE) then
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

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
+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.