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

Volibear Spellpack v1.1

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
  • Like
Reactions: 1 person
Hi this is my first SpellPack.

Systems used:
-UnitIndexer
-DamangeEvent
-GroupUtils
-TimerUtils
-xecast
-UnitEvent
-MoveUnitX
-PlayerEvent
-SpellEfectEvent
-KnockbackTools
-LightingSystem
-TimedEffect

The codes:

ChosenOfTheStorm:
JASS:
scope ChosenOfTheStorm

    //Todas las estadisticas de la habilidad han sido sacadas de:
    //http://gameinfo.lan.leagueoflegends.com/es/game-info/champions/volibear/

    //CONFIG
    //==========================================================
    globals
        private constant integer    SPELL_ID           = 'A007'
        private constant integer    DUMMY_SPELL_ID     = 'A009'
        private constant integer    DUMMY_ID           = 'e000'
        private constant string     DUMMY_ORDER_STRING = "innerfire"
        private constant string     EFECT_FX           = "Abilities\\Heal_Green.mdl"
        private constant real       BUFF_DURATION      = 6.
        private constant real       SPELL_CD           = 120.
        private constant real       LIFE_SPEED_RATE    = 1.8
        private constant real       LIFE_PERCENT       = 30.
    endglobals
    //==========================================================
    //ENDCONFIG

    private function GetLifePercent takes unit u returns real
        return GetWidgetLife(u)/GetUnitState(u,UNIT_STATE_MAX_LIFE)*100.
    endfunction

    private function GetLifeSpecificPercent takes unit u returns real
        return GetUnitState(u,UNIT_STATE_MAX_LIFE)*LIFE_PERCENT/100.
    endfunction

    private struct ChosenOfTheStorm
        static xecast caster
        unit u
        real currentLife
        real totalLife
        real duration
        boolean onCD

        static method onLoop takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            local real l=GetWidgetLife(.u)+LIFE_SPEED_RATE

            set .duration=.duration-.03125
            call SetWidgetLife(.u,l)
    
            if l>=.totalLife or .duration<=0. then
                set .u=null
                call ReleaseTimer(t)
            endif
            set t=null
        endmethod

        method setAlive takes nothing returns nothing
            set .totalLife=GetLifeSpecificPercent(.u)+.currentLife
            call SetWidgetLife(.u,.currentLife)
            call TimerStart(NewTimerEx(this),.03125,true,function thistype.onLoop)
        endmethod

        method reincarnate takes nothing returns nothing
            local unit u=GetEventUnit()
            local real x=GetUnitX(u)
            local real y=GetUnitY(u)
            local player p=GetOwningPlayer(u)
            call SelectUnit(u,GetLocalPlayer()==p)
            call TimedEffect.createOnUnit(EFECT_FX,u,"overhead",BUFF_DURATION)
            set caster.owningplayer=p
            call caster.castOnTarget(u)
            call .setAlive()
            set u=null
        endmethod
        implement UnitEventStruct

        static method cooldown takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            set .onCD=false
            call ReleaseTimer(t)
            set t=null
        endmethod

        static method filter takes nothing returns boolean
            local thistype this=DamageEvent.targetId
            local player p1=GetOwningPlayer(DamageEvent.target)
            local player p2=GetOwningPlayer(DamageEvent.source)
            return IsPlayerEnemy(p1,p2) and GetUnitAbilityLevel(DamageEvent.target,SPELL_ID)>0 and GetLifePercent(DamageEvent.target)<=LIFE_PERCENT and not .onCD
        endmethod

        static method onDamage takes nothing returns nothing
            local thistype this=DamageEvent.targetId
            local unit d=CreateUnit(GetOwningPlayer(DamageEvent.source),DUMMY_ID,0.,0.,0.)

            set .u=DamageEvent.target
            set .onCD=true
            set .duration=BUFF_DURATION
            set .currentLife=GetWidgetLife(.u)
            
            call UnitDamageTarget(d,.u,99999.,false,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_NORMAL,null)
            call TimerStart(NewTimerEx(this),SPELL_CD,false,function thistype.cooldown)
            call RemoveUnit(d)
    
            set d=null
        endmethod
        implement DamageEvent
        
        static method onInit takes nothing returns nothing
            set caster=xecast.createBasic(DUMMY_SPELL_ID,OrderId(DUMMY_ORDER_STRING),Player(15))
            set caster.recycledelay=.1
        endmethod
    endstruct
endscope

