(1 ratings)
//==========================================================================================
//====================================CONFIGURATION=========================================
// The main ability raw code
constant function TL_SpellID takes nothing returns integer
return 'A000'
endfunction
// Length of rewind time per level
constant function TL_Time takes integer level returns real
if level == 1 then
return 6.0 // Level 1
elseif level == 2 then
return 6.0 // Level 2
else
return 6.0 // Level 3
endif
endfunction
// Sfx created at the cast point
constant function TL_CastSfx takes nothing returns string
return "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl"
endfunction
// Sfx created at the target point
constant function TL_TargetSfx takes nothing returns string
return "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTarget.mdl"
endfunction
// How often the Hero's states will be saved
constant function TL_Accuracy takes nothing returns real
return 0.25
endfunction
//=====================================END OF CONFIGURATION=================================
//==========================================================================================
function SaveNode takes nothing returns nothing
local unit u = GetEnumUnit()
local integer dex
local integer node
local integer i
local integer c
local real l
if GetUnitTypeId(u) != 0 then
set l = GetWidgetLife(u)
if l > 0.405 then
set dex = GetHandleId(u)
set node = R2I(TL_Time(LoadInteger(udg_TL_Hashtable, dex, -2)) / TL_Accuracy())
set i = node
loop
call SaveReal(udg_TL_Hashtable, dex, i, LoadReal(udg_TL_Hashtable, dex, i - 1))
call SaveReal(udg_TL_Hashtable, dex, i + node , LoadReal(udg_TL_Hashtable, dex, i + node - 1))
call SaveReal(udg_TL_Hashtable, dex, i + node * 2 , LoadReal(udg_TL_Hashtable, dex, i + node * 2 - 1))
call SaveReal(udg_TL_Hashtable, dex, i + node * 3 , LoadReal(udg_TL_Hashtable, dex, i + node * 3 - 1))
call SaveReal(udg_TL_Hashtable, dex, i + node * 4 , LoadReal(udg_TL_Hashtable, dex, i + node * 4 - 1))
set i = i - 1
exitwhen i == 1
endloop
call SaveReal(udg_TL_Hashtable, dex, 1, l)
call SaveReal(udg_TL_Hashtable, dex, 1 + node, GetUnitState(u, UNIT_STATE_MANA))
call SaveReal(udg_TL_Hashtable, dex, 1 + 2 * node, GetUnitFacing(u))
call SaveReal(udg_TL_Hashtable, dex, 1 + 3 * node, GetUnitX(u))
call SaveReal(udg_TL_Hashtable, dex, 1 + 4 * node, GetUnitY(u))
call SaveInteger(udg_TL_Hashtable, dex, -1, LoadInteger(udg_TL_Hashtable, dex, -1) + 1)
else
call FlushChildHashtable(udg_TL_Hashtable,dex)
call SaveInteger(udg_TL_Hashtable, dex, -1, 0)
endif
else
call GroupRemoveUnit(udg_TL_Group, u)
call FlushChildHashtable(udg_TL_Hashtable,dex)
set c = LoadInteger(udg_TL_Hashtable, -1, 999) - 1
call SaveInteger(udg_TL_Hashtable, -1, 999, c)
if c == 0 then
call PauseTimer(udg_TL_Timer)
endif
endif
set u = null
endfunction
function TL_Loop takes nothing returns nothing
call ForGroup(udg_TL_Group, function SaveNode)
endfunction
function learn takes nothing returns boolean
local integer i
local integer c
local integer lv
local integer ln = GetLearnedSkill()
local unit u
if ln == TL_SpellID() then
set u = GetTriggerUnit()
set lv = GetUnitAbilityLevel(u, ln)
if not IsUnitInGroup(u, udg_TL_Group) then
set i = GetHandleId(u)
set c = LoadInteger(udg_TL_Hashtable, -1, 999) + 1
call SaveInteger(udg_TL_Hashtable, -1, 999, c)
call SaveInteger(udg_TL_Hashtable, i, -1, 0)
call SaveInteger(udg_TL_Hashtable, i, -2, lv)
call GroupAddUnit(udg_TL_Group, u)
if c == 1 then
call TimerStart(udg_TL_Timer, TL_Accuracy(), true, function TL_Loop)
endif
endif
set u = null
endif
return false
endfunction
function cast takes nothing returns boolean
local integer dex
local integer node
local integer total
local unit caster
local real x
local real y
if GetSpellAbilityId() == TL_SpellID() then
set caster = GetTriggerUnit()
if IsUnitInGroup(caster, udg_TL_Group) then
set dex = GetHandleId(caster)
set node = R2I(TL_Time(LoadInteger(udg_TL_Hashtable, dex, -2)) / TL_Accuracy())
set total = LoadInteger(udg_TL_Hashtable, dex, -1)
if total > 0 then
call DestroyEffect(AddSpecialEffect(TL_CastSfx(), GetUnitX(caster), GetUnitY(caster)))
if total >= node then
call SetWidgetLife(caster,LoadReal(udg_TL_Hashtable, dex, node))
call SetUnitState(caster, UNIT_STATE_MANA, LoadReal(udg_TL_Hashtable, dex, 2 * node))
call SetUnitFacing(caster, LoadReal(udg_TL_Hashtable, dex, 3 * node))
set x = LoadReal(udg_TL_Hashtable, dex, 4 * node)
set y = LoadReal(udg_TL_Hashtable, dex, 5 * node)
call SetUnitX(caster, x)
call SetUnitY(caster, y)
else
call SetWidgetLife(caster,LoadReal(udg_TL_Hashtable, dex, total))
call SetUnitState(caster, UNIT_STATE_MANA, LoadReal(udg_TL_Hashtable, dex, total + node))
call SetUnitFacing(caster, LoadReal(udg_TL_Hashtable, dex, total + node * 2))
set x = LoadReal(udg_TL_Hashtable, dex, total + node * 3)
set y = LoadReal(udg_TL_Hashtable, dex, total + node * 4)
call SetUnitX(caster, x)
call SetUnitY(caster, y)
endif
call DestroyEffect(AddSpecialEffect(TL_TargetSfx(), x, y))
call FlushChildHashtable(udg_TL_Hashtable, dex)
call SaveInteger(udg_TL_Hashtable, dex, -1, 0)
else
call IssueImmediateOrder(caster, "stop")
endif
endif
set caster = null
endif
return false
endfunction
function InitTrig_Time_Lapse takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
local integer i = 0
set udg_TL_Hashtable = InitHashtable()
loop
call TriggerRegisterPlayerUnitEvent(t1, Player(i), EVENT_PLAYER_HERO_SKILL, null)
call TriggerRegisterPlayerUnitEvent(t2, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call SaveInteger(udg_TL_Hashtable, -1, 999, 0)
call TriggerAddCondition(t1, Condition(function learn))
call TriggerAddCondition(t2, Condition(function cast))
set t1 = null
set t2 = null
endfunction
function IsUnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_DEAD) and (GetUnitTypeId(u) != 0)
endfunction
function IsUnitAlive takes unit u returns boolean
return GetWidgetLife(u) > 0.405 // and (GetUnitTypeId(u) != 0)
endfunction
// MAGTHERIDON96 SAYS NOOOOOO
udg_TL_Caster[UnitUserData(unit)]
would be better.it's because each hero need to save 1 value per TL_Accuracy, I guess using hashtable the spell will be so much simpler, and I don't like simpleValues like mana, life, facing can easily be stored into real arrays, why do you use strings?
set loc = Location( GetUnitX(caster), GetUnitY(caster) )
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
call AddSpecialEffect(TL_CastSfx(), x, y )
I forgot about that and yes it is possible with a hashtable.it's because each hero need to save 1 value per TL_Accuracy, I guess using hashtable the spell will be so much simpler, and I don't like simple
constant function TL_Time takes integer level returns real
local real array time
set time[1] = 6.0 // rewind time for level 1
set time[2] = 6.0 // rewind time for level 2
set time[3] = 6.0 // rewind time for level 3
return time[level]
endfunction
constant function TL_Time takes integer level returns real
return 6.
endfunction
constant function TL_Time takes integer level returns real
return 6.+level
endfunction
constant function TL_Time takes integer level returns real
if level == 1 then
return 6
elseif level == 2 then
return 8
else
return 14
endif
endfunction
function IsUnitAlive takes unit u returns boolean
if ( GetUnitState(u,UNIT_STATE_LIFE) <= 0.24 ) then
return false
endif
return true
endfunction
constant function TL_IsUnitAlive takes unit u returns boolean
return not IsUnitType(u, UNIT_TYPE_ALIVE) and GetUnitTypeId(u)!=0
endfunction
call TriggerAddAction( t1, function learn )
call TriggerAddAction( t2, function cast )
call TriggerAddCondition( t1, Condition(function learn) )
call TriggerAddCondition( t2, Condition(function cast) )
if ( casted == TL_Ability() ) then
if ( GetSpellAbilityId() == TL_Ability() ) then
->JASS:constant function TL_Time takes integer level returns real local real array time set time[1] = 6.0 // rewind time for level 1 set time[2] = 6.0 // rewind time for level 2 set time[3] = 6.0 // rewind time for level 3 return time[level] endfunction
That can be easily changed like this :JASS:constant function TL_Time takes integer level returns real return 6. endfunction
OrJASS:constant function TL_Time takes integer level returns real return 6.+level endfunction
JASS:constant function TL_Time takes integer level returns real if level == 1 then return 6 elseif level == 2 then return 8 else return 14 endif endfunction
Mine allows user to define it per level
->JASS:function IsUnitAlive takes unit u returns boolean if ( GetUnitState(u,UNIT_STATE_LIFE) <= 0.24 ) then return false endif return true endfunction
JASS:constant function TL_IsUnitAlive takes unit u returns boolean return not IsUnitType(u, UNIT_TYPE_ALIVE) and GetUnitTypeId(u)!=0 endfunction
I have fixed it on the newest version
->JASS:call TriggerAddAction( t1, function learn ) call TriggerAddAction( t2, function cast )
And makes those callback funcs return boolean and return false at the end of these funcs.JASS:call TriggerAddCondition( t1, Condition(function learn) ) call TriggerAddCondition( t2, Condition(function cast) )
okay
Don't use location but real instead.
fixed
if ( casted == TL_Ability() ) then
->
if ( GetSpellAbilityId() == TL_Ability() ) then
local casted = GetSpellAbilityId()
Rhaaa I stopped when I saw that much strings >_<
Why using strings and not real/integer :/ ?
I'll review it again after changing strings to real/integer ^^
it's because each hero need to save 1 value per TL_Accuracy, I guess using hashtable the spell will be so much simpler, and I don't like simpleValues like mana, life, facing can easily be stored into real arrays, why do you use strings?
constant function TL_Time takes integer level returns real
if level == 1 then
return 6
elseif level == 2 then
return 8
else
return 14
endif
endfunction
My way is better because the func is constant so inline.
- The function is a one-liner
- If the function is called by call the function's contents must begin with set or call or be a return of a single function.
- If the inlined function is an assigment (set) it should not assign one of its arguments.
- Every argument must be evaluated once and only once by the function, in the same order as they appear in the arguments list.
- If the function contains function calls, they should all be evaluated after the arguments UNLESS the function is marked as non-state changing, at the moment some very few native functions and also return bug exploiters are considered as non-state changing.
There is also a lot of feedback from Malhorne in the thread, who is also an experienced wc3 coder.
I might be the one moderating your resource, but other opinions are also very valuable.
Then you better code in chinese, if it is so simpleEDIT:
if I change to hashtable, you will say, "the spell is too simple" because, really, using hashtable the spell will be looks just like a sandbox, I mean very heavenly craby patty simple..
Follow these sentences, best adviceKeep your stuff always as simple as possible without losing important features.
Noone ever said needlessly complicated == cool.
local unit caster = GetTriggerUnit()
local real accuracy = TL_Accuracy()
set caster = null
in the if block too.local integer learned = GetLearnedSkill()
local unit u = GetTriggerUnit()
if CountUnitsInGroup(udg_TL_Group) == 0 then
call DestroyTimer(udg_TL_Timer)
endif
TriggerRegisterPlayerUnitEvent
and a loop from 0 to bj_MAX_PLAYER_SLOTS is exactly the same as TriggerRegisterAnyUnitEventBJ
unless you add a specific player filter (no computers, etc...)that's why I order the caster to stop so that if the hashtable is still empty the spell won't be cooldowned.. and finally... thnks for the review and approval!!I think this one --> call IssueImmediateOrder(caster, "stop") is not required, because the channel ability itself interupts the current order.
Unlikely to happen, but if so the ability would go into cooldown while nothing happens.
i think it's not reseting the cooldown.. the hero stopped before the ability cooldowned..
if l > 0.405 then
set dex = GetHandleId(u)
set node = R2I(TL_Time(LoadInteger(udg_TL_Hashtable, dex, -2)) / TL_Accuracy())
set i = node
loop
call SaveReal(udg_TL_Hashtable, dex, i, LoadReal(udg_TL_Hashtable, dex, i - 1))
call SaveReal(udg_TL_Hashtable, dex, i + node , LoadReal(udg_TL_Hashtable, dex, i + node - 1))
call SaveReal(udg_TL_Hashtable, dex, i + node * 2 , LoadReal(udg_TL_Hashtable, dex, i + node * 2 - 1))
call SaveReal(udg_TL_Hashtable, dex, i + node * 3 , LoadReal(udg_TL_Hashtable, dex, i + node * 3 - 1))
call SaveReal(udg_TL_Hashtable, dex, i + node * 4 , LoadReal(udg_TL_Hashtable, dex, i + node * 4 - 1))
set i = i - 1
exitwhen i == 1
endloop
call SaveReal(udg_TL_Hashtable, dex, 1, l)
call SaveReal(udg_TL_Hashtable, dex, 1 + node, GetUnitState(u, UNIT_STATE_MANA))
call SaveReal(udg_TL_Hashtable, dex, 1 + 2 * node, GetUnitFacing(u))
call SaveReal(udg_TL_Hashtable, dex, 1 + 3 * node, GetUnitX(u))
call SaveReal(udg_TL_Hashtable, dex, 1 + 4 * node, GetUnitY(u))
call SaveInteger(udg_TL_Hashtable, dex, -1, LoadInteger(udg_TL_Hashtable, dex, -1) + 1)
else
call FlushChildHashtable(udg_TL_Hashtable,dex)
call SaveInteger(udg_TL_Hashtable, dex, -1, 0)
if total > 0 then
else
call IssueImmediateOrder(caster, "stop")
call IssueImmediateOrderById(caster, 851973)