Spellpack DotA Spell Pack 1

emjlr3

Change can be a good thing
Reaction score
395
DotA Spell Pack 1

My first attempt at using ABC and TT, with some abilities not found in DotA Heroes. Toss and Black Hole were requested.
Includes:
  1. Toss
  2. Ice Path
  3. Wild Axes
  4. Black Hole

Toss:

Toss.jpg

JASS:
scope Toss

//******************************************************************************************
//*
//*  Toss - By emjlr3, Original seen in DotA Allstars
//*
//*  Toss a friend or foe from here to there by targeting on a unit, and grabbing
//*  a random target in the area, launching them towards the targeted area.
//* 
//*  Requires:
//*    - "TT" trigger copied to your map, if not already there
//*    - The "Toss" ability copied to your map
//*    - A vJASS Preprocessor
//*
//******************************************************************************************

globals
    // Config Globals:
    private constant integer abil_id = 'A001' // Toss ability rawcode
    private constant integer fly_id = 'Amrf' // Rawcode of ability to use for fly trick, if you have not touched Crow Form, this doesn't need changing
    private constant real impact_damage = .20 // Percent of toss damage dealt to tossed unit
    private constant real time = 1. // Flight time for tossed unit (seconds)
    private constant string fly_sfx = "Abilities\\Spells\\Undead\\Cripple\\CrippleTarget.mdl" // Effect created on target during toss
    private constant string end_sfx = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl" // Effect created on target at end of toss
    private constant boolean kill_trees = true // Whether trees are destroyed upon target landing
    private constant attacktype attack_type = ATTACK_TYPE_NORMAL // Attack type used for damage
    private constant damagetype damage_type = DAMAGE_TYPE_DEMOLITION // Damage type used for damage
    
    // Needed Globals:
    private group G = CreateGroup()
    private unit U = null
    private rect R = null
    private location L = null
    public trigger Trigger = null // Output trigger will be Toss_Trigger, which can be used publically
endglobals
// Config. Functions:
private function Damage takes integer lvl returns real
    return 75.*lvl // Damage/lvl
endfunction
private function Area takes integer lvl returns real
    return 275. // Area within to grab units and damage units/lvl
endfunction

//========================================================================================
private struct data
    unit u
    unit targ
    player p
    real xt
    real yt
    real xl
    real yl
    real dist
    real ang
    real cos
    real sin
    real speed
    real hc
    integer lvl
    integer count = 1
    effect e
    
    static method FiltIsEnemy takes nothing returns boolean
        return IsUnitEnemy(GetFilterUnit(), bj_groupEnumOwningPlayer) and GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>.405
    endmethod 
    static method DamageGroup takes unit damager, real radius, real x, real y, real amount returns nothing
        local unit u
    
        set bj_groupEnumOwningPlayer = GetOwningPlayer(damager)
        call GroupClear(G)
        call GroupEnumUnitsInRange(G, x, y, radius, Condition(function data.FiltIsEnemy)) 
        loop
            set u = FirstOfGroup(G)
            exitwhen u == null
            call GroupRemoveUnit(G,u)
            call UnitDamageTarget(damager,u,amount,false,false,attack_type,damage_type,null)
        endloop
    endmethod
    static method KillTrees_Child takes nothing returns nothing
        call KillDestructable(GetEnumDestructable())    
    endmethod
    static method KillTrees takes real x, real y, real radius returns nothing
        set R = Rect(x - radius,y - radius,x + radius,y + radius)
    
        call EnumDestructablesInRect(R,null,function data.KillTrees_Child)
        call RemoveRect(R)
    endmethod
    method onDestroy takes nothing returns nothing
        call SetUnitFlyHeight(.targ,GetUnitDefaultFlyHeight(.targ),0.)
		call PauseUnit(.targ,false)
		call SetUnitPathing(.targ,true)
        call DestroyEffect(.e)
        call UnitDamageTarget(.u,.targ,Damage(.lvl)*impact_damage,false,false,attack_type,damage_type,null)
		call DestroyEffect(AddSpecialEffectTarget(end_sfx,.targ,"origin"))
		call data.DamageGroup(.u,Area(.lvl),.xl,.yl,Damage(.lvl))
        if kill_trees then
            call data.KillTrees(.xl,.yl,Area(.lvl))
        endif
    endmethod