RollingThunder:
JASS:
scope RollingThunder

    globals
        private real array dmgLvl
        private real array speedLvl
    endglobals

    //Todas las estadisticas de la habilidad han sido sacadas de:
    //http://gameinfo.lan.leagueoflegends.com/es/game-info/champions/volibear/

    //CONFIG
    //==========================================================
    globals
        private constant integer    SPELL_ID       = 'A008'
        private constant integer    BUFF_ID        = 'B002'
        private constant string     FX_1           = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"
        private constant string     FX_2           = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
        private constant real       BUFF_DURATION  = 4.
        private constant real       AoE            = 1700.
        private constant real       TREES_RATIO    = 200.
        private constant real       SPEED_RATE     = 15.
        private constant damagetype DMG_TYPE       = DAMAGE_TYPE_NORMAL
    endglobals

    private function DamangeConfig takes nothing returns nothing
        set dmgLvl[1] = 30.
        set dmgLvl[2] = 60.
        set dmgLvl[3] = 90.
        set dmgLvl[4] = 120.
        set dmgLvl[5] = 150.
    endfunction

    private function SpeedConfig takes nothing returns nothing
        set speedLvl[1] = 30.
        set speedLvl[2] = 35.
        set speedLvl[3] = 40.
        set speedLvl[4] = 45.
        set speedLvl[5] = 50.
    endfunction
    
    private function FilterConfig takes unit u returns boolean
        return IsUnitType(u,UNIT_TYPE_HERO) and not IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)
    endfunction
    //==========================================================
    //ENDCONFIG
    
    private struct RollingThunder
        static rect treesRect
        static unit f=null
        static thistype ta_this
        unit c
        player p
        real duration
        real speed
        real dmg
        real extTotal
        boolean hit
        
        private static method killTrees takes nothing returns nothing
            local destructable d=GetEnumDestructable()
            if not IsDestructableIsDead(d) and IsDestructableIsTree(d) then
                call KillDestructable(d)
            endif
            set d=null
        endmethod
        
        static method onKnockbackStop takes nothing returns boolean
            call DestroyEffect(AddSpecialEffectTarget(FX_1,Knockback.lastStopedUnit,"origin"))
            call MoveRectTo(treesRect,GetUnitX(Knockback.lastStopedUnit),GetUnitY(Knockback.lastStopedUnit))
            call EnumDestructablesInRect(treesRect,null,function thistype.killTrees)
            return false
        endmethod
        
        static method filter takes nothing returns boolean
            local thistype this=DamageEvent.sourceId
            local player p1=GetOwningPlayer(DamageEvent.target)
            local player p2=GetOwningPlayer(DamageEvent.source)
            return IsPlayerEnemy(p1,p2) and not IsUnitType(DamageEvent.target,UNIT_TYPE_MAGIC_IMMUNE) and GetUnitAbilityLevel(DamageEvent.source,BUFF_ID)>0 and .hit
        endmethod
        
        static method onDamage takes nothing returns nothing
            local thistype this=DamageEvent.sourceId
            local unit u=DamageEvent.target
            local real x1=GetUnitX(.c)
            local real y1=GetUnitY(.c)
            local real x2=GetUnitX(u)
            local real y2=GetUnitY(u)
            local real d=SquareRoot(Pow(x2-x1,2)+Pow(y2-y1,2))
            local real a=Atan2(y1-y2,x1-x2)
            local unit dum=CreateUnit(.p,XE_DUMMY_UNITID,x1,y1,0.)
    
            call UnitDamageTarget(dum,u,.dmg,false,false,ATTACK_TYPE_HERO,DMG_TYPE,null)
            call DestroyEffect(AddSpecialEffectTarget(FX_2,u,"origin"))
            
            if not IsUnitType(u,UNIT_TYPE_STRUCTURE) then
                set Knockback[u].speed=20.
                set Knockback[u].arc=.9
                set Knockback[u].fx=""
                set Knockback[u].fly=true
                set Knockback[u].pause=true
                set Knockback[u].pathing=false
                set Knockback[u].hitTrees=false
                set Knockback[u].useSlideSpeed=false
                call Knockback[u].launch(a,d*2.+20.)
            endif
    
            set .hit=false
            call RemoveUnit(dum)
    
            set dum=null
            set u=null
        endmethod
        implement DamageEvent
        
        static method filterGroup takes nothing returns boolean
            local thistype this=ta_this
            set f=GetFilterUnit()
            return IsPlayerEnemy(GetOwningPlayer(f),.p) and GetWidgetLife(f)>.405 and FilterConfig(f) and IsUnitVisible(f,.p)
        endmethod

        static method onLoop takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            local real x=GetUnitX(.c)
            local real y=GetUnitY(.c)
    
            set ta_this=this
            call GroupEnumUnitsInArea(ENUM_GROUP,x,y,AoE,Filter(function thistype.filterGroup))

            if not IsUnitGroupEmptyBJ(ENUM_GROUP) then
                if .speed<.extTotal then
                    set .speed=.speed+.6
                    call SetUnitMoveSpeed(.c,.speed)
                endif
            endif

            set .duration=.duration-.03125
    
            if .duration<=0. then
                call SetUnitMoveSpeed(.c,GetUnitDefaultMoveSpeed(.c))
                set .c=null
                set .p=null
                call ReleaseTimer(t)
            endif
            set t=null
        endmethod

        static method onCast takes nothing returns nothing
            local unit c=GetTriggerUnit()
            local thistype this=GetUnitId(c)
            local integer lvl=GetUnitAbilityLevel(c,SPELL_ID)
            local real ex=(GetUnitDefaultMoveSpeed(c)*SPEED_RATE)/100.
    
            if .c==null then
                set .c=c
                set .p=GetTriggerPlayer()
            endif
            
            set .speed   =GetUnitDefaultMoveSpeed(.c)+ex
            set .extTotal=(.speed*speedLvl[lvl])/100.+GetUnitDefaultMoveSpeed(.c)
            set .dmg     =dmgLvl[lvl]
            set .duration=BUFF_DURATION
            set .hit     =true
    
            call SetUnitMoveSpeed(.c,GetUnitDefaultMoveSpeed(.c))
            call TimerStart(NewTimerEx(this),.03125,true,function thistype.onLoop)
            
            set c=null
        endmethod
        
        static method onInit takes nothing returns nothing
            call DamangeConfig()
            call SpeedConfig()
            set treesRect=Rect(-TREES_RATIO,-TREES_RATIO,TREES_RATIO,TREES_RATIO)
            call Knockback.registerEvent(Condition(function thistype.onKnockbackStop),Knockback.STOP)
            call RegisterSpellEffectEvent(SPELL_ID,function thistype.onCast)
        endmethod
    endstruct
