• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Ice Temple

  • Like
Reactions: Blood Raven
I made this spell some times ago.
I guess it's a pain in the *ss to import it in a real map since it's quiet dependant on the caster's model and animations but who knows. It only requires the JNGP.

The models are from me. I don't know if I should post it in the model section (I don't see how you could use it other than with this spell).

I don't want to go back on updating this thing. Consider I'll be extremely lazy about it.

Free to use or edit anything. Give credits.

JASS:
scope IceTemple initializer Init
// requires optional StunSystem :
// http://www.hiveworkshop.com/forums/jass-resources-412/system-stun-196749/

// This spell assume that the ability "Raven form" ('Amrf') and
// the destructable "Large pathing blocker both" ('YTfc') are not modified too much.
// It may be asynchronous as far as GetLocationZ is.
// However, a slight difference will unlikely trigger a real problem.

// HOW TO IMPORT :
// 1) Download the test map.
// 2) Copy/paste this scope in your map.
// 3) Export/import the 2 models "war3mapImported\IceDrop.mdx" and "war3mapImported\IceTemple.mdx" from the test map.
// 4) You can also get the icons.
// 6) Copy/paste the units "Drop" and "Ice Temple".
// 7) You can also get the "Dummy" unit and the abilities "Ice Temple" and "Frost Nova (Dummy - Ice Temple)". If you don't, make custom abilities to replace them.
// 8) Look the obtained spells and units IDs and configure the scope.

globals

    private location LOCZ     = Location (0,0)
    private group LOCALGROUP  = CreateGroup()
    private hashtable THEHASH

    sound SubmergeSound

    private real array FrozenDamages     // Over-time damages when frozen
    private real array ExtraDuration     // Time spent to freeze units
    private real array FreezeTimeout     // Delay between 2 freezing
    private real array SpellRadius       // Spell's base radius

endglobals

//=====================================//
//                                     //
//         CONFIGURATION BLOC          //
//                                     //
//=====================================//

globals

    private constant integer SPELL_ID           = 'A000'      // The castable spell
    private constant integer NOVA_ID            = 'A001'      // A Frost Nova (or any other unit-targeting spell) for dummy, dealing the ending damages ; it should have as many levels as the main spell
    private constant integer DUMMY_TEMPLE_ID    = 'n000'      // The Id of the Temple dummy
    private constant integer DUMMY_ID           = 'n001'      // A dummy Id for casting Frost Novas
    private constant integer DUMMY_DROP_ID      = 'n002'      // The Id of the Drop dummy
    private constant string NOVA_ORDER          = "frostnova" // Adapt this field to the NOVA_ID spell.

    private constant boolean MOVE_CASTER        = true        // Set it to false if you don't want the caster to be involved in the spell.
    // If MOVE_CASTER is false, the following 3 globals are unused.
    private constant string CASTER_ANIM_CAST    = "stand victory"
    private constant string CASTER_ANIM_CHANNEL = "spell"
    private constant string CASTER_ANIM_JUMP    = "attack"

    // Those 4 globals shouldn't be modified in most cases.
    private constant real TIMEOUT               = 0.04   // A timeout value for fast periodic timers.
    private constant real MAXHEIGHT             = 175    // The height doesn't depend on the model's scale
    private constant real MODELSCALEFACTOR      = 1.18   // ModelScale = SpellRadius * MODELSCALEFACTOR / 450
    private constant real NOVARADIUSFACTOR      = 1.3    // NovaRadius = SpellRadius * NOVARADIUSFACTOR

endglobals

private function SetupDatas takes nothing returns nothing
    // You can use a custom hashtable here instead of creating a new one.
    // The spell only uses timers' Ids as parent keys.
    set THEHASH = InitHashtable()

    // Set up the datas per level.
    // Final damage (and slow) are supposed to be in the "NOVA_ID" spell.
    set FrozenDamages[1] = TIMEOUT * 20
    set ExtraDuration[1] = 1.5
    set FreezeTimeout[1] = 0.25
    set SpellRadius[1] = 300 // The model looks bad if spell radius is too far from 380.

    set FrozenDamages[2] = TIMEOUT * 25
    set ExtraDuration[2] = 2.5
    set FreezeTimeout[2] = 0.25
    set SpellRadius[2] = 380

    set FrozenDamages[3] = TIMEOUT * 30
    set ExtraDuration[3] = 3
    set FreezeTimeout[3] = 0.25
    set SpellRadius[3] = 460
