• 🏆 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!

Town portal & mini spellpack

Status
Not open for further replies.
Level 17
Joined
Nov 13, 2006
Messages
1,814
i posted here coz i dont got time for make correct tooltip/ balance in dmg, icons etc, maybe this give few ideea to u

i am really glad if somebody can tell me if i do something bad in triggers, it is work but maybe sometimes u see better way :p (and yes it is NORMAL WE JASS, not vjass :p)

First of all, here few thing from map header and map init and +1 trigger


the header, i copied from Magtheridon96 post
JASS:
function HideBothersomeItem takes nothing returns nothing
    if IsItemVisible(GetEnumItem()) then
        set udg_TW_hidden[udg_TW_hiddenMax] = GetEnumItem()
        call SetItemVisible(udg_TW_hidden[udg_TW_hiddenMax], false)
        set udg_TW_hiddenMax = udg_TW_hiddenMax + 1
    endif
endfunction

function IsTerrainWalkable takes real x, real y returns boolean
    
    call MoveRectTo(udg_TW_r, x, y)
    call EnumItemsInRect(udg_TW_r, null, function HideBothersomeItem)

    call SetItemPosition(udg_TW_check, x, y)//this unhides the item...
    set udg_TW_X=GetItemX(udg_TW_check)
    set udg_TW_Y=GetItemY(udg_TW_check)
    call SetItemVisible(udg_TW_check, false)//...so we must hide it again
    
    loop
        exitwhen udg_TW_hiddenMax <= 0
        set udg_TW_hiddenMax = udg_TW_hiddenMax - 1
        call SetItemVisible(udg_TW_hidden[udg_TW_hiddenMax], true)
        set udg_TW_hidden[udg_TW_hiddenMax] = null
    endloop
    
    return (x - udg_TW_X) * (x - udg_TW_X) + (y - udg_TW_Y) * (y - udg_TW_Y) < udg_TW_MAX_RANGE * udg_TW_MAX_RANGE
endfunction

function InitTrig_initTerrainWalk takes nothing returns nothing
    set udg_TW_MAX_RANGE = 10
    set udg_TW_X = 0
    set udg_TW_Y = 0
    set udg_TW_r = Rect(0, 0, 128, 128)
    set udg_TW_check = CreateItem('ciri', 0, 0)
    call SetItemVisible(udg_TW_check, false)
    set udg_TW_hiddenMax = 0 
endfunction

stop channeling function
JASS:
function Trig_Change_crap_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer cv = GetUnitUserData(u)
if udg_Channel_Boolean[cv] == true then
   set udg_Channel_Boolean[cv] = false
endif
set u = null
endfunction

//===========================================================================
function InitTrig_Stop_Channeling takes nothing returns nothing
    set gg_trg_Stop_Channeling = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Stop_Channeling, EVENT_PLAYER_UNIT_SPELL_FINISH )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Stop_Channeling, EVENT_PLAYER_UNIT_SPELL_ENDCAST )

    call TriggerAddAction( gg_trg_Stop_Channeling, function Trig_Change_crap_Actions )
endfunction

mapinit

JASS:
function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
set udg_Channel_Table = InitHashtable()
set udg_Spell_Table = InitHashtable()
set udg_Misc_Table = InitHashtable()
endfunction

//===========================================================================
function InitTrig_Map_init takes nothing returns nothing
    set gg_trg_Map_init = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Map_init, function Trig_Untitled_Trigger_001_Actions )
endfunction



1.
Healing rain - its basically same than Tranquility just here u set how much hp its heal back/mana cost per second

JASS:
function Trig_Tranquility_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A001'
endfunction

function TranquilityTimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local unit u = LoadUnitHandle(udg_Channel_Table, id, 1)
    local integer cv = GetUnitUserData(u)
    local unit pu
    local real x = udg_Channel_X[cv]
    local real y = udg_Channel_Y[cv]
    local real heal
    local real mana = GetUnitState(u, UNIT_STATE_MANA)
    local integer i = 0
   
    if mana >= udg_Channel_ManaCost[cv] and udg_Channel_Boolean[cv] then
        call SetUnitState (u, UNIT_STATE_MANA, (mana - udg_Channel_ManaCost[cv]))

            call GroupEnumUnitsInRange(udg_UG, x, y, 600.00, null)
            loop
                set pu = FirstOfGroup(udg_UG)
                exitwhen (pu==null)
                if IsUnitAlly(pu, GetOwningPlayer(u)) then
                    set heal = GetWidgetLife(pu)+udg_Channel_Dmg[cv]
                    call SetWidgetLife(pu, heal)
                    call DestroyEffect(AddSpecialEffect ("Abilities\\Spells\\Items\\AIil\\AIilTarget.mdl", GetUnitX(pu) , GetUnitY(pu)))
                endif
                call GroupRemoveUnit(udg_UG, pu)
           endloop
    
        call TimerStart(t, 1, false, function TranquilityTimer)
    else
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Channel_Table, id)
        if udg_Channel_CasterSF[cv] != null then
            call IssueImmediateOrder( u, "stop" )
            call DestroyEffect(udg_Channel_CasterSF[cv])
        endif
    endif
   
    set t = null
    set u = null
    set pu = null
endfunction