endscope

Frenesi:
JASS:
scope Frenesi

    globals
        private real array dmgLvl
        private integer array buffLvl
    endglobals

    //Todas las estadisticas de la habilidad han sido sacadas de:
    //http://gameinfo.lan.leagueoflegends.com/es/game-info/champions/volibear/

    //CONFIG
    //==========================================================
    globals
        private constant integer    VOLIBEAR_DUMMY     = 'h003'
        private constant integer    PASSIVE_SPELL_ID   = 'A006'
        private constant integer    SPELL_ID           = 'A005' //Mordisco
        private constant integer    BUFF_ID            = 'B003'
        private constant string     BUFF_ORDER_ID      = "unholyfrenzy"
        private constant string     FX                 = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
        private constant real       ADDITIONAL_LIFE    = 15.
        private constant real       AoE_ON_CAST        = 250.
        private constant real       BUFF_DURATION      = 4.
        private constant damagetype DMG_TYPE           = DAMAGE_TYPE_NORMAL
    endglobals

    private function DamangeConfig takes nothing returns nothing
        set dmgLvl[1] = 80.
        set dmgLvl[2] = 125.
        set dmgLvl[3] = 170.
        set dmgLvl[4] = 215.
        set dmgLvl[5] = 260.
    endfunction

    private function BuffConfig takes nothing returns nothing
        set buffLvl[1] = 'A00A'
        set buffLvl[2] = 'A00B'
        set buffLvl[3] = 'A00C'
    endfunction

    private function GetLifePercent takes unit u returns real
        return GetWidgetLife(u)/GetUnitState(u,UNIT_STATE_MAX_LIFE)*100.
    endfunction

    private function GetAdditionalLife takes unit u returns real
        return (I2R(GetHeroStr(u,true)-GetHeroStr(u,false))*ADDITIONAL_LIFE)/100.
    endfunction
    
    private function FilterConfig takes unit u returns boolean
        return not IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(u,UNIT_TYPE_STRUCTURE)
    endfunction
    //==========================================================
    //ENDCONFIG
    
    private struct Frenesi
        static xecast caster
        unit c
        unit u
        player p
        integer count
        integer chargue
        real duration
        real dur
        real dmg
        boolean up
        boolean haveBite
        
        static method recycle takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            call SetPlayerAbilityAvailable(.p,SPELL_ID,false)
            call SetPlayerAbilityAvailable(.p,PASSIVE_SPELL_ID,true)
            set .haveBite=false
            call ReleaseTimer(t)
            set t=null
        endmethod

        static method onPeriodic takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            set .dur=.dur+.03125
            call IssueImmediateOrderById(.c,851972)
            if .dur>=.3 then
                call SetUnitTimeScale(.c,1.)
                if GetWidgetLife(.u)>.405 then
                    call IssueTargetOrderById(.c,851983,.u)
                endif
                call ReleaseTimer(t)
            endif
            set t=null
        endmethod

        static method onBiteCast takes nothing returns nothing
            local thistype this=GetUnitId(GetTriggerUnit())
            local integer lvl=GetUnitAbilityLevel(.c,PASSIVE_SPELL_ID)
            local real addDmg
            local real d=SquareRoot(Pow(GetUnitX(.u)-GetUnitX(.c),2)+Pow(GetUnitY(.u)-GetUnitY(.c),2))
            
            call TimerStart(NewTimerEx(this),.1,false,function thistype.recycle)
    
            if d<=AoE_ON_CAST and GetWidgetLife(.u)>.405 then
                call DestroyEffect(AddSpecialEffectTarget(FX,.u,"origin"))
        
                set addDmg=100.-GetLifePercent(.u)
                set .dmg=dmgLvl[lvl]+addDmg+GetAdditionalLife(.c)
                set .dur=0.
                call IssueImmediateOrderById(.c,851972)
                call SetUnitAnimation(.c,"Attack")
                call SetUnitTimeScale(.c,2.)
                call TimerStart(NewTimerEx(this),.03125,true,function thistype.onPeriodic)
                call UnitDamageTarget(.c,.u,.dmg,false,false,ATTACK_TYPE_HERO,DMG_TYPE,null)
            endif
            set .count=3
        endmethod
        
        method executeCaster takes integer abilId, integer lvl returns nothing
            set caster.owningplayer = .p
            set caster.abilityid = abilId
            set caster.level = lvl
            set caster.orderstring = BUFF_ORDER_ID
            call caster.castOnTarget(.c)
        endmethod
        
        method destroy takes nothing returns nothing
            if .haveBite then
                call SetPlayerAbilityAvailable(.p,SPELL_ID,false)
                call SetPlayerAbilityAvailable(.p,PASSIVE_SPELL_ID,true)
                set .haveBite=false
            endif
            set .c=null
            set .u=null
            set .p=null
            set .count=0
        endmethod

        static method onLoop takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            set .duration=.duration-.03125
            if .duration==0. then
                call .destroy()
                call ReleaseTimer(t)
            endif
            set t=null
        endmethod

        static method filter takes nothing returns boolean
            local thistype this=DamageEvent.sourceId
            local player p1=GetOwningPlayer(DamageEvent.target)
            local player p2=GetOwningPlayer(DamageEvent.source)
            return IsPlayerEnemy(p1,p2) and FilterConfig(DamageEvent.target) and GetUnitAbilityLevel(DamageEvent.source,PASSIVE_SPELL_ID)>0
        endmethod

        static method onDamage takes nothing returns nothing
            local thistype this=DamageEvent.sourceId
            local integer lvl=GetUnitAbilityLevel(DamageEvent.source,PASSIVE_SPELL_ID)
            local real x=GetUnitX(DamageEvent.source)
            local real y=GetUnitY(DamageEvent.source)

            set .count=.count+1
            set .duration=BUFF_DURATION
    
            if .count>=3 and .count<4 then
                if GetUnitAbilityLevel(.c,BUFF_ID)==0 then
                    call .executeCaster(buffLvl[1],lvl)
                endif
            endif
    
            if .count>=4 and .count<7 then
                if .up then
                    set .chargue=.chargue+1
                endif
                call .executeCaster(buffLvl[.chargue],lvl)
            endif
            
            if .count==6 then
                if not .haveBite then
                    call SetPlayerAbilityAvailable(.p,PASSIVE_SPELL_ID,false)
                    call SetPlayerAbilityAvailable(.p,SPELL_ID,true)
                    set .haveBite=true
                endif
                set .count=3
                set .up=false
                set .chargue=3
            endif
    
            if .u!=null then
                set .u=null
            endif
            
            set .u=DamageEvent.target
            
            if .c==null then
                set .c=DamageEvent.source
                set .p=GetOwningPlayer(.c)
                set .chargue=0
                set .up=true
                call TimerStart(NewTimerEx(this),.03125,true,function thistype.onLoop)
            endif
        endmethod
        implement DamageEvent

        static method onLearnedSkill takes nothing returns nothing
            local unit u=GetTriggerUnit()
            if (GetLearnedSkill()==PASSIVE_SPELL_ID) and GetUnitAbilityLevel(u,PASSIVE_SPELL_ID)==1 then
                call UnitAddAbility(u,SPELL_ID)
                call SetPlayerAbilityAvailable(GetTriggerPlayer(),SPELL_ID,false)
            endif
            set u=null
        endmethod

        static method onInit takes nothing returns nothing
            set caster=xecast.create()
            set caster.recycledelay=.1
            call DamangeConfig()
            call BuffConfig()
            call RegisterPlayerUnitEvent(EVENT_PLAYER_HERO_SKILL,function thistype.onLearnedSkill)
            call RegisterSpellEffectEvent(SPELL_ID,function thistype.onBiteCast)
        endmethod
    endstruct