endfunction

// Additional filters for targetable units. The spell also checks if :
// - the target is alive,
// - the target's height is lower than the spell's height,
// - the target hasn't already been trapped or hit by a Frost Nova.
private function TrapFilter takes unit caster, unit target returns boolean
    return IsUnitEnemy(target,GetOwningPlayer(caster)) /*
        */ and not(IsUnitType(target,UNIT_TYPE_STRUCTURE)) /*
        */ and not(IsUnitType(target,UNIT_TYPE_MAGIC_IMMUNE))
endfunction

private function EndingNovaFilter takes unit caster, unit target returns boolean
    return IsUnitEnemy(target,GetOwningPlayer(caster)) /*
        */ and not(IsUnitType(target,UNIT_TYPE_STRUCTURE)) /*
        */ and not(IsUnitType(target,UNIT_TYPE_MAGIC_IMMUNE))
endfunction

//=====================================//
//                                     //
//     END OF CONFIGURATION BLOC       //
//                                     //
//=====================================//

// You can make this function public.
private function GetPointZ takes real x, real y returns real
    call MoveLocation(LOCZ,x,y)
    return GetLocationZ(LOCZ)
endfunction

private function RemoveUnitAfterWaitCallback takes nothing returns nothing
    local timer t=GetExpiredTimer()
    call RemoveUnit(LoadUnitHandle(THEHASH,GetHandleId(t),0))
    call FlushChildHashtable(THEHASH,GetHandleId(t))
    call DestroyTimer(t)
    set t=null
endfunction

// You can make this function public.
private function RemoveUnitAfterWait takes unit whichUnit, real wait returns nothing
    local timer t=CreateTimer()
    call SaveUnitHandle(THEHASH,GetHandleId(t),0,whichUnit)
    call TimerStart(t,wait,false,function RemoveUnitAfterWaitCallback)
    set t=null
endfunction

private function PauseUnitSafeCallback takes nothing returns nothing
    local timer t=GetExpiredTimer()
    local unit u=LoadUnitHandle(THEHASH,GetHandleId(t),0)
    static if LIBRARY_StunSystem then
        call Stun.apply(u,9999,false)
    else
        call PauseUnit(u,true)
    endif
    call SetUnitX(u,LoadReal(THEHASH,GetHandleId(t),1))
    call SetUnitY(u,LoadReal(THEHASH,GetHandleId(t),2))
    call SetUnitAnimation(u,CASTER_ANIM_CAST)
    call QueueUnitAnimation(u,CASTER_ANIM_CAST)
    call FlushChildHashtable(THEHASH,GetHandleId(t))
    call DestroyTimer(t)
    set t=null
    set u=null
endfunction

private function PauseUnitSafe takes unit whichUnit returns nothing
    local timer t=CreateTimer()
    call SaveUnitHandle(THEHASH,GetHandleId(t),0,whichUnit)
    call SaveReal(THEHASH,GetHandleId(t),1,GetUnitX(whichUnit))
    call SaveReal(THEHASH,GetHandleId(t),2,GetUnitY(whichUnit))
    call TimerStart(t,0,false,function PauseUnitSafeCallback)
    set t=null
endfunction

private function ClearMainDatas takes timer t returns nothing
    local integer Id=GetHandleId(t)
    call RemoveUnitAfterWait(LoadUnitHandle(THEHASH,Id,2),2)
    call DestroyGroup(LoadGroupHandle(THEHASH,Id,5))
    call DestroyGroup(LoadGroupHandle(THEHASH,Id,6))
    call RemoveDestructable(LoadDestructableHandle(THEHASH,Id,10))
    call RemoveDestructable(LoadDestructableHandle(THEHASH,Id,11))
    call RemoveDestructable(LoadDestructableHandle(THEHASH,Id,12))
    call RemoveDestructable(LoadDestructableHandle(THEHASH,Id,13))
    call FlushChildHashtable(THEHASH,Id)
    call DestroyTimer(t)