function Trig_Tranquility_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real radius = 300.00
    local real dmg = 500.00
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)
    local integer cv = GetUnitUserData(u)
    set udg_Channel_Boolean[cv] = true
    set udg_Channel_X[cv] = x
    set udg_Channel_Y[cv] = y
    set udg_Channel_ManaCost[cv] = 10
    set udg_Channel_Dmg[cv] = dmg
    if GetUnitState(u, UNIT_STATE_MANA) >= 10 then
        set udg_Channel_Count[cv] = 0
        set udg_Channel_Dur[cv] = 0
        call SaveUnitHandle(udg_Channel_Table, id, 1, u)
        call TimerStart(t, 0.5, false, function TranquilityTimer)
        set udg_Channel_CasterSF[cv] = AddSpecialEffectTarget("Abilities\\Spells\\NightElf\\Tranquility\\Tranquility.mdl", u, "origin")
    endif
    set t = null
    set u = null
endfunction

//===========================================================================
function InitTrig_Healing_Rain takes nothing returns nothing
    set gg_trg_Healing_Rain = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Healing_Rain, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( gg_trg_Healing_Rain, Condition( function Trig_Tranquility_Conditions ) )
    call TriggerAddAction( gg_trg_Healing_Rain, function Trig_Tranquility_Actions )
endfunction


2.Jump but its more like ground dashing, so jump up (hero look to air, speed slower by height, then fast fall down, hero look the ground during falling and deal aoe dmg)

also knockback the enemies around


JASS:
function Trig_Jump_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A008'
endfunction

function JumpTimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local unit pu
    local unit u = LoadUnitHandle(udg_Spell_Table, id, 1)
    local real dmg
    local real x
    local real y
    local real xt
    local real yt
    local real ang
    local real height = LoadReal(udg_Spell_Table, id, 2)
    local real maxheight = LoadReal(udg_Spell_Table, id, 3)
    local real rate = (maxheight - height) / 3 + 10
    local integer action = LoadInteger(udg_Spell_Table, id, 5)

    call SetUnitAnimation( u, "walk" )

    if action == 1 and height > 0 then
        set height = height - rate
        call SaveReal(udg_Spell_Table, id, 2, height )
        call SetUnitFlyHeight( u, height, 0 )
        call TimerStart(t, 0.03, false, function JumpTimer)
    elseif action == 0 then
        set height = height + rate
        call SaveReal(udg_Spell_Table, id, 2, height)
        call SetUnitFlyHeight( u, height, 0 )
        set maxheight = LoadReal(udg_Spell_Table, id, 3)
        if height > maxheight then
            call SetUnitLookAt( u, "bone_head", u, 0, 0, - 190 )
            call SaveInteger(udg_Spell_Table, id, 5, 1)
        endif
        call TimerStart(t, 0.03, false, function JumpTimer)
    elseif action == 1 and height <= 0 then
        set x = GetUnitX(u)
        set y = GetUnitY(u)
        set dmg = LoadReal(udg_Spell_Table, id, 4)
        call ResetUnitLookAt(u)
        call TerrainDeformRipple(x, y, 200, 25, 1 * 1000, 1, 200 * 2 / 512, 2, 1, false)
        call DestroyEffect(AddSpecialEffect ("Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl", x , y))
        call GroupEnumUnitsInRange(udg_UG, x, y, 250.00, null)
        loop
            set pu = FirstOfGroup(udg_UG)
            exitwhen (pu==null)
            if IsUnitEnemy(pu, GetOwningPlayer(u)) then
                set ang = Atan2(GetUnitY(pu) - y, GetUnitX(pu) - x)
                set xt = x + 250 * Cos(ang)
                set yt = y + 250 * Sin(ang)
                call SetUnitPosition(pu, xt, yt)
                call UnitDamageTarget(u, pu, dmg * 2, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
            endif
            call GroupRemoveUnit(udg_UG, pu)
        endloop
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Spell_Table, id)
    endif

    set t = null
    set u = null
endfunction

function Trig_Jump_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real height = 0.00
    local real maxheight = 300.00
    local integer action = 0
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)
    local real dmg = 100

    call SetUnitLookAt( u, "bone_head", u, 0, 0, + 190 )
    call UnitAddAbility(u, 'Amrf' )
    call UnitRemoveAbility(u, 'Amrf' )

//call SetUnitFlyHeight( u, 100, 0 )
    call SaveUnitHandle(udg_Spell_Table, id, 1, u)
    call SaveReal(udg_Spell_Table, id, 2, height)
    call SaveReal(udg_Spell_Table, id, 3, maxheight)
    call SaveReal(udg_Spell_Table, id, 4, dmg)
    call SaveInteger(udg_Spell_Table, id, 5, action)

    call TimerStart(t, 0.05, false, function JumpTimer)

    set u = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Jump takes nothing returns nothing
    set gg_trg_Jump = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Jump, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Jump, Condition( function Trig_Jump_Conditions ) )
    call TriggerAddAction( gg_trg_Jump, function Trig_Jump_Actions )
endfunction


3. Phoenix Wings
Summon a phoenix what deal damage to every enemy on way and knockback(900 range) then blown up and deal 2x more dmg than phoenix did during flying
(every enemy get only 1x damage before blownup, so dont knock foward the target and hurt again everytime :D)