endscope

MajesticRoar:
JASS:
scope MajesticRoar

    globals
        private real array dmgLvl
    endglobals

    //Todas las estadisticas de la habilidad han sido sacadas de:
    //http://gameinfo.lan.leagueoflegends.com/es/game-info/champions/volibear/

    //CONFIG
    //==========================================================
    globals
        private constant integer    SPELL_ID           = 'A00E'
        private constant integer    DUMMY_ID           = 'e000'
        private constant integer    DUMMY_EFECT_ID     = 'h002'
        private constant integer    DUMMY_SPELL_ID     = 'A004'
        private constant string     DUMMY_ORDER_STRING = "slow"
        private constant string     EFECT_FX           = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
        private constant real       EFECT_DURATION     = .40
        private constant real       AoE                = 425.
        private constant real       AP_POWER           = 60.
        private constant damagetype DMG_TYPE           = DAMAGE_TYPE_MAGIC
        private constant boolean    GET_ATT_BONUS      = true
    endglobals

    private function DamangeConfig takes nothing returns nothing
        set dmgLvl[1] = 60.
        set dmgLvl[2] = 105.
        set dmgLvl[3] = 150.
        set dmgLvl[4] = 195.
        set dmgLvl[5] = 240.
    endfunction

    private function GetAttribute takes unit u, boolean bonus returns real
        return (I2R(GetHeroInt(u,bonus))*AP_POWER)/100.
    endfunction
    
    private function FilterConfig takes unit u returns boolean
        return not IsUnitType(u,UNIT_TYPE_STRUCTURE) and not IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)
    endfunction
    //==========================================================
    //ENDCONFIG

    private struct MajesticRoar
        static xecast caster
        static unit f=null
        
        static method destroyEffect takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            call RemoveUnit(GetUnitById(this))
            call ReleaseTimer(t)
            set t=null
        endmethod

        static method filter takes nothing returns boolean
            local player p=GetTriggerPlayer()
            set f=GetFilterUnit()
            return IsPlayerEnemy(GetOwningPlayer(f),p) and GetWidgetLife(f)>.405 and FilterConfig(f)
        endmethod

        static method onCast takes nothing returns nothing
            local unit c     =GetTriggerUnit()
            local player p   =GetTriggerPlayer()
            local real x     =GetUnitX(c)
            local real y     =GetUnitY(c)
            local integer lvl=GetUnitAbilityLevel(c,SPELL_ID)
            local real dmg   =GetAttribute(c,GET_ATT_BONUS)+dmgLvl[lvl]
            local unit d     =CreateUnit(p,DUMMY_ID,x,y,0.)
            local unit m     =CreateUnit(p,DUMMY_EFECT_ID,x,y,0.)
            local thistype id=GetUnitId(m)
            local integer duration=R2I(EFECT_DURATION*1000.)
            local real spaceWave  =2.*duration/10.
            local real timeWave   =2.*AoE/200.
            local real radiusRatio=AoE/50.
            local unit u

            call TimerStart(NewTimerEx(id),EFECT_DURATION,false,function thistype.destroyEffect)
            call DestroyEffect(AddSpecialEffect(EFECT_FX,x,y))
            call TerrainDeformStop(TerrainDeformRipple(x,y,AoE,200.,duration,2,spaceWave,timeWave,radiusRatio,true),duration)
            
            call GroupEnumUnitsInArea(ENUM_GROUP,x,y,AoE,Filter(function thistype.filter))
            set caster.owningplayer=p
            set caster.level=lvl
            
            loop
                set u=FirstOfGroup(ENUM_GROUP)
                call GroupRemoveUnit(ENUM_GROUP,u)
                call UnitDamageTarget(d,u,dmg,false,false,ATTACK_TYPE_HERO,DMG_TYPE,null)
                call caster.castOnTarget(u)
                exitwhen u==null
            endloop
    
            call RemoveUnit(d)
            set c=null
            set d=null
            set m=null
        endmethod

        static method onInit takes nothing returns nothing
            call DamangeConfig()
            set caster=xecast.createBasic(DUMMY_SPELL_ID,OrderId(DUMMY_ORDER_STRING),Player(15))
            set caster.recycledelay=.1
            call RegisterSpellEffectEvent(SPELL_ID,function thistype.onCast)
        endmethod
    endstruct