endfunction

private function FinalDamagesEnum takes unit caster,group targets returns nothing
    local integer Id=GetHandleId(GetExpiredTimer())
    local unit dummy
    local unit u
    local timer t
    loop
        set u=FirstOfGroup(targets)
        exitwhen u==null
        call GroupRemoveUnit(targets,u)
        if IsUnitInGroup(u,LoadGroupHandle(THEHASH,Id,5)) then
            set t=LoadTimerHandle(THEHASH,Id,GetHandleId(u))
            static if LIBRARY_StunSystem then
                call Stun.stop(u)
            else
                call PauseUnit(u,false)
            endif
            call SetUnitTimeScale(u,1)
            call GroupRemoveUnit(LoadGroupHandle(THEHASH,Id,5),u)
            call RemoveUnit(LoadUnitHandle(THEHASH,GetHandleId(t),2))
            call DestroyEffect(LoadEffectHandle(THEHASH,GetHandleId(t),4))
            call FlushChildHashtable(THEHASH,GetHandleId(t))
            call DestroyTimer(t)
            set t=null
        endif
        if not IsUnitInGroup(u,LoadGroupHandle(THEHASH,Id,6)) and GetWidgetLife(u)>0.405 and GetPointZ(GetUnitX(u),GetUnitY(u))+GetUnitFlyHeight(u)<=LoadReal(THEHASH,Id,3)+MAXHEIGHT and EndingNovaFilter(caster,u) then
            set dummy=CreateUnit(GetOwningPlayer(caster),DUMMY_ID,GetUnitX(u),GetUnitY(u),0)
            call UnitAddAbility(dummy,NOVA_ID)
            call SetUnitAbilityLevel(dummy,NOVA_ID,LoadInteger(THEHASH,Id,1))
            call IssueTargetOrder(dummy,NOVA_ORDER,u)
            call RemoveUnitAfterWait(dummy,1)
            call GroupAddUnit(LoadGroupHandle(THEHASH,Id,6),u)
        endif
    endloop
    set dummy=null
endfunction

private function FinalDamages takes nothing returns nothing
    local integer Id=GetHandleId(GetExpiredTimer())
    local real timeleft=LoadReal(THEHASH,Id,4)-TIMEOUT
    local unit caster
    local unit u
    call SaveReal(THEHASH,Id,4,timeleft)
    call GroupEnumUnitsInRange(LOCALGROUP,GetUnitX(LoadUnitHandle(THEHASH,Id,2)),GetUnitY(LoadUnitHandle(THEHASH,Id,2)),(1-timeleft/1.4)*SpellRadius[LoadInteger(THEHASH,Id,1)]*NOVARADIUSFACTOR,null)
    call FinalDamagesEnum(LoadUnitHandle(THEHASH,Id,0),LOCALGROUP)
    if timeleft<=0 then
        call FinalDamagesEnum(LoadUnitHandle(THEHASH,Id,0),LoadGroupHandle(THEHASH,Id,5))
        call ClearMainDatas(GetExpiredTimer())
    endif
endfunction