endstruct

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == abil_id
endfunction
private function Filt takes nothing returns boolean
    return GetFilterUnit()!=U and GetWidgetLife(GetFilterUnit())>.405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(),UNIT_TYPE_FLYING)
endfunction
private function GetSpeed takes real dist returns real
    return dist/(1./TT_PERIOD)
endfunction
private function GetCountConversion takes integer count returns real
    return (50./(time/TT_PERIOD))*count
endfunction
private function Movement takes nothing returns boolean
    local data d = TT_GetData()
    local real conv
    local real height
	local real speed 
    local real x 
    local real y 
    
    if d.count<=time/TT_PERIOD then
        set conv = GetCountConversion(d.count)
        set height = (conv-25.)*(conv-25.)
        set speed = d.count*d.speed
        set x = d.xt+speed*d.cos
        set y = d.yt+speed*d.sin
        call SetUnitX(d.targ,x)
        call SetUnitY(d.targ,y)
		call SetUnitFlyHeight(d.targ,625.-height,0.)
		set d.count = d.count + 1
        return false
	else
        call d.destroy()
        return true
    endif
endfunction
private function Actions takes nothing returns nothing
    local data d = data.create()
    
    set d.u = GetTriggerUnit()
    set d.p = GetOwningPlayer(d.u)
    set d.lvl = GetUnitAbilityLevel(d.u,abil_id)
    
    call GroupClear(G)
    set U = d.u
    call GroupEnumUnitsInRange(G,GetUnitX(d.u),GetUnitY(d.u),Area(d.lvl),Condition(function Filt))
    set d.targ = GroupPickRandomUnit(G)
    if d.targ==null then
        call d.destroy()
        return
    endif
    
    set d.xt = GetUnitX(d.targ)
    set d.yt = GetUnitY(d.targ)
    set L = GetSpellTargetLoc()
    set d.xl = GetLocationX(L)
    set d.yl = GetLocationY(L)
    set d.ang = Atan2(d.yl-d.yt,d.xl-d.xt)
    set d.cos = Cos(d.ang)
    set d.sin = Sin(d.ang)
    set d.dist = SquareRoot((d.xt-d.xl)*(d.xt-d.xl) + (d.yt-d.yl)*(d.yt-d.yl))
    set d.speed = GetSpeed(d.dist)
    
    call PauseUnit(d.targ,true)
    call SetUnitPathing(d.targ,false)
    call UnitAddAbility(d.targ,fly_id)
    call UnitRemoveAbility(d.targ,fly_id)
    set d.e = AddSpecialEffectTarget(fly_sfx,d.targ,"origin")
    
    call TT_Start(function Movement,d)
    
    call RemoveLocation(L)
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    set Trigger = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( Trigger, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( Trigger, Condition( function Conditions ) )
    call TriggerAddAction( Trigger, function Actions )
endfunction

endscope

Ice Path:

IP.jpg

JASS:
scope IcePath

//******************************************************************************************
//*
//*  Ice Path - By emjlr3 - Original seen in DotA Allstars
//* 
//*  Creates a path of ice in front of the caster, which promptly explodes, freezing
//*  units nearby.
//* 
//*  Requires:
//*    - "TT", "PUI", "ABC" and "ABCT" triggers copied to your map, if not already there
//*    - The "Ice Path" ability copied to your map
//*    - The "Ice Path" unit copied to your map
//*    - A vJASS Preprocessor
//*
//******************************************************************************************

globals
    private constant integer abil_id = 'A004' // Ice Path ability rawcode
    private constant integer dummy_id = 'e001' // Ice Path unit rawcode
    private constant real space = 100. // Space between each ice block
    private constant real life = .75 // Duration of each created ice block (seconds)
    private constant integer counter = 2 // How many timer runs must pass before a new ice block is created, added this in since with TT you cannot specificy dynamically timer speed, and speed is not a physical value in the spell, so this allows you to create blocks at multiples of your TT_PERIOD
    private constant string create_sfx = "Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl" // Effect on ice blocks when created
    private constant string death_sfx = "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathMissile.mdl" // Effect during ice blocks death
    private constant string pause_sfx = "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdl" // Effect created on paused units
    
    private location L = null
    private unit Dum = null
    private integer Lvl
    private group G = CreateGroup()
    public trigger Trigger = null // Output trigger will be IcePath_Trigger, which can be used publically
    private effect array SFX // Use PUI to return the effect attached to an affected unit
    private integer array LVL // Use PUI to return the level of the ability for the dummy ice block
endglobals
private function Number takes integer lvl returns integer
    return 10 // Ice blocks created/lvl
endfunction
private function Area takes integer lvl returns real
    return 175. // Stun area/lvl
endfunction
private function Duration takes integer lvl returns real
    return .5*lvl // Stun duration/lvl
endfunction

private struct data
    unit u
    player p
    real x
    real y
    real xl
    real yl
    real ang
    real cos
    real sin
    integer count = 0
    integer total
    integer lvl
    
    group grp
endstruct

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId()==abil_id
endfunction
private function Movement takes nothing returns boolean
    local data d = TT_GetData()
    local real x
    local real y
    
    set d.count = d.count + 1
    if d.count>(d.total*counter)+counter then
        call d.destroy()
        return true
    endif
    
    if ModuloInteger(d.count,counter)!=1 or d.count/counter==0 then
        return false
    endif
    
    set x = d.x+((d.count/counter)*space)*d.cos
    set y = d.y+((d.count/counter)*space)*d.sin
    set Dum = CreateUnit(d.p,dummy_id,x,y,GetRandomReal(0.,360.))
    call UnitApplyTimedLife(Dum,'BTLF',life)
    //call SetUnitUserData(Dum,d.lvl)
    set LVL[GetUnitIndex(Dum)] = d.lvl
    call DestroyEffect(AddSpecialEffect(create_sfx,x,y))
    
    return false
endfunction
private function Actions takes nothing returns nothing       
    local data d = data.create()
    set L = GetSpellTargetLoc()        
    
    set d.u = GetTriggerUnit()
    set d.p = GetOwningPlayer(d.u)
    set d.x = GetUnitX(d.u)
    set d.y = GetUnitY(d.u)
    set d.xl = GetLocationX(L)
    set d.yl = GetLocationY(L)
    set d.ang = Atan2(d.yl - d.y, d.xl - d.x)
    set d.cos = Cos(d.ang)
    set d.sin = Sin(d.ang)
    set d.lvl = GetUnitAbilityLevel(d.u,abil_id)
    set d.total = Number(d.lvl)
    call TT_Start(function Movement,d)
    
    call RemoveLocation(L)
endfunction

private function Death_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit())==dummy_id
endfunction
private function Filt takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit())>.405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE) and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetTriggerUnit())) 
endfunction
private function UnStun_Child takes nothing returns nothing
    local integer pui = GetUnitIndex(GetEnumUnit())
    
    call PauseUnit(GetEnumUnit(),false)
    call SetUnitTimeScale(GetEnumUnit(),1.)
    call DestroyEffect(SFX[pui])
    set SFX[pui] = null