endscope

ThunderClaws:
JASS:
scope ThunderClaws

    globals
        private real array dmgLvl
    endglobals

    //Todas las estadisticas de la habilidad han sido sacadas de:
    //http://gameinfo.lan.leagueoflegends.com/es/game-info/champions/volibear/

    //CONFIG
    //==========================================================
    globals
        //Lo basico:
        private constant integer    DUMMY_MISSILE_ID   = 'h001'
        private constant integer    SPELL_ID           = 'A003'
        //Configuraciones de habilidad y buff casteados por el dummy:
        private constant integer    DUMMY_SPELL_ID     = 'A00N'
        private constant integer    BUFF_ID            = 'B008'
        private constant string     DUMMY_ORDER_STRING = "spiritlink"
        //Efectos:
        private constant string     EFECT_FX           = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
        private constant string     FX_ON_CAST         = "Abilities\\Spells\\Orc\\LightningShield\\LightningShieldTarget.mdl"
        //Tipo de rayo:
        private constant string     LIGHTNING_EFECT    = "CLPB"
        //Reales:
        private constant real       AoE                = 300.
        private constant real       AP_POWER           = 30.
        //Valores de escala:
        private constant real       DEFAULT_SCALE      = 1.05
        private constant real       MAX_SCALE_PERCENT  = 46.
        private constant real       MAX_LIGHTNING_Z    = 170.
        //Configuraciones relacionadas con el daño provocado:
        private constant integer    MAX_HITS           = 4
        private constant damagetype DMG_TYPE           = DAMAGE_TYPE_MAGIC
        private constant boolean    GET_ATT_BONUS      = true
    endglobals

    private function DamangeConfig takes nothing returns nothing
        set dmgLvl[1] = 75.
        set dmgLvl[2] = 115.
        set dmgLvl[3] = 155.
    endfunction

    private function GetAttribute takes unit u, boolean bonus returns real
        return (I2R(GetHeroInt(u,bonus))*AP_POWER)/100.
    endfunction
    
    private function FilterConfig takes unit u returns boolean
        return not IsUnitType(u,UNIT_TYPE_STRUCTURE) and not IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)
    endfunction
    //==========================================================
    //ENDCONFIG

    private struct ThunderClaws
        static constant location loc1=Location(0.,0.)
        static constant location loc2=Location(0.,0.)
        static unit f=null
        static xecast caster
        real scaleDefault
        real scale
        unit c

        static method recycleDummy takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            call RemoveUnit(GetUnitById(this))
            call ReleaseTimer(t)
            set t=null
        endmethod
        
        static method scaleLoop takes nothing returns nothing
            local timer t=GetExpiredTimer()
            local thistype this=GetTimerData(t)
            if GetUnitAbilityLevel(.c,BUFF_ID)>0 then
                if .scale<(DEFAULT_SCALE*MAX_SCALE_PERCENT)/100.+DEFAULT_SCALE then
                    set .scale=.scale+.01
                    call SetUnitScale(.c,.scale,.scale,.scale)
                endif
            else
                set .scale=.scale-.01
                call SetUnitScale(.c,.scale,.scale,.scale)
                if .scale<=DEFAULT_SCALE then
                    call SetUnitScale(.c,DEFAULT_SCALE,DEFAULT_SCALE,DEFAULT_SCALE)
                    set .c=null
                    call ReleaseTimer(t)
                endif
            endif
            set t=null
        endmethod
        
        static method filterGroup takes nothing returns boolean
            local player p=GetOwningPlayer(DamageEvent.source)
            set f=GetFilterUnit()
            return IsPlayerEnemy(GetOwningPlayer(f),p) and f!=DamageEvent.target and GetWidgetLife(f)>.405 and FilterConfig(f) and GetUnitTypeId(f)!=XE_DUMMY_UNITID and GetUnitAbilityLevel(f,'Aloc')==0
        endmethod

        static method filter takes nothing returns boolean
            local player p1=GetOwningPlayer(DamageEvent.target)
            local player p2=GetOwningPlayer(DamageEvent.source)
            return IsPlayerEnemy(p1,p2) and FilterConfig(DamageEvent.target) and GetUnitAbilityLevel(DamageEvent.source,BUFF_ID) > 0
        endmethod
        
        static method onDamage takes nothing returns nothing
            local unit c=DamageEvent.source
            local unit t=DamageEvent.target
            local player p=GetOwningPlayer(c)
            local real x=GetUnitX(c)
            local real y=GetUnitY(c)
            local unit d=CreateUnit(p,DUMMY_MISSILE_ID,x,y,0.)
            local integer lvl=GetUnitAbilityLevel(c,SPELL_ID)
            local real dmg=GetAttribute(c,GET_ATT_BONUS)+dmgLvl[lvl]
            local integer count=0
            local real z1
            local real z2
            local unit u

            call DestroyEffect(AddSpecialEffectTarget(EFECT_FX,c,"origin"))
            call TimerStart(NewTimerEx(GetUnitId(d)),.4,false,function thistype.recycleDummy)
            
            //! textmacro Claws takes VAR1,VAR2,VAR3,VAR4,REAL
            call MoveLocation(loc1,$VAR3$,$VAR4$)
            call MoveLocation(loc2,GetUnitX($VAR2$),GetUnitY($VAR2$))
            set z1=GetLocationZ(loc1)
            set z2=GetLocationZ(loc2)
            call DestroyEffect(AddSpecialEffectTarget(EFECT_FX,t,"origin"))
            call Lightning.unitToUnit($VAR1$,$VAR2$,z1+$REAL$,z2+20.,true,.3,LIGHTNING_EFECT,count)
            call UnitDamageTarget(d,$VAR2$,dmg,false,false,ATTACK_TYPE_HERO,DMG_TYPE,null)
            //! endtextmacro
            //! runtextmacro Claws("c","t","x","y","MAX_LIGHTNING_Z")
            
            call GroupEnumUnitsInArea(ENUM_GROUP,x,y,AoE,Filter(function thistype.filterGroup))
            
            loop
                exitwhen count==MAX_HITS-1
                set u=FirstOfGroup(ENUM_GROUP)
                call GroupRemoveUnit(ENUM_GROUP,u)
                if u!=null then
                    //! runtextmacro Claws("t","u","GetUnitX(t)","GetUnitY(t)","20.")
                    set t=u
                endif
                set count=count+1
            endloop
            
            set c=null
            set t=null
            set d=null
            set u=null
        endmethod
        implement DamageEvent

        static method onCast takes nothing returns nothing
            local unit u=GetTriggerUnit()
            local thistype this=GetUnitId(u)
            set .c=u
            call TimedEffect.createOnUnit(FX_ON_CAST,u,"origin",.5)
            if GetUnitAbilityLevel(.c,BUFF_ID)==0 then
                set .scale=DEFAULT_SCALE
                call TimerStart(NewTimerEx(this),.03125,true,function thistype.scaleLoop)
            endif
            call caster.castOnTarget(u)
            set u=null
        endmethod

        static method onInit takes nothing returns nothing
            call DamangeConfig()
            set caster=xecast.createBasic(DUMMY_SPELL_ID,OrderId(DUMMY_ORDER_STRING),Player(15))
            set caster.recycledelay=.1
            call RegisterSpellEffectEvent(SPELL_ID,function thistype.onCast)
        endmethod
    endstruct