private function FinalMove takes nothing returns nothing
    local integer Id=GetHandleId(GetExpiredTimer())
    local unit caster=LoadUnitHandle(THEHASH,Id,0)
    local real x=GetUnitX(caster)
    local real y=GetUnitY(caster)
    local real facing=GetUnitFacing(caster)*bj_DEGTORAD
    local real speedfactor=SpellRadius[LoadInteger(THEHASH,Id,1)]*MODELSCALEFACTOR/450
    local real timeleft=LoadReal(THEHASH,Id,4)-TIMEOUT
    call SaveReal(THEHASH,Id,4,timeleft)
    static if not MOVE_CASTER then
        if timeleft>=2 then
            call SaveReal(THEHASH,Id,4,-1)
            call TimerStart(GetExpiredTimer(),1.44,false,function FinalMove)
            return
        else
            call SaveReal(THEHASH,Id,4,1.4)
            call SaveGroupHandle(THEHASH,Id,6,CreateGroup())
            call TimerStart(GetExpiredTimer(),TIMEOUT,true,function FinalDamages)
        endif
        return
    else
        if timeleft>=0.78 then
            if timeleft>=2 then
                call SaveReal(THEHASH,Id,4,1.04)
                call TimerStart(GetExpiredTimer(),TIMEOUT,true,function FinalMove)
                return
            endif
            call SetUnitX(caster,x+770*speedfactor*TIMEOUT*Cos(facing))
            call SetUnitY(caster,y+770*speedfactor*TIMEOUT*Sin(facing))
            call SetUnitFlyHeight(caster,280+LoadReal(THEHASH,Id,3)-GetPointZ(x,y)+(1.04-timeleft)*231*speedfactor,0)
        elseif timeleft>=0.52 then
            call SetUnitTimeScale(caster,1)
            call SetUnitX(caster,x+461*speedfactor*TIMEOUT*Cos(facing))
            call SetUnitY(caster,y+461*speedfactor*TIMEOUT*Sin(facing))
            call SetUnitFlyHeight(caster,280+LoadReal(THEHASH,Id,3)-GetPointZ(x,y)+(240-timeleft*231)*speedfactor,0)
        elseif timeleft>=0.26 then
            call SetUnitX(caster,x+309*speedfactor*TIMEOUT*Cos(facing))
            call SetUnitY(caster,y+309*speedfactor*TIMEOUT*Sin(facing))
            call SetUnitFlyHeight(caster,280+LoadReal(THEHASH,Id,3)-GetPointZ(x,y)+(timeleft*77+80)*speedfactor,0)
        elseif timeleft>=0 then
            call SetUnitX(caster,x+193*speedfactor*TIMEOUT*Cos(facing))
            call SetUnitY(caster,y+193*speedfactor*TIMEOUT*Sin(facing))
            call SetUnitFlyHeight(caster,280+LoadReal(THEHASH,Id,3)-GetPointZ(x,y)+(timeleft*461-20)*speedfactor,0)
        elseif timeleft>-0.4 then
            call SetUnitFlyHeight(caster,280+LoadReal(THEHASH,Id,3)-GetPointZ(x,y)+timeleft*650,0)
        else
            call SetUnitFlyHeight(caster,0,0)
            static if LIBRARY_StunSystem then
                call Stun.stop(caster)
            else
                call PauseUnit(caster,false)
            endif
            call SetUnitInvulnerable(caster,false)
            call SetUnitPosition(caster,x,y)
            call SaveReal(THEHASH,Id,4,1.4)
            call SaveGroupHandle(THEHASH,Id,6,CreateGroup())
            call TimerStart(GetExpiredTimer(),TIMEOUT,true,function FinalDamages)
        endif
    endif
    set caster=null
endfunction

private function StartFinal takes nothing returns nothing
    local integer Id=GetHandleId(GetExpiredTimer())
    local unit caster=LoadUnitHandle(THEHASH,Id,0)
    static if MOVE_CASTER then
        call SetUnitAnimation(caster,CASTER_ANIM_JUMP)
        call QueueUnitAnimation(caster,"stand")
        call SetUnitTimeScale(caster,0.5)
    endif
    call SetUnitAnimation(LoadUnitHandle(THEHASH,Id,2),"death")
    call FlushChildHashtable(THEHASH,GetHandleId(LoadTimerHandle(THEHASH,Id,6)))
    call DestroyTimer(LoadTimerHandle(THEHASH,Id,6))
    call SaveReal(THEHASH,Id,4,3)
    call TimerStart(GetExpiredTimer(),1.26,false,function FinalMove)
endfunction