endfunction
private function UnStun takes nothing returns boolean
    local data d = ABCT_GetData()
    
    call ForGroup(d.grp,function UnStun_Child)
    call DestroyGroup(d.grp)
    call d.destroy()
    return true
endfunction
private function Stun takes nothing returns nothing
    local integer pui = GetUnitIndex(GetEnumUnit())
    
    call PauseUnit(GetEnumUnit(),true)
    call SetUnitTimeScale(GetEnumUnit(),0.)    
    if SFX[pui]==null then
        set SFX[pui] = AddSpecialEffectTarget(pause_sfx,GetEnumUnit(),"origin")
    endif
endfunction
private function Death_Actions takes nothing returns nothing
    local data d = data.create()
    
    set Dum = GetTriggerUnit()
    //set Lvl = GetUnitUserData(Dum)
    set Lvl = LVL[GetUnitIndex(Dum)]
    set d.grp = CreateGroup()
    call GroupEnumUnitsInRange(d.grp,GetUnitX(Dum),GetUnitY(Dum),Area(Lvl),Condition(function Filt))
    call ForGroup(d.grp,function Stun)
    
    call ABCT_Start(function UnStun,d,Duration(Lvl))
    call DestroyEffect(AddSpecialEffect(death_sfx,GetUnitX(Dum),GetUnitY(Dum)))
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    local trigger trig = CreateTrigger()
    set Trigger = CreateTrigger()
    
    call TriggerRegisterAnyUnitEventBJ(Trigger , EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(Trigger, function Actions)
    call TriggerAddCondition(Trigger , Condition(function Conditions))
    
    call TriggerRegisterAnyUnitEventBJ(trig , EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddAction(trig , function Death_Actions)
    call TriggerAddCondition(trig , Condition(function Death_Conditions))
endfunction

endscope

Wild Axes

WA.jpg

JASS:
scope WildAxes

//******************************************************************************************
//*
//*  Wild Axes - By emjlr3, Original seen in DotA Allstars
//*
//*  Hurl two axes outward, which then intersect and return. Each axe can 
//*  only damage a unit once and destroys trees in its wake. 
//* 
//*  Requires:
//*    - "TT" trigger copied to your map, if not already there
//*    - The "Wild Axes" ability copied to your map
//*    - The "Wild Axes" unit copied to your map
//*    - A vJASS Preprocessor
//*
//******************************************************************************************

globals
    // Config. Globals:
    private constant integer abil_id = 'A003' // Wild Axes ability rawcode
    private constant integer dummy_id = 'e000' // Wild Axes unit rawcode
    private constant real speed = .028 // Speed for axes, this is an arbitrary value, increasing it increases the axes speed, while decreasing it decreases their speed
    private constant real width = 375. // Width for bezier curve, larger values give a wider arc, and vice versa
    private constant real area = 150. // Area to damage units around axes and destroy trees
    private constant string sfx = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl" // Effect created on hit units
    private constant attacktype attack_type = ATTACK_TYPE_NORMAL // Attack type for damage
    private constant damagetype damage_type = DAMAGE_TYPE_NORMAL // Damage type for damage
    
    // Needed Globals:
    public trigger Trigger = null // Output trigger will be WildAxes_Trigger, which can be used publically
    private group G = CreateGroup()
    private group TempG = null
    private player P = null
    private location L = null
    private rect R = null
endglobals
// Config. Functions:
private function Damage takes integer lvl returns real
    return 50.+(lvl*30.) // Damage/lvl
endfunction

private struct data
    unit u
    unit axe
    player p
    group grp
    real x
    real y
    real xl
    real yl
    real a = 1.
    real outx
    real outy
    real ang
    integer lvl
    boolean first = true
endstruct

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId()==abil_id
endfunction
private function Filt takes nothing returns boolean
    return not IsUnitInGroup(GetFilterUnit(),TempG) and GetWidgetLife(GetFilterUnit())>.405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and IsUnitEnemy(GetFilterUnit(),P)
endfunction
private function Kill_Trees takes nothing returns nothing
	call KillDestructable(GetEnumDestructable())
endfunction
private function Effects takes unit u, real x, real y, group grp, integer lvl returns nothing
    local unit dum
    
    set R = Rect(x-150.,y-150.,x+150.,y+150.)
    call EnumDestructablesInRect(R,null,function Kill_Trees)
    call RemoveRect(R)
    call GroupClear(G)
    set P = GetOwningPlayer(u)
    set TempG = grp
    call GroupEnumUnitsInRange(G,x,y,area,Condition(function Filt))
    loop
        set dum = FirstOfGroup(G)
        exitwhen dum==null
        call GroupRemoveUnit(G,dum)
        call UnitDamageTarget(u,dum,Damage(lvl),false,false,attack_type,damage_type,null)
        call DestroyEffect(AddSpecialEffectTarget(sfx,dum,"chest"))
        call GroupAddUnit(grp,dum)
    endloop
endfunction
private function Movement takes nothing returns boolean
    local data d = TT_GetData()
    local real b = 1.-d.a
    
    call SetUnitX(d.axe,d.x*d.a*d.a+d.outx*2*d.a*b+d.xl*b*b)
	call SetUnitY(d.axe,d.y*d.a*d.a+d.outy*2*d.a*b+d.yl*b*b)
    call Effects(d.u,GetUnitX(d.axe),GetUnitY(d.axe),d.grp,d.lvl)
    if d.first then
		set d.a = d.a-speed
	else
		set d.a = d.a+speed
		set d.x = GetUnitX(d.u)
		set d.y = GetUnitY(d.u)
	endif
    if d.a<0. and d.first then
		set d.first = false
		set d.outx = d.x+width*Cos(Atan2(d.yl-d.y,d.xl-d.x)+d.ang)
        set d.outy = d.y+width*Sin(Atan2(d.yl-d.y,d.xl-d.x)+d.ang)
	endif
    if d.a>1. and d.first==false then
		call DestroyGroup(d.grp)
		call RemoveUnit(d.axe)
		call d.destroy()
        return true
	endif
    return false
endfunction
private function Actions takes nothing returns nothing
    local data d1 = data.create()
    local data d2 = data.create()
    
    set d1.u = GetTriggerUnit()
    set d2.u = d1.u
    set d1.x = GetUnitX(d1.u)
    set d2.x = d1.x
    set d1.y = GetUnitY(d1.u)
    set d2.y = d1.y
    set d1.p = GetOwningPlayer(d1.u)
    set d2.p = d1.p
    set d1.axe = CreateUnit(d1.p,dummy_id,d1.x,d1.y,0.)
    set d2.axe = CreateUnit(d1.p,dummy_id,d1.x,d1.y,0.)
    set d1.grp = CreateGroup()
    set d2.grp = CreateGroup()
    set d1.lvl = GetUnitAbilityLevel(d1.u,abil_id)
    set d2.lvl = d1.lvl
    set L = GetSpellTargetLoc()
    set d1.xl = GetLocationX(L)
    set d2.xl = d1.xl
    set d1.yl = GetLocationY(L)
    set d2.yl = d1.yl
    
    set d1.outx = d1.x+width*Cos(Atan2(d1.yl-d1.y,d1.xl-d1.x)+45.)
    set d1.outy = d1.y+width*Sin(Atan2(d1.yl-d1.y,d1.xl-d1.x)+45.)
    set d2.outx = d1.x+width*Cos(Atan2(d1.yl-d1.y,d1.xl-d1.x)-45.)
    set d2.outy = d1.y+width*Sin(Atan2(d1.yl-d1.y,d1.xl-d1.x)-45.)
    set d1.ang = -45.
    set d2.ang = 45.
    
    call TT_Start(function Movement,d1)
    call TT_Start(function Movement,d2)
    
    call RemoveLocation(L)
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    set Trigger = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( Trigger, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( Trigger, Condition( function Conditions ) )
    call TriggerAddAction( Trigger, function Actions )
endfunction

endscope

Black Hole

BH.jpg

JASS:
scope BlackHole

//******************************************************************************************
//*
//*  Blackhole - By emjlr3, Original seen in DotA Allstars
//*
//*  Summon a black hole from the darkest abyss, which sucks enemy units into
//*  its center, dealing damage over time. 
//* 
//*  Requires:
//*    - "TT" trigger copied to your map, if not already there
//*    - The "Black Hole" ability copied to your map
//*    - The "Black Hole (Dummy)" ability copied to your map
//*    - The "Black Hole" buff copied to your map, set as the previous abilities buff
//*    - The "Black Hole" unit copied to your map, with the "Black Hole (Dummy)" ability added to it
//*    - A vJASS Preprocessor
//*
//******************************************************************************************

globals
    // Config. Globals:
    private constant integer abil_id = 'A002' // Black Hole ability rawcode
    private constant integer dummy_id = 'u000' // Black Hole unit rawcode
    private constant real pull = 1.75 // Distance pulled/interval
    private constant boolean fight = false // Whether units can fight against the pull
    private constant string sfx = "Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl" // Effect created on pulled units
    
    // Needed Globals:
    public trigger Trigger = null // Output trigger will be BlackHole_Trigger, which can be used publically
    private group G = CreateGroup()
    private player P = null
    private real X
    private real Y
endglobals
// Config. Functions:
private function Range takes integer lvl returns real
    return 400. // Area for pull/lvl
endfunction
// Damage is found on the Black Hole (Dummy) ability

private struct data
    unit hole
    unit u
    player p
    integer lvl
    real x
    real y
endstruct

private function Conditions takes nothing returns boolean
    return GetUnitTypeId(GetSummonedUnit())==dummy_id
endfunction
private function Filt takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit())>.405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and IsUnitEnemy(GetFilterUnit(),P)
endfunction
private function Effects takes nothing returns nothing
    local real x 
    local real y
    local real ang
    
    set bj_ghoul[25] = GetEnumUnit()
    set x = GetUnitX(bj_ghoul[25])
    set y = GetUnitY(bj_ghoul[25])
    set ang = Atan2(Y-y,X-x)
    if fight then
        call SetUnitX(bj_ghoul[25],x+pull*Cos(ang))
        call SetUnitY(bj_ghoul[25],y+pull*Sin(ang))
    else
        call SetUnitPosition(bj_ghoul[25],x+pull*Cos(ang),y+pull*Sin(ang))
    endif
    call DestroyEffect(AddSpecialEffectTarget(sfx,bj_ghoul[25],"origin"))
endfunction
private function Movement takes nothing returns boolean
    local data d = TT_GetData()
    
    if GetWidgetLife(d.hole)<.405 then
        call d.destroy()
        return true
    endif
    
    call GroupClear(G)
    set P = d.p
    set X = d.x
    set Y = d.y
    call GroupEnumUnitsInRange(G,d.x,d.y,Range(d.lvl),Condition(function Filt))
    call ForGroup(G,function Effects)
    return false
endfunction
private function Actions takes nothing returns nothing
    local data d = data.create()
    
    set d.hole = GetSummonedUnit()
    set d.x = GetUnitX(d.hole)
    set d.y = GetUnitY(d.hole)
    set d.u = GetSummoningUnit()
    set d.p = GetOwningPlayer(d.u)
    set d.lvl = GetUnitAbilityLevel(d.u,abil_id)
    call TT_Start(function Movement,d)
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    set Trigger = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( Trigger, EVENT_PLAYER_UNIT_SUMMON )
    call TriggerAddCondition( Trigger, Condition( function Conditions ) )
    call TriggerAddAction( Trigger, function Actions )
endfunction

endscope

Enjoy, and please comment

Version 3
 

Attachments

  • emjlr3 - DotA Spell Pack 1.w3x
    125 KB · Views: 2,501

Cohadar

master of fugue
Reaction score
209
Welcome to the dark side :)

Lets tear this code apart:

==================================================
In Toss you are using a bunch of static methods that have absolutely nothing in common with the struct they are into.

Static methods should be used only when you need to access some static attributes of the struct.
Most common examples are static counters (for whatever purpose)
Or when you pass data to filters or ForGroup functions with static methods of a struct. (in order to encapsulate)

Now since you have not a single one static attribute it is plain and simple wrong.
It only pollutes struct name space without any purpose.
Those static methods have nothing to do with structs and should be private functions instead.
==================================================
START YOUR STRUCT NAMES WITH UPPERCASE OR BE DOOMED FOREVER.
==================================================
JASS:
    set d.count = d.count + 1
    if d.count>(d.total*counter)+counter then
        call d.destroy()
        return true
    endif


and
JASS:
    if d.count<=time/TT_PERIOD then
        set conv = GetCountConversion(d.count)
        set height = (conv-25.)*(conv-25.)
        //....


Have you considered using ticks? aka counting downwards?
==================================================

Everything else is perfect and I see you did some heavy math here.
Not easy to make stuff at all. Have some rep.
EDIT:
I would also like to say that I am especially pleased how you made this stuff Period independent,
but I did not expect anything less from you anyways.
 

Tinki3

Special Member
Reaction score
418
Cool spellpack.
Though, I noticed that you use "not InUnitType(...)" in your filter funcs:
SFilip once said that IsUnitType can cause bugs if a == or != comparison is not used (If I can recall correctly).

Black Hole code seems fine.

Ice Path code also seems fine, apart from in the "Death_Actions" trigger, why are you grouping with the global G group, and then adding the group
to the d.grp, when you could just directly group through d.grp?

Toss:
In the static method "KillTrees", you're leaking a Rect, R.

Wild Axes code is good, but, you're leaking a Rect in the "Effects" function.

Overall, cool :)
Note: you might want to change the title to something else; "DotA Spells 1" has already been used, I think.
 