JASS:
function Trig_PhoenixWings_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A007'
endfunction

function PhoenixWingsTimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local integer cv
    local unit pu
    local unit uc = LoadUnitHandle(udg_Spell_Table, id, 8)
    local unit u = LoadUnitHandle(udg_Spell_Table, id, 1)
    local real x = GetUnitX(uc)
    local real y = GetUnitY(uc)
    local real ang = LoadReal(udg_Spell_Table, id, 2)
    local real nx = x + 50 * Cos(ang * bj_DEGTORAD)
    local real ny = y + 50 * Sin(ang * bj_DEGTORAD)
    local real distance = LoadReal(udg_Spell_Table, id, 3) - 50
    local real dmg = LoadReal(udg_Spell_Table, id, 5)
    local real ucsize = LoadReal(udg_Spell_Table, id, 9) + 0.05
    local integer cliff = LoadInteger(udg_Spell_Table, id, 4)
    local integer cliff1 = GetTerrainCliffLevel(nx, ny)
    call SaveReal(udg_Spell_Table, id, 6, nx)
    call SaveReal(udg_Spell_Table, id, 7, ny)
    call SaveReal(udg_Spell_Table, id, 9, ucsize)
    call SetUnitScale(uc, ucsize, ucsize, ucsize)
    if distance > 0 and IsTerrainWalkable(nx, ny) and cliff==cliff1 then
        call SaveReal(udg_Spell_Table, id, 3, distance)
        call SetUnitPosition(uc, nx, ny)
 
        call GroupEnumUnitsInRange(udg_UG, nx, ny, ucsize * 100, null)
        loop
            set pu = FirstOfGroup(udg_UG)
            exitwhen (pu==null)
            if IsUnitEnemy(pu, GetOwningPlayer(u)) then
                set cv = GetUnitUserData(pu)
                call SetUnitPosition(pu, nx + 50 * Cos(ang * bj_DEGTORAD), ny + 50 * Sin(ang * bj_DEGTORAD))
                if LoadInteger(udg_Misc_Table, id, cv) == 0 then
                    call UnitDamageTarget(u, pu, dmg, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                endif
                call SaveInteger(udg_Misc_Table, id, cv, 1)
            endif
            call GroupRemoveUnit(udg_UG, pu)
        endloop
        call TimerStart(t, 0.05, false, function PhoenixWingsTimer)
    else
        call DestroyEffect(AddSpecialEffect ("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", x , y))
        call GroupEnumUnitsInRange(udg_UG, x, y, 200.00, null)
        loop
            set pu = FirstOfGroup(udg_UG)
            exitwhen (pu==null)
            if IsUnitEnemy(pu, GetOwningPlayer(u)) then
                call UnitDamageTarget(u, pu, dmg * 2, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
            endif
            call GroupRemoveUnit(udg_UG, pu)
        endloop
        call KillUnit(uc)
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Spell_Table, id)
        call FlushChildHashtable(udg_Misc_Table, id)
        call RemoveUnit(uc)
    endif

    set t = null
    set u = null
    set uc = null
endfunction

function Trig_PhoenixWings_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real ang = bj_RADTODEG * Atan2(GetSpellTargetY() - y, GetSpellTargetX() - x)
    local integer cliff = GetTerrainCliffLevel(GetUnitX(u), GetUnitY(u))
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)
    local real distance = 900.00
    local real dmg = 100

    call SaveUnitHandle(udg_Spell_Table, id, 1, u)
    call SaveReal(udg_Spell_Table, id, 2, ang)
    call SaveReal(udg_Spell_Table, id, 3, distance)
    call SaveInteger(udg_Spell_Table, id, 4, cliff)
    call SaveReal(udg_Spell_Table, id, 5, dmg)
    call SaveReal(udg_Spell_Table, id, 6, x)
    call SaveReal(udg_Spell_Table, id, 7, y)
    set u = CreateUnit (GetTriggerPlayer(), 'h008', x, y, ang)
    call SaveUnitHandle(udg_Spell_Table, id, 8, u)
    call SaveReal(udg_Spell_Table, id, 9, 1)

    call TimerStart(t, 0.05, false, function PhoenixWingsTimer)
    set u = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Phoenix_Wings takes nothing returns nothing
    set gg_trg_Phoenix_Wings = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Phoenix_Wings, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Phoenix_Wings, Condition( function Trig_PhoenixWings_Conditions ) )
    call TriggerAddAction( gg_trg_Phoenix_Wings, function Trig_PhoenixWings_Actions )
endfunction


4. Blizzard
Actually original blizzard remade, coz this way u can set the dmgeventtype if u use gui dmg engine, also u can customize the damage/blizard per wave/range etc easily
its also drain the mana every sec so not like original


JASS:
function Trig_Blizzard_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00A'
endfunction

function BlizzardTimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local unit u = LoadUnitHandle(udg_Channel_Table, id, 1)
    local integer cv = GetUnitUserData(u)
    local unit pu
    local real x = udg_Channel_X[cv]
    local real y = udg_Channel_Y[cv]
    local real mana = GetUnitState(u, UNIT_STATE_MANA)
    local integer i = 0
     
    set udg_Channel_Dur[cv] = udg_Channel_Dur[cv] + 1

    if mana >= udg_Channel_ManaCost[cv] and udg_Channel_Boolean[cv] then
        set udg_Channel_Count[cv] = udg_Channel_Count[cv] + 1
        call SetUnitState (u, UNIT_STATE_MANA, (mana - udg_Channel_ManaCost[cv]))
        loop
            exitwhen i > 15
            call DestroyEffect(AddSpecialEffect ("Abilities\\Spells\\Human\\Blizzard\\BlizzardTarget.mdl", x + 250 * Cos(GetRandomReal(0, 360.00) * bj_DEGTORAD) , y + 250 * Sin(GetRandomReal(0, 360.00) * bj_DEGTORAD)))
            set i = i + 1
        endloop
    endif

    if udg_Channel_Dur[cv] > 1 then
        if udg_Channel_Unit[cv] == null then
            set udg_Channel_Unit[cv] = CreateUnit (GetOwningPlayer(u), 'o000', x, y, 0)
        endif
        set udg_Channel_Count[cv] = udg_Channel_Count[cv] - 1
        call GroupEnumUnitsInRange(udg_UG, x, y, 300.00, null)
            loop
                set pu = FirstOfGroup(udg_UG)
                exitwhen (pu==null)
                if IsUnitEnemy(pu, GetOwningPlayer(u)) then
                    call UnitDamageTarget(u, pu, udg_Channel_Dmg[cv], true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                endif
                call GroupRemoveUnit(udg_UG, pu)
            endloop
    endif

    if udg_Channel_Count[cv] == 0 then
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Channel_Table, id)
        if udg_Channel_CasterSF[cv] != null then
            call IssueImmediateOrder( u, "stop" )
            call DestroyEffect(udg_Channel_CasterSF[cv])

        endif
        if udg_Channel_Unit[cv] != null then
            call RemoveUnit (udg_Channel_Unit[cv])
            set udg_Channel_Unit[cv] = null
        endif
    else
        call TimerStart(t, 1, false, function BlizzardTimer)
    endif

    set t = null
    set u = null
    set pu = null
endfunction

function Trig_Blizzard_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real x = GetSpellTargetX()
    local real y = GetSpellTargetY()
    local real radius = 300.00
    local real dmg = 100.00
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)
    local integer cv = GetUnitUserData(u)
    set udg_Channel_Boolean[cv] = true
    set udg_Channel_X[cv] = x
    set udg_Channel_Y[cv] = y
    set udg_Channel_ManaCost[cv] = 10
    set udg_Channel_Dmg[cv] = dmg
    if GetUnitState(u, UNIT_STATE_MANA) >= 10 then
        set udg_Channel_Count[cv] = 0
        set udg_Channel_Dur[cv] = 0
        call SaveUnitHandle(udg_Channel_Table, id, 1, u)
        call TimerStart(t, 0.5, false, function BlizzardTimer)
        set udg_Channel_CasterSF[cv] = AddSpecialEffectTarget("Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl", u, "origin")
    endif
    set t = null
    set u = null
endfunction

//===========================================================================
function InitTrig_Blizzard takes nothing returns nothing
    set gg_trg_Blizzard = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Blizzard, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( gg_trg_Blizzard, Condition( function Trig_Blizzard_Conditions ) )
    call TriggerAddAction( gg_trg_Blizzard, function Trig_Blizzard_Actions )
endfunction


5. Arrow Rain.
previous version was in spell section but this use timer so now totally cleared every triggersleep craps

JASS:
function Trig_Arrow_Rain_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'ANcl'
endfunction

function ArrowUpDown takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local unit u = LoadUnitHandle(udg_Channel_Table, id, 1)
    local unit u1
    local unit pu
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real mana = GetUnitState(u, UNIT_STATE_MANA)
    local integer i = 0
    local integer cv = GetUnitUserData(u)
     
    set udg_Channel_Dur[cv] = udg_Channel_Dur[cv] + 0.2

    if mana >= udg_Channel_ManaCost[cv] and udg_Channel_Boolean[cv] then
        set udg_Channel_Count[cv] = udg_Channel_Count[cv] + 1
        if I2R(R2I(udg_Channel_Dur[cv] + 1)) == udg_Channel_Dur[cv] then
            call SetUnitState (u, UNIT_STATE_MANA, (mana - udg_Channel_ManaCost[cv]))
        endif
        loop
            exitwhen i > 2
            set u1 = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'h000', x + GetRandomInt(0, 100) * Cos(GetRandomReal(0, 360.00) * bj_DEGTORAD) , y + GetRandomInt(0, 100) * Sin(GetRandomReal(0, 360.00) * bj_DEGTORAD), 0)
            call SetUnitFlyHeight(u1, 1500.00, 1200 )
            call UnitApplyTimedLife(u1, 'BTLF', 1.00 )
            set i = i + 1
        endloop
    endif

    if udg_Channel_Dur[cv] > 1.4 then
        set udg_Channel_Count[cv] = udg_Channel_Count[cv] - 1
        set x = udg_Channel_X[cv]
        set y = udg_Channel_Y[cv]
        if I2R(R2I(udg_Channel_Dur[cv] + 1)) == udg_Channel_Dur[cv] then
            call GroupEnumUnitsInRange(udg_UG, x, y, 250.00, null)
            loop
                set pu = FirstOfGroup(udg_UG)
                exitwhen (pu==null)
                if IsUnitEnemy(pu, GetOwningPlayer(u)) then
                    call UnitDamageTarget(u, pu, udg_Channel_Dmg[cv], true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                endif
                call GroupRemoveUnit(udg_UG, pu)
            endloop
        endif
        set i = 0
        loop
            exitwhen i > 4

            set u1 = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'h001', udg_Channel_X[cv] + GetRandomInt(0, 250) * Cos(GetRandomReal(0, 360.00) * bj_DEGTORAD) , udg_Channel_Y[cv] + GetRandomInt(0, 250) * Sin(GetRandomReal(0, 360.00) * bj_DEGTORAD), 0)
            call SetUnitFlyHeight( u1, GetRandomReal(5.00, 40.00), 1500 )
            call UnitApplyTimedLife( u1, 'BTLF', 2.00 )
            set i = i + 1
        endloop
    endif

    if udg_Channel_Count[cv] == 0 then
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Channel_Table, id)
        if udg_Channel_CasterSF[cv] != null then
            call IssueImmediateOrder( u, "stop" )
            call DestroyEffect(udg_Channel_CasterSF[cv])
        endif
    else
        call TimerStart(t, 0.2, false, function ArrowUpDown)
    endif

    set t = null
    set u = null
    set u1 = null
    set pu = null