private function TrapUnitLoop takes nothing returns nothing
    local integer Id=GetHandleId(GetExpiredTimer())
    local integer Idm=LoadInteger(THEHASH,Id,0)
    local unit target=LoadUnitHandle(THEHASH,Id,1)
    local real x
    local real y
    if LoadBoolean(THEHASH,Id,3) then
        set x=GetUnitX(LoadUnitHandle(THEHASH,Id,2))-GetUnitX(target)
        set y=GetUnitY(LoadUnitHandle(THEHASH,Id,2))-GetUnitY(target)
        // If the unit flees to far or go in transport, we cancel the freeze.
        if x*x+y*y<=90000 and not IsUnitHidden(target) then
            call SaveBoolean(THEHASH,Id,3,false)
            static if LIBRARY_StunSystem then
                call Stun.apply(target,9999,false)
            else
                call PauseUnit(target,true)
            endif
            call SetUnitTimeScale(target,0)
            call TimerStart(GetExpiredTimer(),TIMEOUT,true,function TrapUnitLoop)
        else
            call DestroyEffect(LoadEffectHandle(THEHASH,Id,4))
            call RemoveUnit(LoadUnitHandle(THEHASH,Id,2))
            call GroupRemoveUnit(LoadGroupHandle(THEHASH,Idm,5),target)
            call FlushChildHashtable(THEHASH,Id)
            call DestroyTimer(GetExpiredTimer())
        endif
    elseif GetWidgetLife(target)>FrozenDamages[LoadInteger(THEHASH,Idm,1)]*2 then
        call UnitDamageTarget(LoadUnitHandle(THEHASH,Idm,0),target,FrozenDamages[LoadInteger(THEHASH,Idm,1)],true,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_UNIVERSAL,WEAPON_TYPE_WHOKNOWS)
    endif
    set target=null
endfunction

private function TrapUnit2 takes nothing returns nothing
    call SaveEffectHandle(THEHASH,GetHandleId(GetExpiredTimer()),4,AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdx",LoadUnitHandle(THEHASH,GetHandleId(GetExpiredTimer()),1),"origin"))
    call TimerStart(GetExpiredTimer(),0.3,false,function TrapUnitLoop)
endfunction

private function TrapUnit takes nothing returns nothing
    local integer Id=LoadInteger(THEHASH,GetHandleId(GetExpiredTimer()),0)
    local group g=LoadGroupHandle(THEHASH,Id,5)
    local real x
    local real y
    local unit target
    local unit drop
    local timer t
    call GroupEnumUnitsInRange(LOCALGROUP,GetUnitX(LoadUnitHandle(THEHASH,Id,2)),GetUnitY(LoadUnitHandle(THEHASH,Id,2)),SpellRadius[LoadInteger(THEHASH,Id,1)],null)
    loop
        set target=FirstOfGroup(LOCALGROUP)
        exitwhen target==null or (not IsUnitInGroup(target,g) and GetWidgetLife(target)>0.405 and GetPointZ(GetUnitX(target),GetUnitY(target))+GetUnitFlyHeight(target)<=LoadReal(THEHASH,Id,3)+MAXHEIGHT and TrapFilter(LoadUnitHandle(THEHASH,Id,0),target))
        call GroupRemoveUnit(LOCALGROUP,target)
    endloop
    call GroupClear(LOCALGROUP)
    if target!=null then
        set x=GetUnitX(target)
        set y=GetUnitY(target)
        call GroupAddUnit(g,target)
        call SetSoundPosition(SubmergeSound,x,y,200)
        call StartSound(SubmergeSound)
        set drop=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_DROP_ID,x,y,0)
        call UnitAddAbility(drop,'Amrf')
        call UnitRemoveAbility(drop,'Amrf')
        call SetUnitX(drop,x)
        call SetUnitY(drop,y)
        call SetUnitFlyHeight(drop,LoadReal(THEHASH,Id,3)-GetPointZ(x,y),0)
        call SetUnitAnimation(drop,"death")
        set t=CreateTimer()
        call SaveInteger(THEHASH,GetHandleId(t),0,Id)
        call SaveUnitHandle(THEHASH,GetHandleId(t),1,target)
        call SaveUnitHandle(THEHASH,GetHandleId(t),2,drop)
        call SaveBoolean(THEHASH,GetHandleId(t),3,true)
        call SaveTimerHandle(THEHASH,Id,GetHandleId(target),t)
        call TimerStart(t,0.4,false,function TrapUnit2)
        set t=null
        set drop=null
        set target=null
    endif
    set g=null
endfunction