Trollvottel

never aging title
Reaction score
262
looks ok, but i dont like how the icepathed units are freezed, set their animation speed to 0 and make an ice cube surrounding them, not just pause them it looks not so very good
 

Cohadar

master of fugue
Reaction score
209
looks ok, but i dont like how the icepathed units are freezed, set their animation speed to 0 and make an ice cube surrounding them, not just pause them it looks not so very good

Or even better use entangling roots with Ice Block as a model.
 

emjlr3

Change can be a good thing
Reaction score
395
Sexy.
I like Toss the most =)
PS: How did you manage to make it so smooth?

is it usually not so?

Cool spellpack.
Though, I noticed that you use "not InUnitType(...)" in your filter funcs:
SFilip once said that IsUnitType can cause bugs if a == or != comparison is not used (If I can recall correctly).

Black Hole code seems fine.

Ice Path code also seems fine, apart from in the "Death_Actions" trigger, why are you grouping with the global G group, and then adding the group
to the d.grp, when you could just directly group through d.grp?

Toss:
In the static method "KillTrees", you're leaking a Rect, R.

Wild Axes code is good, but, you're leaking a Rect in the "Effects" function.

Overall, cool :)
Note: you might want to change the title to something else; "DotA Spells 1" has already been used, I think.

you are correct about the rects, its minor - but still a leak, optimizer fixes the unittype "bug", also correct about grouping note, will update that too