endfunction

function Trig_Arrow_Rain_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real x = GetSpellTargetX()
    local real y = GetSpellTargetY()
    local real dmg = 100.00
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)
    local integer cv = GetUnitUserData(u)
    set udg_Channel_Boolean[cv] = true
    set udg_Channel_X[cv] = x
    set udg_Channel_Y[cv] = y
    set udg_Channel_ManaCost[cv] = 10
    set udg_Channel_Dmg[cv] = dmg
    if GetUnitState(u, UNIT_STATE_MANA) >= 10 then
        set udg_Channel_Count[cv] = 0
        set udg_Channel_Dur[cv] = 0
        call SaveUnitHandle(udg_Channel_Table, id, 1, u)
        call TimerStart(t, 0.2, false, function ArrowUpDown)
        set udg_Channel_CasterSF[cv] = AddSpecialEffectTarget("Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl", u, "origin")
    endif
    set t = null
    set u = null
endfunction

//===========================================================================
function InitTrig_Arrow_Rain takes nothing returns nothing
    set gg_trg_Arrow_Rain = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Arrow_Rain, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddCondition( gg_trg_Arrow_Rain, Condition( function Trig_Arrow_Rain_Conditions ) )
    call TriggerAddAction( gg_trg_Arrow_Rain, function Trig_Arrow_Rain_Actions )
endfunction


6. Distance Shrink
Fast move the caster foward with 600 range and hurt every enemy on your way


JASS:
function Trig_Distance_Shrink_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00D'
endfunction

function Shrinking takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local integer cv
    local unit u = LoadUnitHandle(udg_Spell_Table, id, 1)
    local unit pu
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real ang = LoadReal(udg_Spell_Table, id, 2)
    local real nx = LoadReal(udg_Spell_Table, id, 5) + 50 * Cos(ang * bj_DEGTORAD)
    local real ny = LoadReal(udg_Spell_Table, id, 6) + 50 * Sin(ang * bj_DEGTORAD)
    local real distance = LoadReal(udg_Spell_Table, id, 3) - 50
    local integer cliff = LoadInteger(udg_Spell_Table, id, 4)

    if distance > 0 and IsTerrainWalkable(nx, ny) and cliff==GetTerrainCliffLevel(nx, ny) then
        call SaveReal(udg_Spell_Table, id, 3, distance)
        call SaveReal(udg_Spell_Table, id, 5, nx)
        call SaveReal(udg_Spell_Table, id, 6, ny)
        call GroupEnumUnitsInRange(udg_UG, nx, ny, 60, null)
        loop
            set pu = FirstOfGroup(udg_UG)
            exitwhen (pu==null)
            if IsUnitEnemy(pu, GetOwningPlayer(u)) then
                set cv = GetUnitUserData(pu)
                if LoadInteger(udg_Misc_Table, id, cv) == 0 then
                    call UnitDamageTarget(u, pu, 100.00, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                endif
                call SaveInteger(udg_Misc_Table, id, cv, 1)
            endif
            call GroupRemoveUnit(udg_UG, pu)
        endloop
        call DestroyEffect(AddSpecialEffect ("Abilities\\Spells\\Orc\\Shockwave\\ShockwaveMissile.mdl", nx , ny))
        call TimerStart(t, 0.03, false, function Shrinking)

    else
        call SetUnitVertexColor(u, 255, 255, 255, 255)
        if GetLocalPlayer() == GetOwningPlayer(u) then
            call ClearSelection()
            call SelectUnit(u, true)
        endif
        call SetUnitPosition(u, nx, ny)
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Spell_Table, id)
        call FlushChildHashtable(udg_Misc_Table, id)
    endif

    set t = null
    set u = null
    set pu = null
endfunction