private function StartFreezing takes nothing returns nothing
    local timer t=CreateTimer()
    local integer Id=GetHandleId(GetExpiredTimer())
    local integer level=LoadInteger(THEHASH,Id,1)
    call SaveGroupHandle(THEHASH,Id,5,CreateGroup())
    call SaveTimerHandle(THEHASH,Id,6,t)
    call SaveInteger(THEHASH,GetHandleId(t),0,Id)
    call TimerStart(t,FreezeTimeout[level],true,function TrapUnit)
    call TimerStart(GetExpiredTimer(),ExtraDuration[level],false,function StartFinal)
    set t=null
endfunction

private function MoveHeroTop takes nothing returns nothing
    local integer Id=GetHandleId(GetExpiredTimer())
    local unit caster=LoadUnitHandle(THEHASH,Id,0)
    local real factor=SpellRadius[LoadInteger(THEHASH,Id,1)]*MODELSCALEFACTOR/450
    local real timeleft=LoadReal(THEHASH,Id,4)-TIMEOUT
    static if MOVE_CASTER then
        call SetUnitFlyHeight(caster,RMaxBJ(0,280+LoadReal(THEHASH,Id,3)-GetPointZ(GetUnitX(caster),GetUnitY(caster))-timeleft*200*factor),0)
    endif
    if timeleft>0 then
        call SaveReal(THEHASH,Id,4,timeleft)
    else
        static if MOVE_CASTER then
            call SetUnitAnimation(caster,CASTER_ANIM_CHANNEL)
            call QueueUnitAnimation(caster,CASTER_ANIM_CHANNEL)
            call QueueUnitAnimation(caster,CASTER_ANIM_CHANNEL)
        endif
        call TimerStart(GetExpiredTimer(),1.8,false,function StartFreezing)
    endif
    set caster=null
endfunction

private function CreateTemple takes unit caster, integer level returns nothing
    local timer t=CreateTimer()
    local integer Id=GetHandleId(t)
    local real ux=GetUnitX(caster)
    local real uy=GetUnitY(caster)
    local real radius=SpellRadius[level]*MODELSCALEFACTOR
    local real angle=GetUnitFacing(caster)*bj_DEGTORAD // x, y and angle with which the temple is created.
    local real x=ux+radius*Cos(angle)
    local real y=uy+radius*Sin(angle)
    local unit temple=CreateUnit(GetOwningPlayer(caster),DUMMY_TEMPLE_ID,x,y,angle*bj_RADTODEG+180)
    call UnitAddAbility(temple,'Amrf')
    call UnitRemoveAbility(temple,'Amrf')
    call SetUnitX(temple,x)
    call SetUnitY(temple,y)
    call SetUnitFlyHeight(temple,260,0)
    call SetUnitScale(temple,radius/450,1,1)
    call SetUnitAnimation(temple,"birth")
    static if MOVE_CASTER then
        call SetUnitInvulnerable(caster,true)
        call PauseUnitSafe(caster)
        call UnitAddAbility(caster,'Amrf')
        call UnitRemoveAbility(caster,'Amrf')
    endif
    call SaveUnitHandle(THEHASH,Id,0,caster)
    call SaveInteger(THEHASH,Id,1,level)
    call SaveUnitHandle(THEHASH,Id,2,temple)
    call SaveReal(THEHASH,Id,3,GetPointZ(x,y))
    call SaveReal(THEHASH,Id,4,2)
    call SaveDestructableHandle(THEHASH,Id,10,CreateDestructable('YTfc',ux,uy,0,1,0))
    call SaveDestructableHandle(THEHASH,Id,11,CreateDestructable('YTfc',x+radius*Cos(angle),y+radius*Sin(angle),0,1,0))
    call SaveDestructableHandle(THEHASH,Id,12,CreateDestructable('YTfc',x+radius*Cos(angle+bj_PI*0.5),y+radius*Sin(angle+bj_PI*0.5),0,1,0))
    call SaveDestructableHandle(THEHASH,Id,13,CreateDestructable('YTfc',x+radius*Cos(angle-bj_PI*0.5),y+radius*Sin(angle-bj_PI*0.5),0,1,0))
    call TimerStart(t,TIMEOUT,true,function MoveHeroTop)
    set temple=null
    set t=null
endfunction