looks ok, but i dont like how the icepathed units are freezed, set their animation speed to 0 and make an ice cube surrounding them, not just pause them it looks not so very good

that could be aranged

Explain to me how will entangled units move? with their eyebrows?

lol, +rep

Or even better use entangling roots with Ice Block as a model.

i was trying to avoid un-needed dummy abilities
 

Tinki3

Special Member
Reaction score
418
> optimizer fixes the unittype "bug"

Is that right? I never knew it did that, cool.

> i was trying to avoid un-needed dummy abilities

They get annoying, yep.
Though, you should add some effect to the frozen units to make it look like they are more frozen, IMO.
(Through triggers).
 

Tom_Kazansky

--- wraith it ! ---
Reaction score
157
I made Wild Axe too, but emjlr3's Wild Axe looks better
EDIT: And I think it's the hardest spell in this pack
 

soulreaping

New Member
Reaction score
17
Dota's toss:
Code:
Tiny grabs the nearest unit, friend or foe, and launches them at a location

Your toss:
Code:
Toss a friend or foe from here to there by targeting on a unit, and grabbing
a random target in the area, launching them towards the targeted area.

In dota's toss it grabs the nearest unit, maybe you should change that, or you didn't intend to make it the same I don't know, but if you did then you probably need to change that.

The other abilities are awesome, great work.