function Trig_Distance_Shrink_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real ang = GetUnitFacing(u)
    local integer cliff = GetTerrainCliffLevel(GetUnitX(u), GetUnitY(u))
    local timer t = CreateTimer()
    local integer id = GetHandleId(t)
    local real distance = 600.00

    call SetUnitVertexColor(u, 255, 255, 255, 0)

    call SaveUnitHandle(udg_Spell_Table, id, 1, u)
    call SaveReal(udg_Spell_Table, id, 2, ang)
    call SaveReal(udg_Spell_Table, id, 3, distance)
    call SaveInteger(udg_Spell_Table, id, 4, cliff)
    call SaveReal(udg_Spell_Table, id, 5, GetUnitX(u))
    call SaveReal(udg_Spell_Table, id, 6, GetUnitY(u))
    call TimerStart(t, 0.03, false, function Shrinking)

    set u = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Distance_Shrink takes nothing returns nothing
    set gg_trg_Distance_Shrink = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Distance_Shrink, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Distance_Shrink, Condition( function Trig_Distance_Shrink_Conditions ) )
    call TriggerAddAction( gg_trg_Distance_Shrink, function Trig_Distance_Shrink_Actions )
endfunction

7. Town Portal
If somebody played the older diablo the its something like that, create 2 town portal (1 to target location, 1 to village), if u right click to it then its activated and u can go back to village, if u go back with that portal what is in village then after u used it both destoryed


Casting
JASS:
function Trig_TownPortal_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00G'
endfunction

function Trig_TownPortal_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real x = GetSpellTargetX()
    local real y = GetSpellTargetY()
    local real xt = GetRandomReal(GetRectMinX(gg_rct_Village), GetRectMaxX(gg_rct_Village))
    local real yt = GetRandomReal(GetRectMinY(gg_rct_Village), GetRectMaxY(gg_rct_Village))
    local real ang = bj_RADTODEG * Atan2(y - GetUnitY(u), x - GetUnitX(u))
    local integer cv = GetUnitUserData(u)
    set udg_Portal_CUnit[cv] = null
    call RemoveUnit(udg_Portal_Unit[cv])
    call RemoveUnit(udg_Portal_Target[cv])
    set udg_Portal_Unit[cv] = CreateUnit(GetTriggerPlayer(), 'o001', x, y, ang)
    set udg_Portal_Target[cv] = CreateUnit(GetTriggerPlayer(), 'o001', xt, yt, ang)
    set u = null
endfunction

//===========================================================================
function InitTrig_TownPortal takes nothing returns nothing
    set gg_trg_TownPortal = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_TownPortal, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_TownPortal, Condition( function Trig_TownPortal_Conditions ) )
    call TriggerAddAction( gg_trg_TownPortal, function Trig_TownPortal_Actions )
endfunction

Order trigger (if u right click to portal then hero can use it, this needed for avoid the annoying tping without u want)
JASS:
function Trig_Town_Portal_Activation_Conditions takes nothing returns boolean
    return OrderId2String(GetUnitCurrentOrder(GetOrderedUnit())) == "smart"
endfunction


function TPChecking takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local unit u = LoadUnitHandle(udg_Spell_Table, id, 1)
    local integer cv = GetUnitUserData(u)
    local real x1 = GetUnitX(u)
    local real y1 = GetUnitY(u)
    local real x2 = GetUnitX(udg_Portal_CUnit[cv])
    local real y2 = GetUnitY(udg_Portal_CUnit[cv])
    local real dx = x2 - x1
    local real dy = y2 - y1
    local real dist = dx * dx + dy * dy

    if dist > 10000 then
        call TimerStart(t, 1, false, function TPChecking )
    else
        if udg_Portal_CUnit[cv] == udg_Portal_Unit[cv] then
            call SetUnitPosition(u, GetUnitX(udg_Portal_Target[cv]), GetUnitY(udg_Portal_Target[cv]))
        elseif udg_Portal_CUnit[cv] == udg_Portal_Target[cv] then
            call SetUnitPosition(u, GetUnitX(udg_Portal_Unit[cv]), GetUnitY(udg_Portal_Unit[cv]))
            set udg_Portal_CUnit[cv] = null
            call RemoveUnit (udg_Portal_Unit[cv])
            call RemoveUnit (udg_Portal_Target[cv])
        endif
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Spell_Table, id)
        call DestroyEffect(AddSpecialEffect ("Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl", x1 , y1))
        call DestroyEffect(AddSpecialEffect ("Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl", GetUnitX(u) , GetUnitY(u)))
        if (GetLocalPlayer() == GetOwningPlayer(u)) then
            call PanCameraTo(GetUnitX(u), GetUnitY(u))
        endif
    endif
    if udg_Portal_CUnit[cv] == null then
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Spell_Table, id)
    endif
    set t = null
    set u = null
endfunction