endscope

Keywords:
wc3, volibear, league of legends, lol, hero, spellpack, spell, vjass.
Contents

Volibear spell pack v1.1 (Map)

Reviews
12th Dec 2015 IcemanBo: For long time as NeedsFix. Rejected. 17:38, 30th Jan 2015 Maker: Check my reply in this thread

Moderator

M

Moderator

12th Dec 2015
IcemanBo: For long time as NeedsFix. Rejected.

17:38, 30th Jan 2015
Maker: Check my reply in this thread
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
You should remove this. IsUnitGroupEmptyBJ
Use a counter to increase whenever a unit enters the group and decrease whenever a unit leaves the group. This will make it more efficient.

Since it is only a temp unit group you should check if the first unit in the group is null.
Like this.
JASS:
            set unitFromGroup = FirstOfGroup(ENUM_GROUP)
            if unitFromGroup != null then
                if .speed<.extTotal then
                    set .speed=.speed+.6
                    call SetUnitMoveSpeed(.c,.speed)
                endif
            endif

Also the ITEs can be combined to make it more efficient.

JASS:
            set unitFromGroup = FirstOfGroup(ENUM_GROUP)
            if unitFromGroup != null and .speed<.extTotal then
                set .speed=.speed+.6
                call SetUnitMoveSpeed(.c,.speed)
            endif
 