Only the Ice Path should create an ice block on all frozen units.
 

waaaks!

Zinctified
Reaction score
255
ooo Toss

thats what im waiting for

ill try it

+rep

EDIT:
In dota's toss it grabs the nearest unit, maybe you should change that, or you didn't intend to make it the same I don't know, but if you did then you probably need to change that.
Wrong...

dota's Toss doesnt grab the nearest unit....instead the random unit...ive played tiny a lot...thats why my favorite spell is toss (i even saved my game on dota when playing tiny, because im planning on making a toss video)

it only says the nearest unit, but the real thing is, it picks a random unit
like icefrog is faking the tooltip and the spell
 

Hatebreeder

So many apples
Reaction score
380
is it usually not so?



you are correct about the rects, its minor - but still a leak, optimizer fixes the unittype "bug", also correct about grouping note, will update that too



that could be aranged



lol, +rep



i was trying to avoid un-needed dummy abilities

Well, most of the Toss Spells are, well, they are triangular... They don't look like a Curve, this one, however, is smooth =)
I'm just curious, what is the maths formula for a smooth Curve?
(Well, It's kinda hard for me to follow this Code)
 

emjlr3

Change can be a good thing
Reaction score
395
ooo Toss

thats what im waiting for

ill try it

+rep

EDIT:

Wrong...

dota's Toss doesnt grab the nearest unit....instead the random unit...ive played tiny a lot...thats why my favorite spell is toss (i even saved my game on dota when playing tiny, because im planning on making a toss video)

it only says the nearest unit, but the real thing is, it picks a random unit
like icefrog is faking the tooltip and the spell

correct, he does that with a lot of spells, take greater bash, he says it knocks back X distance, but if you look at the code, not only is the distance variable upon the length the polledwait last, but it also is not even close to the distances suggested
Well, most of the Toss Spells are, well, they are triangular... They don't look like a Curve, this one, however, is smooth =)
I'm just curious, what is the maths formula for a smooth Curve?
(Well, It's kinda hard for me to follow this Code)

try graphing 775-[(x-25)*(x-25)]
from x=1 to x=50 , with window size from y=0 to y=800

and there is your curve, the max height is 775 I believe, and therefore, the value of y(x) = (x-25)*(x-25) at a given location subtracted from 775 will give you the height you want at that location, where x is a value from 1-50, and goes from the start location to the end location of the movement
 

Trollvottel

never aging title
Reaction score
262
>Explain to me how will entangled units move? with their eyebrows?

yes thats what i mean, they play their stand animation and so some of them turn around or play football etc.....
 

emjlr3

Change can be a good thing
Reaction score
395
Version 2 uploaded

  • fixed rect leaks in Toss and Wild Axes
  • reworked Toss fly height change a bit, now it is perfect
  • added pause effect to Ice Path, added check in group filter for dead units, and removed unit animation speed during pause
  • removed usage of global group on death of ice blocks in Ice Path

Ice Path now requires PUI

**** El problemo, for some odd reason, effects do not get removed very reliably, could someone check that I used PUI correctly, and try to figure out wtf it is doing what it is doing....
 

Cohadar

master of fugue
Reaction score
209
JASS:

private function UnStun_Child takes nothing returns nothing
    local integer pui = GetUnitIndex(GetEnumUnit())
    call PauseUnit(GetEnumUnit(),false)
    call SetUnitTimeScale(GetEnumUnit(),1.)
    call DestroyEffect(SFX[pui])
    set SFX[pui] = null // you have to null pui attached values, so you know they are recycled
endfunction


JASS:

private function Stun takes nothing returns nothing
    local integer pui = GetUnitIndex(GetEnumUnit())
    call PauseUnit(GetEnumUnit(),true)
    call SetUnitTimeScale(GetEnumUnit(),0.)
    if SFX[pui] != null then // since unit handles are recycled this can be true
        call DestroyEffect(SFX[pui])
        call BJDebugMsg("told ya")
    endif
    set SFX[pui] = AddSpecialEffectTarget(pause_sfx,GetEnumUnit(),"origin")
endfunction


Btw when I tested the map "told ya" was printed every time.
So I guess you are adding ice effects to the same unit twice.
(witch is why they did not remove properly)

Come to think of it I even saw animations blinking twice.
So you have an error in your code somewhere.

Theoretically if your code was 100% correct you would not have to null pui variables and "told ya" would never print.
But I am a programmer and I know for a fact that there is no such thing as 100% correct code.
 

emjlr3

Change can be a good thing
Reaction score
395
ah k, makes sense

Version 3 uploaded, fixed perma effect bug with Ice Path

also realised that Ice Path is not fully MUI, that would require a timer/unit, and I dont care to go down that path, if you care you can always do it yourself

enjoy
 

Cohadar

master of fugue
Reaction score
209
that would require a timer/unit
enjoy

Or unitArray + tick/unit

I had that problem with IceAge spell (FrostMage ulty)

Spells like that should be handled by buff engine actually.
But meh, who cares.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/
  • The Helper The Helper:
    Here is another comfort food favorite - Million Dollar Casserole - https://www.thehelper.net/threads/recipe-million-dollar-casserole.193614/

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top