function Trig_Town_Portal_Activation_Actions takes nothing returns nothing
    local unit u = GetOrderedUnit()
    local unit ut = GetOrderTargetUnit()
    local integer cv = GetUnitUserData(u)
    local timer t
    local integer id
    local real x1 = GetUnitX(u)
    local real y1 = GetUnitY(u)
    local real x2
    local real y2
    local real xt
    local real yt
    local real dx
    local real dy
    local real dist
    local integer action = 0

    if ut == udg_Portal_Unit[cv] then
        set x2 = GetUnitX(udg_Portal_Unit[cv])
        set y2 = GetUnitY(udg_Portal_Unit[cv])
        set xt = GetUnitX(udg_Portal_Target[cv])
        set yt = GetUnitY(udg_Portal_Target[cv])
        set action = 1
    elseif ut == udg_Portal_Target[cv] then
        set x2 = GetUnitX(udg_Portal_Target[cv])
        set y2 = GetUnitY(udg_Portal_Target[cv])
        set xt = GetUnitX(udg_Portal_Unit[cv])
        set yt = GetUnitY(udg_Portal_Unit[cv])
        set action = 2
    endif

    if action > 0 then
        set udg_Portal_CUnit[cv] = ut
        set dx = x2 - x1
        set dy = y2 - y1
        set dist = dx * dx + dy * dy

        if dist > 10000 then
            call IssuePointOrder(u,"move",xt,yt)
            set t = CreateTimer()
            set id = GetHandleId(t)
            call SaveUnitHandle(udg_Spell_Table, id, 1, u)
            call TimerStart(t, 1, false, function TPChecking )
        elseif udg_Portal_CUnit[cv] == udg_Portal_Target[cv] then
            call SetUnitPosition(u, xt, yt)
            set udg_Portal_CUnit[cv] = null
            call RemoveUnit (udg_Portal_Unit[cv])
            call RemoveUnit (udg_Portal_Target[cv])
            call DestroyEffect(AddSpecialEffect ("Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl", x1 , y1))
            call DestroyEffect(AddSpecialEffect ("Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl", xt , yt))
            if (GetLocalPlayer() == GetOwningPlayer(u)) then
                call PanCameraTo(xt, yt)
            endif
        endif
    endif

    set u = null
    set t = null

endfunction

//===========================================================================
function InitTrig_Town_Portal_To_Village takes nothing returns nothing
    set gg_trg_Town_Portal_To_Village = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Town_Portal_To_Village, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
    call TriggerAddCondition( gg_trg_Town_Portal_To_Village, Condition( function Trig_Town_Portal_Activation_Conditions ) )
    call TriggerAddAction( gg_trg_Town_Portal_To_Village, function Trig_Town_Portal_Activation_Actions )
endfunction
 

Attachments

  • 1.jpg
    1.jpg
    197.6 KB · Views: 130
  • 2.jpg
    2.jpg
    192.5 KB · Views: 81
  • 3.jpg
    3.jpg
    180.6 KB · Views: 76
  • 4.jpg
    4.jpg
    165.7 KB · Views: 82
  • arrowrain.w3x
    71.3 KB · Views: 83
Level 29
Joined
Mar 10, 2009
Messages
5,016
Healing rain only;
- all confuguration such as radius, dmg, sfx, etc...is recommended be placed on top as a constant function...
- you do not need to use unit indexer if you're using hashtables...
- in your loop, filter also if ally is alive...
- you should put an event like EVENT_PLAYER_UNIT_SPELL_ENDCAST...
- save a boolean (true) as ID (or index) of your caster, and in your loop and put it here >>> if mana >= udg_Channel_ManaCost[cv], replacing the udg_Channel_Boolean[cv]...
- if your spell ENDS, or stop prematurely set it to false...

This...
JASS:
set heal = GetWidgetLife(pu)+udg_Channel_Dmg[cv]
call SetWidgetLife(pu, heal)

can be...
call SetWidgetLife(pu, GetWidgetLife(pu)+udg_Channel_Dmg[cv])

Remove:
- call TimerStart(t, 1, false, function TranquilityTimer)[/icode], coz you already have it in the casting code...
- set pu = null coz the FirstOfGroup nulls it...
- GetUnitState(u, UNIT_STATE_MANA) >= 10, coz its already in the object editor and the loop...
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
Healing rain only;
- all confuguration such as radius, dmg, sfx, etc...is recommended be placed on top as a constant function...
- you do not need to use unit indexer if you're using hashtables...
- in your loop, filter also if ally is alive...
- you should put an event like EVENT_PLAYER_UNIT_SPELL_ENDCAST...
- save a boolean (true) as ID (or index) of your caster, and in your loop and put it here >>> if mana >= udg_Channel_ManaCost[cv], replacing the udg_Channel_Boolean[cv]...
- if your spell ENDS, or stop prematurely set it to false...

This...
JASS:
set heal = GetWidgetLife(pu)+udg_Channel_Dmg[cv]
call SetWidgetLife(pu, heal)

can be...
call SetWidgetLife(pu, GetWidgetLife(pu)+udg_Channel_Dmg[cv])

Remove:
- call TimerStart(t, 1, false, function TranquilityTimer)[/icode], coz you already have it in the casting code...
- set pu = null coz the FirstOfGroup nulls it...
- GetUnitState(u, UNIT_STATE_MANA) >= 10, coz its already in the object editor and the loop...

i used unit indexer coz i must use it anyway but another side it i faster than save everything to hashtable and load it then save again,no?

ally alive thing is good ideea
so it is this right?
JASS:
not IsUnitType(pu, UNIT_TYPE_DEAD)

first, thank you coz u checked the trigger, +rep ofc

if u have time then i am glad if u can check the another triggers too