Level 9
Joined
Jun 21, 2012
Messages
432
Nice spells, person who I never knew before ;)

thanks my friend... :vw_love:

You should remove this. IsUnitGroupEmptyBJ
Use a counter to increase whenever a unit enters the group and decrease whenever a unit leaves the group. This will make it more efficient.

Since it is only a temp unit group you should check if the first unit in the group is null.
Like this.
JASS:
            set unitFromGroup = FirstOfGroup(ENUM_GROUP)
            if unitFromGroup != null then
                if .speed<.extTotal then
                    set .speed=.speed+.6
                    call SetUnitMoveSpeed(.c,.speed)
                endif
            endif

Also the ITEs can be combined to make it more efficient.

JASS:
            set unitFromGroup = FirstOfGroup(ENUM_GROUP)
            if unitFromGroup != null and .speed<.extTotal then
                set .speed=.speed+.6
                call SetUnitMoveSpeed(.c,.speed)
            endif


I'll take note :ogre_love:
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Review emerges!

★ Spell Review ★
[Review]
.....Reviewer: Dalvengyr
.....Contact me: ( Visitor Message / Private Message )
.....Date: 2014/Jan/16 - 19:32 GMT

[Overall]
.....Voted status: Awaiting update
.....Rating: 0/5 - Not rated
.....Personal comments:
Still unable to give comments. Remember that this is not a full review, I haven't reached the technical parts. Translate everything to English and I will try to review this again. :)