private function CastingFilter takes nothing returns boolean
    if GetSpellAbilityId()==SPELL_ID then
        call CreateTemple(GetTriggerUnit(),GetUnitAbilityLevel(GetTriggerUnit(),SPELL_ID))
    endif
    return false
endfunction

private function Init takes nothing returns nothing
    local trigger spellTrigger = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( spellTrigger, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( spellTrigger, Condition (function CastingFilter) )
    set SubmergeSound = CreateSound( "Abilities\\Spells\\Other\\Submerge\\Submerge1.wav", false, true, true, 10, 10, "" )
    call SetSoundParamsFromLabel( SubmergeSound, "SubmergeSound" )
    call SetupDatas()
endfunction

endscope

Keywords:
Ice, Temple, Ultimate, Freeze, Jaina, Water
Contents

SPELL Ice Temple (Map)

Reviews
21 Jan 2012 Bribe: I like the changes you made. The code is enormously difficult to read, though, and you have a sound variable which is not private for some reason so I feel like approving it but not "recommending" it yet, per say. Using structs...

Moderator

M

Moderator

21 Jan 2012
Bribe: I like the changes you made. The code is enormously difficult to read, though, and you have a sound variable which is not private for some reason so I feel like approving it but not "recommending" it yet, per say. Using structs with TimerUtils data attachment will make this much more readable, but it's up to you. Not doing so will not affect this thing's approval.

Approved 3/5.
 
CosBJ -> Cos
SinBJ -> Sin

The use of those bj globals makes this pretty sloppy. Using locals would be much more readable and much faster (Globals are way too slow)
Also, I recommend adding linebreaks and comments inside the functions for more readability.

And since this is vJass, you should take advantage of structs, else you could make it strictly vanilla Jass so that people using the WE could use it too.

The sound in the globals block should be private.

If you want to stick to using hashtables, I'd recommend implementing Table by Bribe.
It makes working with hashtables a piece of cake.
You'd need multiple Tables though (one for each handle/scalar variable you want to store)

Structs are way better in my opinion. If you're not that familiar with them:
- http://www.hiveworkshop.com/forums/jass-ai-scripts-tutorials-280/structs-dummies-197435/
- http://www.hiveworkshop.com/forums/...ls-280/coding-efficient-vjass-structs-187477/
 
Level 5
Joined
Jan 5, 2012
Messages
134
It looks Cool. I like it. :)
EDIT
I tested it again.
-->[broke="That's Goddamn Amazing! You made all the Models yourself? Dude, this is gold. except Icy, I love it so much. DotA Should Use this. But Dota heroes can kind of run out cant they? :p Anywho, its a Great Spell. 5/5"]Comment[/broke]<--
 
Last edited:
Level 12
Joined
Jul 11, 2010
Messages
422
Thx Final-Burn.

@ Magtheridon96
I said I will be extremely lazy :goblin_jawdrop:. I'm not against making any update but the ones you suggest are only details.

CosBJ -> Cos
SinBJ -> Sin
Yeah, I'll think of it if I update...

The use of those bj globals makes this pretty sloppy. Using locals would be much more readable and much faster (Globals are way too slow)
I need globals for filters and I wanted to limit the global declaration, but that's true I would better use custom globals with good names. But I ask for prooves about the way-too-slowness of globals.

Also, I recommend adding linebreaks and comments inside the functions for more readability.
I just think it's the contrary : I never comment a function inside it. I only put comments inside a function to comment a line or a group of actions. I find it much more readable.

And since this is vJass, you should take advantage of structs, else you could make it strictly vanilla Jass so that people using the WE could use it too.
The main problem with jass is the global declaration... And I prefer to force someone to get the JNGP than letting him think he can do all with simple WE. I don't want to rewrite the code for using structs but I may eventually do that.

The sound in the globals block should be private.
Why?

If you want to stick to using hashtables, I'd recommend implementing Table by Bribe.
It makes working with hashtables a piece of cake.
You'd need multiple Tables though (one for each handle/scalar variable you want to store)
Again, I think the contrary : I find hashtable's API a lot better than Table's API (putting big integers into [] can only give bad habits :ogre_rage:). I usually define more concise functions and use StringHash, but it's even not necessary for such a short scope.
 
Top