i used endcast/stop cast trigger, it is in 1st post 1st hidden tag

i dont got that mana cost part since i need it for if because if dont have mana then channeling must stop, coz ability must consume x mana each second

Remove:
- call TimerStart(t, 1, false, function TranquilityTimer)[/icode], coz you already have it in the casting code...
then i just use call the TranquilityTimer?

then how can i save the timer id and keep tracking? because atm i start in action function, and in timer loop function i allways get the expired timer, but if i dont start in action function then dont have expired timer and also no timerid for hashtable....

- GetUnitState(u, UNIT_STATE_MANA) >= 10, coz its already in the object editor and the loop...

i dont got why, because since it must drain each time x mana, i must check allways the current mana, io want channeling ability based on periodic mana drain not like regular casting mana cost.
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
GetUnitUserData(u) returns 0 without a UnitIndexer (bro-tip)

WEAPON_TYPE_WHOKNOWS and DAMAGE_TYPE_NORMAL can be replaced with null and you'd get the same results.

Since you're using a UnitIndexer, hashtables are pointless.
You could replace them with arrays and use the UnitUserData as indices.

i never thought the normal dmg type also null :D so more shorter the code, the weapon type thing u noticed to me in my spellpack too, i will change it (atm i used in few ability case, damage but when i will use later buffs instead dmg's just when i implentate to my bigger map then easier if unit group with loop already done :D)

but then how to identify example the unit what i knocking back? or u mean make 1 timer for each spell?
problem is the time intervals are different, so ok i can do linked list for knockback, but then example for jump i must use a different trigger with different periodic time and a different linked list array checking, this could be madness if many ability use different time interval :)

in channeling ability also i will change healing rain periodic time to 5 sec and since only players use triggering spell, so it is 10-20 timer in same time if we cast fast (if 10 player, each cast 1 ability then fast another and still previous timer run then its 20 timer), if i do for each timer interval 1 timer then atleast that also 5-6 periodic timer trigger, so difference worth the effort?

a question, have this null constants, but in jasscraft why show me everywhere convertstat convert this and that things if it is null?
i belive to u, just dont understand why have that ConvertDamageType(4) things?
 
My bad, only the things that are equal to ConvertXXXXXX(0) can be replaced with null
DAMAGE_TYPE_UNKNOWN can be replaced with null.
DAMAGE_TYPE_NORMAL should be kept as is :p (I fail sometimes)
ATTACK_TYPE_NORMAL -> null (just for future reference)

I editted my first post with relatively large text, but while saving, my browser and I was too lazy to rewrite it again :p

Here's a brief explanation of what you should do:

Use dynamic indexing to get indices for the spell and use arrays for everything.
You can get an index by calling Allocate:

JASS:
function Allocate takes nothing returns integer
    local integer this = rn[0]
    if this == 0 then
        set ic = ic + 1
        return ic
    endif
    set rn[0] = rn[this]
    return this
endfunction

You deallocate an instance when you're done with it by calling Deallocate(integer):

JASS:
function Deallocate takes integer this returns nothing
    set rn[this] = rn[0]
    set rn[0] = this
endfunction

These are the required variables:
integer ic
integer array rn

What this does is recycle instances.
Assume the spell runs for 3 seconds:

Using it every 5 seconds would keep the index at 1.
Using it every 2 seconds:

0 seconds: using 1
2 seconds: using 2
3 seconds: 1 is recycled, 2 is still active
4 seconds: 2 is recycled, using 1
etc...
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
My bad, only the things that are equal to ConvertXXXXXX(0) can be replaced with null
DAMAGE_TYPE_UNKNOWN can be replaced with null.
DAMAGE_TYPE_NORMAL should be kept as is :p (I fail sometimes)
ATTACK_TYPE_NORMAL -> null (just for future reference)

I editted my first post with relatively large text, but while saving, my browser and I was too lazy to rewrite it again :p

Here's a brief explanation of what you should do:

Use dynamic indexing to get indices for the spell and use arrays for everything.
You can get an index by calling Allocate:

JASS:
function Allocate takes nothing returns integer
    local integer this = rn[0]
    if this == 0 then
        set ic = ic + 1
        return ic
    endif
    set rn[0] = rn[this]
    return this
endfunction

You deallocate an instance when you're done with it by calling Deallocate(integer):

JASS:
function Deallocate takes integer this returns nothing
    set rn[this] = rn[0]
    set rn[0] = this
endfunction

These are the required variables:
integer ic
integer array rn

What this does is recycle instances.
Assume the spell runs for 3 seconds:

Using it every 5 seconds would keep the index at 1.
Using it every 2 seconds:

0 seconds: using 1
2 seconds: using 2
3 seconds: 1 is recycled, 2 is still active
4 seconds: 2 is recycled, using 1
etc...

so acctually Allocate function, get me a unused index, right?
so i can attach this index something like this:
spellid=Allocate
udg_Spellindex[cv] = spellid
udg_spell_dmg[spellid]=100
udg_spell_caster[spellid]=triggerunit

this good for dot, regeneration and for every spell where timer got same interval. this nice

but still i must use different timer for different interval things, like example where interval 0.03 sec, 0.5sec, 5 sec etc
 
Status
Not open for further replies.
Top