(Take note that optional points are not required to be fixed but could affect your final rating.)

[Details]

  • Code/trigger:
    • Said that KnockbackTools and xepreload are recommended (optional), not required. But I failed to compile your codes when I tried to remove those systems.
    • [ChosenOfTheStorm]
    • Add some short descriptions/documentations on those configuration variables and some parts of your codes for easier reviewing. And everything (code documentation, tooltips, etc.) should be in English.
    • (Optional)
      .03125 could be stored into a constant variable.
    • (Optional)
      private constant string DUMMY_ORDER_STRING = "innerfire
      Could be in integer instead. To avoid OrderId(DUMMY_ORDER_STRING)
    • (Optional)
      Attack/damage/weapon type of dealt damage could be added into configuration.
    • (Optional)
      JASS:
              private constant real       BUFF_DURATION      = 6.
              private constant real       SPELL_CD           = 120.
              private constant real       LIFE_SPEED_RATE    = 1.8
              private constant real       LIFE_PERCENT       = 30.
      Could probably support multi-level values.
  • Object data:
    • -
  • Import data:
    • -
  • Miscellaneous:
    • Documentations are required: short description of your spells, configuration instruction, credits, required libraries, user API, importing instructions, and code outlines.
    • Again, everything should be in English. It was hard to figure out what does your spell do without seeing it live on action and understanding the description/tooltips (due to used language).
 
Level 9
Joined
Jun 21, 2012
Messages
432
★ Spell Review ★
[Review]
.....Reviewer: Dalvengyr
.....Contact me: ( Visitor Message / Private Message )
.....Date: 2014/Jan/16 - 19:32 GMT

[Overall]
.....Voted status: Awaiting update
.....Rating: 0/5 - Not rated
.....Personal comments:
Still unable to give comments. Remember that this is not a full review, I haven't reached the technical parts. Translate everything to English and I will try to review this again. :)

(Take note that optional points are not required to be fixed but could affect your final rating.)

[Details]

  • Code/trigger:
    • Said that KnockbackTools and xepreload are recommended (optional), not required. But I failed to compile your codes when I tried to remove those systems.
    • [ChosenOfTheStorm]
    • Add some short descriptions/documentations on those configuration variables and some parts of your codes for easier reviewing. And everything (code documentation, tooltips, etc.) should be in English.
    • (Optional)
      .03125 could be stored into a constant variable.
    • (Optional)
      private constant string DUMMY_ORDER_STRING = "innerfire
      Could be in integer instead. To avoid OrderId(DUMMY_ORDER_STRING)
    • (Optional)
      Attack/damage/weapon type of dealt damage could be added into configuration.
    • (Optional)
      JASS:
              private constant real       BUFF_DURATION      = 6.
              private constant real       SPELL_CD           = 120.
              private constant real       LIFE_SPEED_RATE    = 1.8
              private constant real       LIFE_PERCENT       = 30.
      Could probably support multi-level values.
  • Object data:
    • -
  • Import data:
    • -
  • Miscellaneous:
    • Documentations are required: short description of your spells, configuration instruction, credits, required libraries, user API, importing instructions, and code outlines.
    • Again, everything should be in English. It was hard to figure out what does your spell do without seeing it live on action and understanding the description/tooltips (due to used language).

Update is coming
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
  • Write the tooltips in English
  • No need to null a periodic timer after each period
  • Is rolling thunder supposed to take the angle from target to caster? Not caster to target?
  • I've heard Pow is slow and multiplication to be faster
  • Don' use GetWidgetLife, use UNIT_TYPE_DEAD or declare native UnitAlive
  • Don't use IsUnitGroupEmptyBJ, it leaks and it is a lot slower than if FirstOfGroup(group) == null then
  • Frenesi does not look like to be MUI due to SetPlayerAbilityAvailable
  • The terrain deformation should be optional
  • Locust makes the dummies invulnerable, they do not need a separate invulnerability ability

 
Level 9
Joined
Jun 21, 2012
Messages
432
  • Write the tooltips in English
  • No need to null a periodic timer after each period
  • Is rolling thunder supposed to take the angle from target to caster? Not caster to target?
  • I've heard Pow is slow and multiplication to be faster
  • Don' use GetWidgetLife, use UNIT_TYPE_DEAD or declare native UnitAlive
  • Don't use IsUnitGroupEmptyBJ, it leaks and it is a lot slower than if FirstOfGroup(group) == null then
  • Frenesi does not look like to be MUI due to SetPlayerAbilityAvailable
  • The terrain deformation should be optional
  • Locust makes the dummies invulnerable, they do not need a separate invulnerability ability


Update coming soon :ogre_icwydt:
 
Top