[Log in / Register]
| News | Chat | Pastebin | Donations | Tutorials | Rules | Forums |
| Maps | Skins | Icons | Models | Spells | Tools | Jass | Packs | Hosted Projects | Starcraft II Modding | Starcraft II Resources | Galaxy Wiki |
(Keeps Hive Alive)
Go Back   The Hive Workshop > Spells


Reply
 
Thread Tools
The Hive Workshop Spells:
Warlock Spells 1.3.7
by Deaod
Images
Highslide JS
Details
Uploaded:23:58, 25th Aug 2009
Last Updated:09:47, 11th Nov 2009
Keywords:None
Type:Target Object, Pack
Category:vJASS

These are two spells I made for a spell contest at a german WC3 modding site.

The first spell, Meat Puppet, turns the target unit into a puppet to be flung around by the hero. When it collides with other units, those units take damage are knocked back.

The second spell, Null Blast ignores the time the unit would take to cast the spell because of its Cast Point. It instantly damages the target unit and weakens it (resulting in a decrease of maximum health). After the effects wear off a second blast is released which damages all surrounding units.

These two spells require/use:
- CurseBolt (model): http://www.wc3c.net/showthread.php?t=107151
- UnitMaxState: http://www.wc3c.net/showthread.php?t=107451
- TextTag: http://www.wc3c.net/showthread.php?t=101963
- GroupUtils: http://www.wc3c.net/showthread.php?t=104464
- UnitIndexingUtils: http://www.wc3c.net/showthread.php?t=101350
- LastOrder and AbortSpell: http://www.wc3c.net/showthread.php?t=104175
- Knockback: http://www.wc3c.net/showthread.php?t=99720
- TerrainPathability: http://www.wc3c.net/showthread.php?t=103862
- SpellEvent: http://www.wc3c.net/showthread.php?t=105374
- TimerUtils: http://www.wc3c.net/showthread.php?t=101322
- Table: http://www.wc3c.net/showthread.php?t=101246
- SimError: http://www.wc3c.net/showthread.php?t=101260
- xe: http://www.wc3c.net/showthread.php?t=101150
- DestructableLib: http://www.wc3c.net/showthread.php?t=103927

Credits
- Archmage Owenalacaster for all his valuable help and feedback
- WILL THE ALLMIGHTY for his CurseBolt model
- Earth-Fury for his UnitMaxState library
- cohadar for his TextTag library
- Rising_Dusk for his libraries: GroupUtils, UnitIndexingUtils, LastOrder, AbortSpell, Knockback and TerrainPathability
- Anitarf for his SpellEvent library
- Vexorian for JassHelper, TimerUtils, Table, SimError, xe and the dummy model
- PipeDream for Grimoire
- PitzerMike for JassNewGenPack and DestructableLib
- MindWorX for JassNewGenPack
- SFilip for TESH


Changelog
26/08/2009 - Version 1.2.3
- initial public release

27/08/2009 - Version 1.2.4
- removed the custom icon (itll still be in the submission).
- fixed a bug with Meat Puppet if the target was too close to the hero.

28/08/2009 - Version 1.3.0
- Both spells can now target friendly units (Null Blast has received an option whether to damage friendly units or not).
- Meat Puppet has received a Release Puppet sub-ability, which immediately breaks the connection.

28/08/2009 - Version 1.3.1
- made Release Puppet replace Meat Puppet when appropriate
- added an option to disable Release Puppet
- fixed the icon of Null Blast's Buff
- deleted a "\n" from SimError.

04/09/2009 - Version 1.3.2
- made the facing angle of the target unit be changed when swinging it around. This allows impressive chains (testedly).
- dropped the blinding function of Null Blast completely.
- changed the way Meat Puppet handles multiple instances on the same caster (from extended arrays to Table).

05/09/2009 - Version 1.3.3
- fixed a critical bug resulting in Meat Puppet not working at all (yay for releasing untested versions)

08/09/2009 - Version 1.3.4
- fixed a few theoretical bugs related to unlearning.
- added the option of reducing the max state by an amount relative to the current
- made several adjustments so Null Blast works with negative STAT_TAKEN amounts

11/09/2009 - Version 1.3.5
- updated to EFs new version of SetUnitMaxState

25/09/2009 - Version 1.3.6
- the meat puppet now lags slightly behind the casters movement.
- added several new options to both spells
- fixed Null Blast not working under certain conditions (mainly after importing into a new map).

11/11/2009 - Version 1.3.7
- Meat Puppet now works with flying units. Flying units will only knock back other flying units (and ground units will only knock back other ground units).
- Fixed a theoretical bug with Null Blast (in cases where buff and cooldown expire simultaneously and the EndCooldown function gets executed before the Callback function)


In-Game-Commands
- "-reset": spawns some footmen
- "-level <level>": Set the heros level to the level you specified. Note that you cannot decrease it that way.
- "-handleid": creates a location, displays its handlid-0x100001, and then destroys it.
- "-credits": displays credits
- "-commands": displays this list
- "-clear": removes all messages ingame


Meat Puppet
library MeatPuppet initializer Init uses LastOrder, GroupUtils, DestructableLib, SpellEvent, Table,/*
                                       */UnitIndexingUtils, AbortSpell, Knockback, TimerUtils

    private keyword Data // DO NOT CHANGE!

    globals
        private constant integer LEARN_AID = 'A006'
        private constant integer CAST_AID = 'A000'
        private constant integer BID = 'B000' // the buff placed by CAST_AID on the target unit.
        private constant real TICK = 1./32

        private constant integer RELEASE_AID = 'A005' // ability is based off of Berserk
        private constant integer RELEASE_BID = 'B002' // placed on caster by RELEASE_AID
        private constant boolean RELEASE_ALLOW = true // if true, RELEASE_AID gets added after casting the spell
        private constant boolean RELEASE_REPLACE_CAST_AID = true // if true and MAX_INSTANCES_PER_CASTER equals 1, CAST_AID gets removed before placing RELEASE_AID

        private constant string LIGHTNING_ID = "INIT" // Ordinary Lightning
        private constant real LIGHTNING_RED = 1.0
        private constant real LIGHTNING_GREEN = 0.2
        private constant real LIGHTNING_BLUE = 0.7
        private constant real LIGHTNING_ALPHA = 0.8 // put "0." in here if you dont want the lightning

        private constant string COLLISION_FX = "" // empty, but someone might want to use it
        private constant real COLLISION_AOE = 95.
        private real array COLLISION_DAMAGE // When the puppet hits an enemy unit, how much damage does the unit hit take
        private real array COLLISION_PUPPET_DAMAGE // When the puppet hits another unit, how much damage does the puppet take
        private constant boolean COLLISION_DAMAGE_FRIENDLY = false // should a friendly puppet take damage from colliding?
        private constant attacktype COLLISION_ATTACK_TYPE = ATTACK_TYPE_NORMAL
        private constant damagetype COLLISION_DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
        private constant weapontype COLLISION_SOUND = WEAPON_TYPE_METAL_MEDIUM_BASH
        private constant weapontype COLLISION_TREE_SOUND = WEAPON_TYPE_WOOD_MEDIUM_BASH
        private real array COLLISION_KB_DISTANCE // how far is the unit hit pushed back
        private real array COLLISION_KB_DURATION // for how long is the unit hit pushed back // values less than or equal to 0 disable knocking back
        private constant boolean KB_UNITS_KILL_TREES = true
        private constant boolean KB_UNITS_KNOCK_OTHERS = false
        private constant boolean KB_UNITS_CHAIN = false // should units knocked back by units knocked back by this spell be able to knock other units back // refer to the manual of Knockback for information

        private constant real MIN_RANGE = 200.
        private constant real MIN_RANGE_TIME = 0.25 // 0. or less is instant
        private constant real ANGLE_CHANGE_SPEED = 0.2 // from 0.0 to 1.0, please // closer to 0: longer time to sync with casters facing, closer to 1: less time to sync with casters facing (1 being instant syncing)
        private constant real DISTANCE_CHANGE_SPEED = 0.1 // from 0.0 to 1.0, please
        private constant integer MAX_INSTANCES_PER_CASTER = 1
        private constant string ERROR_TARGET_ALREADY_IN_INSTANCE = "Target already targeted by another instance of this spell!"
        private constant string ERROR_TOO_MANY_INSTANCES = "Too many instances of this spell for the caster!"
        private constant string ABILITY_HOTKEY = "T" // hotkey triggering AID
    endglobals

    // Damage
    private function SetUpCOLLISION_DAMAGE takes nothing returns nothing
        set COLLISION_DAMAGE[1]=125.
        set COLLISION_DAMAGE[2]=200.
        set COLLISION_DAMAGE[3]=300.
    endfunction

    private function Collision_Damage takes integer level returns real
        return COLLISION_DAMAGE[level]
    endfunction

    // Puppet Damage
    private function SetUpCOLLISION_PUPPET_DAMAGE takes nothing returns nothing
        set COLLISION_PUPPET_DAMAGE[1]=0.
        set COLLISION_PUPPET_DAMAGE[2]=0.
        set COLLISION_PUPPET_DAMAGE[3]=0.
    endfunction

    private function Collision_Puppet_Damage takes integer level returns real
        return COLLISION_PUPPET_DAMAGE[level]
    endfunction

    // Distance
    private function SetUpCOLLISION_KB_DISTANCE takes nothing returns nothing
        set COLLISION_KB_DISTANCE[1]=125.
        set COLLISION_KB_DISTANCE[2]=175.
        set COLLISION_KB_DISTANCE[3]=225.
    endfunction

    private function Collision_Kb_Distance takes integer level returns real
        return COLLISION_KB_DISTANCE[level]
    endfunction

    // Duration
    private function SetUpCOLLISION_KB_DURATION takes nothing returns nothing
        set COLLISION_KB_DURATION[1]=1.0
        set COLLISION_KB_DURATION[2]=1.2
        set COLLISION_KB_DURATION[3]=1.4
    endfunction

    private function Collision_Kb_Duration takes integer level returns real
        return COLLISION_KB_DURATION[level]
    endfunction

    // Validate Target
    private function ValidTarget takes unit u, Data s returns boolean
        return IsUnitType(u, UNIT_TYPE_DEAD)==false/*
            */ and IsUnitType(u, UNIT_TYPE_STRUCTURE)==false/*
            */ and IsUnitType(u, UNIT_TYPE_FLYING)==IsUnitType(s.t, UNIT_TYPE_FLYING)/*
            */ and IsUnitEnemy(u, GetOwningPlayer(s.caster))/*
            */ and (not IsKnockedBack(u))/*
            */ and u!=s.t/*
            */ and GetUnitMoveSpeed(u)>0/*
            */
    endfunction

    //

    private struct Data
        unit caster
        unit t // Target
        lightning l // Link
        integer level
        integer instanceofcaster
        real a // angleOffset
        real d // distanceOffset
        real dd // deltadistance // MIN_RANGE
        real tf // targets facing, relative
        real c // counter

        static Table InstanceOfCaster
        static integer array Instances
        static thistype array InstanceOfUnit // Linking Back, so instances dont conflict with each other
        static boolexpr Collision
        static boolexpr TreeFilter
        static thistype tmps
        static rect R
        static location LocZ=Location(0,0)

        private integer i

        private static thistype array Structs
        private static timer T=CreateTimer()
        private static integer Count=0

        static method GetLocZ takes real x, real y returns real
            call MoveLocation(.LocZ, x,y)
            return GetLocationZ(.LocZ)
        endmethod

        method onDestroy takes nothing returns nothing
        local integer id=GetUnitId(.caster)
            // Recycle instance of this caster properly
            set .Instances[id]=.Instances[id]-1
            set .InstanceOfCaster[id*MAX_INSTANCES_PER_CASTER+.instanceofcaster]=.InstanceOfCaster[id*MAX_INSTANCES_PER_CASTER+.Instances[id]]
            set thistype(.InstanceOfCaster[id*MAX_INSTANCES_PER_CASTER+.instanceofcaster]).instanceofcaster=.instanceofcaster
            call .InstanceOfCaster.flush(id*MAX_INSTANCES_PER_CASTER+.Instances[id])
            if RELEASE_ALLOW and .Instances[id]==0 then
                call UnitRemoveAbility(.caster, RELEASE_AID)
                if MAX_INSTANCES_PER_CASTER==1 and RELEASE_REPLACE_CAST_AID and GetUnitAbilityLevel(.caster, LEARN_AID)>0 then
                    call UnitAddAbility(.caster, CAST_AID)
                    call SetUnitAbilityLevel(.caster, CAST_AID, GetUnitAbilityLevel(.caster, LEARN_AID))
                    call UnitMakeAbilityPermanent(.caster, true, CAST_AID)
                endif
            endif
            // Normal cleanup
            set .InstanceOfUnit[GetUnitId(.t)]=0
            call SetUnitPosition(.t, GetUnitX(.t), GetUnitY(.t)) // avoid getting stuck
            call IssueLastOrder(.t) // avoid not carrying out the last order
            set .t=null
            set .caster=null
            call DestroyLightning(.l)
            set .l=null
            // clean your struct here
            set .Count=.Count-1
            set .Structs[.i]=.Structs[.Count]
            set .Structs[.i].i=.i
            if .Count==0 then
                call PauseTimer(.T)
            endif
        endmethod

        private static method CollisionFunc takes nothing returns boolean
        local unit u=GetFilterUnit()
        local real a
        local real v
            if ValidTarget(u, .tmps) then
                if UnitDamageTarget(.tmps.caster, u, Collision_Damage(.tmps.level), true, false, COLLISION_ATTACK_TYPE, COLLISION_DAMAGE_TYPE, COLLISION_SOUND) then // should the unit for some reason be immune to damage, dont continue
                    if COLLISION_DAMAGE_FRIENDLY or IsUnitEnemy(.tmps.t, GetOwningPlayer(.tmps.caster)) then
                        call UnitDamageTarget(.tmps.caster, .tmps.t, Collision_Puppet_Damage(.tmps.level), true, false, COLLISION_ATTACK_TYPE, COLLISION_DAMAGE_TYPE, null) // sound has already been played
                    endif
                    call DestroyEffect(AddSpecialEffect(COLLISION_FX, GetUnitX(.tmps.t), GetUnitY(.tmps.t)))
                    if Collision_Kb_Duration(.tmps.level)>0 then // if the user doesnt want the units hit to be knocked back, dont do it
                        set a=(2*Collision_Kb_Distance(.tmps.level))/(Collision_Kb_Duration(.tmps.level)*Collision_Kb_Duration(.tmps.level)) // s=a/2*t^2 --> a=2*s/(t^2)
                        set v=a*Collision_Kb_Duration(.tmps.level) // v=a*t
                        call KnockbackTarget(.tmps.caster, u, Atan2(GetUnitY(u)-GetUnitY(.tmps.t), GetUnitX(u)-GetUnitX(.tmps.t))*bj_RADTODEG, v, a, KB_UNITS_KILL_TREES, KB_UNITS_KNOCK_OTHERS, KB_UNITS_CHAIN)
                    endif
                endif
            endif
            set u=null
            return false
        endmethod

        private static method TreeFilterFunc takes nothing returns boolean
        local destructable d=GetFilterDestructable()
        local real dx=GetWidgetX(d)-GetUnitX(.tmps.t)
        local real dy=GetWidgetY(d)-GetUnitY(.tmps.t)
            if (not IsDestructableDead(d)) and IsDestructableTree(d) and (dx*dx+dy*dy<=COLLISION_AOE*COLLISION_AOE) then
                if COLLISION_DAMAGE_FRIENDLY or IsUnitEnemy(.tmps.t, GetOwningPlayer(.tmps.caster)) then
                    call UnitDamageTarget(.tmps.caster, .tmps.t, Collision_Puppet_Damage(.tmps.level), true, false, COLLISION_ATTACK_TYPE, COLLISION_DAMAGE_TYPE, COLLISION_TREE_SOUND)
                endif
                call KillDestructable(d)
            endif
            set d=null
            return false
        endmethod

        private static method Callback takes nothing returns nothing
        local integer i=.Count-1
        local thistype s
        local real a
        local real x
        local real y
        local real dx
        local real dy
        local real r
            loop
                exitwhen i<0
                set s=.Structs[i]
                if GetUnitAbilityLevel(s.t, BID)==0 or IsUnitType(s.caster, UNIT_TYPE_DEAD)==true then
                    call s.destroy()
                endif
                if s.d<MIN_RANGE then // move the unit to MIN_RANGE
                    set s.d=s.d+s.dd/MIN_RANGE_TIME*TICK
                endif
                set x=GetUnitX(s.caster)
                set y=GetUnitY(s.caster)
                set dx=GetUnitX(s.t)-x
                set dy=GetUnitY(s.t)-y
                set r=Atan2(dy, dx) // current angle from caster to target
                if r<0 then // map the angle from -Pi..Pi to 0..2*Pi
                    set r=2*bj_PI+r
                endif
                set a=ModuloReal(((GetUnitFacing(s.caster)*bj_DEGTORAD+s.a)-r), 2*bj_PI) // calculate the difference between current angle between caster and target and the current facing of the caster
                if a>bj_PI then // map the delta angle from 0..2*Pi to -Pi..Pi
                    set a=-2*bj_PI+a
                endif
                set a=r+a*ANGLE_CHANGE_SPEED // calculate the new angle in which the target if offset from the caster
                set r=SquareRoot(dx*dx+dy*dy) // calculate the distance between caster and target
                set r=r+(s.d-r)*DISTANCE_CHANGE_SPEED // calculate the new distance the target is offset from the caster
                set x=Cos(a)*r+x
                set y=Sin(a)*r+y
                call SetUnitX(s.t, x)
                call SetUnitY(s.t, y)
                call SetUnitFacing(s.t, GetUnitFacing(s.caster)+s.tf)
                call MoveLightningEx(s.l, true, GetUnitX(s.caster), GetUnitY(s.caster), .GetLocZ(GetUnitX(s.caster), GetUnitY(s.caster))+GetUnitFlyHeight(s.caster), x, y, .GetLocZ(x, y)+GetUnitFlyHeight(s.t))
                set .tmps=s
                call GroupEnumUnitsInRange(ENUM_GROUP, x,y, COLLISION_AOE, .Collision)
                call MoveRectTo(.R, x,y)
                call EnumDestructablesInRect(.R, .TreeFilter, null)
                // do your things here, dont forget to call s.destroy() somewhen
                //
                set i=i-1
            endloop
        endmethod

        private static method PlaceRelease takes nothing returns nothing
        local thistype s=thistype(GetTimerData(GetExpiredTimer()))
            if MAX_INSTANCES_PER_CASTER==1 and RELEASE_REPLACE_CAST_AID then
                call UnitRemoveAbility(s.caster, CAST_AID)
            endif
            call UnitAddAbility(s.caster, RELEASE_AID)
            call UnitMakeAbilityPermanent(s.caster, true, RELEASE_AID)
            call ReleaseTimer(GetExpiredTimer())
        endmethod

        static method create takes nothing returns thistype
        local thistype s=.allocate()
        local real dx
        local real dy
        local real r
        local integer id
        local timer t
            // Populate the struct
            set s.caster=SpellEvent.CastingUnit
            set s.t=SpellEvent.TargetUnit
            set .InstanceOfUnit[GetUnitId(s.t)]=s
            set s.level=GetUnitAbilityLevel(s.caster, CAST_AID)
            // SetUp the relative position
            set dx=GetUnitX(s.t)-GetUnitX(s.caster)
            set dy=GetUnitY(s.t)-GetUnitY(s.caster)
            set r=Atan2(dy, dx)
            if r<0 then
                set r=2*bj_PI+r
            endif
            set s.a=r-GetUnitFacing(s.caster)*bj_DEGTORAD
            set s.d=SquareRoot(dx*dx+dy*dy)
            if s.d<MIN_RANGE then
                set s.dd=MIN_RANGE-s.d
                if MIN_RANGE_TIME<=0 then
                    set s.d=MIN_RANGE
                endif
            endif
            set s.tf=GetUnitFacing(s.t)-GetUnitFacing(s.caster)
            // SetUp the lightning
            set s.l=AddLightningEx(LIGHTNING_ID, true, GetUnitX(s.caster), GetUnitY(s.caster), .GetLocZ(GetUnitX(s.caster), GetUnitY(s.caster))+GetUnitFlyHeight(s.caster), GetUnitX(s.t), GetUnitY(s.t), .GetLocZ(GetUnitX(s.t), GetUnitY(s.t))+GetUnitFlyHeight(s.t))
            call SetLightningColor(s.l, LIGHTNING_RED, LIGHTNING_GREEN, LIGHTNING_BLUE, LIGHTNING_ALPHA)

            set id=GetUnitId(s.caster)
            set .InstanceOfCaster[id*MAX_INSTANCES_PER_CASTER+.Instances[id]]=s
            set s.instanceofcaster=.Instances[id]
            if RELEASE_ALLOW and .Instances[id]==0 then
                set t=NewTimer()
                call SetTimerData(t, s)
                call TimerStart(t, 0, false, function thistype.PlaceRelease)
            endif
            set .Instances[id]=.Instances[id]+1

            // initialize the struct here
            set .Structs[.Count]=s
            set s.i=.Count
            if .Count==0 then
                call TimerStart(.T, TICK, true, function thistype.Callback)
            endif
            set .Count=.Count+1
            return s
        endmethod

        private static method onInit takes nothing returns nothing
            set .InstanceOfCaster=Table.create()
            set .Collision=Condition(function thistype.CollisionFunc)
            set .TreeFilter=Condition(function thistype.TreeFilterFunc)
            set .R=Rect(-COLLISION_AOE, -COLLISION_AOE, COLLISION_AOE, COLLISION_AOE)
            if MAX_INSTANCES_PER_CASTER<=0 then
                call BJDebugMsg(SCOPE_PREFIX+": MAX_INSTANCES_PER_CASTER is too low (<=0)!")
            endif
            if ANGLE_CHANGE_SPEED<=0 then
                call BJDebugMsg(SCOPE_PREFIX+": ANGLE_CHANGE_SPEED is too low (<=0)!")
            elseif ANGLE_CHANGE_SPEED>1 then
                call BJDebugMsg(SCOPE_PREFIX+": ANGLE_CHANGE_SPEED is too high (>1)!")
            endif
            if DISTANCE_CHANGE_SPEED<=0 then
                call BJDebugMsg(SCOPE_PREFIX+": DISTANCE_CHANGE_SPEED is too low (<=0)!")
            elseif DISTANCE_CHANGE_SPEED>1 then
                call BJDebugMsg(SCOPE_PREFIX+": DISTANCE_CHANGE_SPEED is too high (>1)!")
            endif
            //
            call SetUpCOLLISION_DAMAGE()
            call SetUpCOLLISION_PUPPET_DAMAGE()
            call SetUpCOLLISION_KB_DISTANCE()
            call SetUpCOLLISION_KB_DURATION()
        endmethod
    endstruct

    private function CreateProxy takes nothing returns nothing
        call Data.create()
    endfunction

    private function CheckValidTarget takes nothing returns nothing
        if Data.InstanceOfUnit[GetUnitId(SpellEvent.TargetUnit)]!=0 then
            call AbortSpell(SpellEvent.CastingUnit, "\n"+ERROR_TARGET_ALREADY_IN_INSTANCE, ABILITY_HOTKEY)
        endif
        if Data.Instances[GetUnitId(SpellEvent.CastingUnit)]>=MAX_INSTANCES_PER_CASTER then
            call AbortSpell(SpellEvent.CastingUnit, "\n"+ERROR_TOO_MANY_INSTANCES, ABILITY_HOTKEY)
        endif
    endfunction

    private function Release takes nothing returns nothing
    local integer id=GetUnitId(SpellEvent.CastingUnit)
        call UnitRemoveAbility(SpellEvent.CastingUnit, RELEASE_BID)
        call UnitRemoveAbility(Data(Data.InstanceOfCaster[id*MAX_INSTANCES_PER_CASTER+Data.Instances[id]-1]).t, BID)
    endfunction

    globals
        private integer array LearnedAbilityLevel
    endglobals

    private function IsLearnAbility takes nothing returns boolean
        return GetLearnedSkill()==LEARN_AID
    endfunction

    private function Learning takes nothing returns nothing
    local unit u=GetLearningUnit()
        if GetLearnedSkillLevel()==1 then
            call UnitAddAbility(u, CAST_AID)
            call UnitMakeAbilityPermanent(u, true, CAST_AID)
        endif
        if not(RELEASE_REPLACE_CAST_AID and MAX_INSTANCES_PER_CASTER==1 and Data.Instances[GetUnitId(u)]==1) then
            call SetUnitAbilityLevel(u, CAST_AID, GetLearnedSkillLevel())
        endif
        set LearnedAbilityLevel[GetUnitId(u)]=GetLearnedSkillLevel()
        set u=null
    endfunction

    private function UnlearnedAbility takes nothing returns boolean
        return GetUnitAbilityLevel(GetTriggerUnit(), LEARN_AID)!=LearnedAbilityLevel[GetUnitId(GetTriggerUnit())]
    endfunction

    private function ResetAbility takes nothing returns nothing
        call UnitRemoveAbility(GetTriggerUnit(), CAST_AID)
    endfunction

    private function Init takes nothing returns nothing
    local trigger t=CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_HERO_SKILL)
        call TriggerAddCondition(t, Condition(function IsLearnAbility))
        call TriggerAddAction(t, function Learning)

        set t=CreateTrigger() // just in case someone uses that damn tome of relearning // untested code
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM)
        call TriggerAddCondition(t, Condition(function UnlearnedAbility))
        call TriggerAddAction(t, function ResetAbility)


        call RegisterSpellEffectResponse(CAST_AID, CreateProxy)
        call RegisterSpellCastResponse(CAST_AID, CheckValidTarget)

        call RegisterSpellEffectResponse(RELEASE_AID, Release)
    endfunction

endlibrary

Null Blast
library NullBlast initializer Init uses LastOrder, SpellEvent, UnitIndexingUtils, UnitMaxState,/*
                                     */ TimerUtils, xecast, xepreload, TextTag

    // This spell ignores the time the hero takes to reach the cast point.
    // Achieving this without potentially breaking, requires some more sophisticated work,
    // since players could potentially abort the casting of the ability after SPELL_CAST has been reached.

    private keyword Data // DO NOT CHANGE!

    globals
        private constant real TICK = 1./32 // interval to check for the buff BLINDNESS_DUMMY_BID

        private constant integer LEARN_AID = 'A001' // Dummy Ability for learning interface
        private constant integer CAST_AID = 'A002' // Dummy Ability for casting only
        private constant integer DUMMY_AID = 'A003' // the mana cost of CAST_AID and DUMMY_AID must match // dummy ability for mana cost and cooldown
        private constant string DUMMY_ORDER = "berserk"
        private constant integer DUMMY_BID = 'B002' // placed by DUMMY_AID on the caster

        private constant integer BLINDNESS_DUMMY_AID = 'A004' // changes duration of spell and % to miss
        private constant string BLINDNESS_DUMMY_ORDER = "curse"
        private constant integer BLINDNESS_DUMMY_BID = 'B001' // placed by BLINDNESS_DUMMY_AID on the target unit

        private constant string FX = "war3mapImported\\CurseBolt.mdx" // blast effect
        private constant string FX_ATTPT = "head"
        private real array COOLDOWN // must match the cooldown time given in DUMMY_AID
        private real array DAMAGE // damage dealt by the primary blast
        private real array SECONDARY_DAMAGE // damage dealt by the secondary blast
        private constant real SECONDARY_DAMAGE_AOE = 192. // units in this area around the target get damaged when the spell ends
        private constant boolean DAMAGE_FRIENDLY_UNITS = false
        private constant boolean DEBUFF_FRIENDLY_UNITS = true
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_MAGIC
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
        private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS // sound effect when damaging
        private constant weapontype SECONDARY_WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS // sound effect when damaging through second blast
        private real array STAT_TAKEN // max hp or max mana taken away for a period of time by this ability // values less than 1 turn this into a relative loss instead of an absolute
        private constant unitstate STAT_MODIFIED = UNIT_STATE_MAX_LIFE // either UNIT_STATE_MAX_LIFE or UNIT_STATE_MAX_MANA
        private constant boolean SHOW_TT = true // should a texttag be shown
        private constant string TT_PATTERN = "&d HP!" // place "&d" where the amount taken away should be (case insensitive)
        private constant string TT_NEGATIVE_HP_BONUS_STRING = "-"
        private constant string TT_POSITIVE_HP_BONUS_STRING = "+"
        private constant string TT_COLOR = "|cffA00030" // color of the text in the texttag; standard WC3 formatting (|cAARRGGBB)
    endglobals

    // Cooldown
    private function SetUpCOOLDOWN takes nothing returns nothing
        set COOLDOWN[1]=10.
        set COOLDOWN[2]=10.
        set COOLDOWN[3]=10.
    endfunction

    private function Cooldown takes integer level returns real
        return COOLDOWN[level]
    endfunction

    // Damage
    private function SetUpDAMAGE takes nothing returns nothing
        set DAMAGE[1]=150.
        set DAMAGE[2]=200.
        set DAMAGE[3]=250.
    endfunction

    private function Damage takes integer level returns real
        return DAMAGE[level]
    endfunction

    // Secondary Damage
    private function SetUpSECONDARY_DAMAGE takes nothing returns nothing
        set SECONDARY_DAMAGE[1]=100.
        set SECONDARY_DAMAGE[2]=125.
        set SECONDARY_DAMAGE[3]=150.
    endfunction

    private function Secondary_Damage takes integer level returns real
        return SECONDARY_DAMAGE[level]
    endfunction

    // HP Taken
    private function SetUpSTAT_TAKEN takes nothing returns nothing
        set STAT_TAKEN[1]=150.
        set STAT_TAKEN[2]=200.
        set STAT_TAKEN[3]=250.
    endfunction

    private function Stat_Taken takes integer level returns real
        return STAT_TAKEN[level]
    endfunction

    // Validate Target
    private function ValidTarget takes unit u, Data s returns boolean
        return IsUnitType(u, UNIT_TYPE_DEAD)==false/*
            */ and IsUnitType(u, UNIT_TYPE_STRUCTURE)==false/*
            */ and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)==false/*
            */ and (DAMAGE_FRIENDLY_UNITS or IsUnitEnemy(u, GetOwningPlayer(s.caster)))/*
            */ and s.target!=u/*
            */
    endfunction

    //

    globals
        private integer PatternLength=StringLength(TT_PATTERN)
    endglobals

    private struct Data
        unit caster
        unit target
        timer t
        integer level
        real hptaken
        boolean cooldown=true
        boolean inloop=true

        static boolean array CooldownActive
        static xecast BlindnessDummy

        static boolexpr DamageFilter
        static thistype tmps

        private integer i

        private static thistype array Structs
        private static timer T=CreateTimer()
        private static integer Count=0

        private method onDestroy takes nothing returns nothing
            set .target=null
            set .caster=null
            set .t=null
        endmethod

        private method RemoveFromLoop takes nothing returns nothing
            if not .cooldown then
                call .destroy()
            endif
            // clean your struct here
            set .Count=.Count-1
            set .Structs[.i]=.Structs[.Count]
            set .Structs[.i].i=.i
            if .Count==0 then
                call PauseTimer(.T)
            endif
            set .inloop=false
        endmethod

        private static method EndCooldown takes nothing returns nothing
        local thistype s=thistype(GetTimerData(GetExpiredTimer()))
            // switch from dummy ability to casting ability
            if GetUnitAbilityLevel(s.caster, LEARN_AID)>0 then
                call UnitRemoveAbility(s.caster, DUMMY_AID)
                call UnitAddAbility(s.caster, CAST_AID)
                call UnitMakeAbilityPermanent(s.caster, true, CAST_AID) // to avoid removal through morphing abilities
                call SetUnitAbilityLevel(s.caster, CAST_AID, GetUnitAbilityLevel(s.caster, LEARN_AID))
            endif
            call ReleaseTimer(s.t) // clean up
            set .CooldownActive[GetUnitId(s.caster)]=false // mark the caster as "not in cooldown"
            set s.cooldown=false
            if GetUnitAbilityLevel(s.target, BLINDNESS_DUMMY_BID)==0 and (not s.inloop) then
                call s.destroy() // if the cooldown is longer than the buff lasts, destroy this instance
            endif
        endmethod

        private static method DamageFilterFunc takes nothing returns boolean
        local unit u=GetFilterUnit()
            if ValidTarget(u, .tmps) then
                call UnitDamageTarget(.tmps.caster, u, Secondary_Damage(.tmps.level), true, false, ATTACK_TYPE, DAMAGE_TYPE, SECONDARY_WEAPON_TYPE)
            endif
            set u=null
            return false
        endmethod

        private static method Callback takes nothing returns nothing
        local integer i=.Count-1
        local thistype s
            loop
                exitwhen i<0
                set s=.Structs[i]
                if GetUnitAbilityLevel(s.target, BLINDNESS_DUMMY_BID)==0 then
                    //buff got removed/expired
                    set .tmps=s
                    call GroupEnumUnitsInRange(ENUM_GROUP, GetUnitX(s.target), GetUnitY(s.target), SECONDARY_DAMAGE_AOE, .DamageFilter)
                    call AddUnitMaxState(s.target, STAT_MODIFIED, s.hptaken)
                    call s.RemoveFromLoop() // if the buff lasts longer than the cooldown, destroy the instance
                endif
                // do your things here, dont forget to call s.destroy() somewhen
                //
                set i=i-1
            endloop
        endmethod

        static method create takes nothing returns thistype
        local thistype s=.allocate()
        local integer i=0
        local string str=""

            set s.t=NewTimer()
            set s.caster=SpellEvent.CastingUnit
            set s.target=SpellEvent.TargetUnit
            set s.level=GetUnitAbilityLevel(s.caster, LEARN_AID)
            call AbortOrder(s.caster) // cancel the spell before it goes into cooldown and costs mana
            // apply the blindness
            set .BlindnessDummy.level=s.level
            //set .BlindnessDummy.owningplayer=GetOwningPlayer(s.caster) // comment out this line to allow targeting friendly units
            call .BlindnessDummy.castOnTarget(s.target)
            // some nice FX
            call DestroyEffect(AddSpecialEffectTarget(FX, s.target, FX_ATTPT))
            if DAMAGE_FRIENDLY_UNITS or IsUnitEnemy(s.target, GetOwningPlayer(s.caster)) then
                call UnitDamageTarget(s.caster, s.target, Damage(s.level), true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE) // damage the target
            endif
            // switch from casting ability to dummy ability
            call UnitRemoveAbility(s.caster, CAST_AID)
            call UnitAddAbility(s.caster, DUMMY_AID)
            call UnitMakeAbilityPermanent(s.caster, true, DUMMY_AID)
            call SetUnitAbilityLevel(s.caster, DUMMY_AID, s.level)
            call IssueImmediateOrder(s.caster, DUMMY_ORDER) // apply mana cost and cooldown
            call UnitRemoveAbility(s.caster, DUMMY_BID) // remove the buff placed by DUMMY_AID
            set .CooldownActive[GetUnitId(s.caster)]=true
            call SetTimerData(s.t, s)
            call TimerStart(s.t, Cooldown(s.level), false, function thistype.EndCooldown)
            if DEBUFF_FRIENDLY_UNITS or IsUnitEnemy(s.target, GetOwningPlayer(s.caster)) then
                if Stat_Taken(s.level)>=1. or Stat_Taken(s.level)<=-1. then // absolute max hp loss
                    if GetUnitState(s.target, STAT_MODIFIED)<=Stat_Taken(s.level) then
                        // if the current max hp of the target are smaller than the amount taken away
                        // Reduce the amount taken away so that it leaves the unit with exactly 1 max hp.
                        set s.hptaken=GetUnitState(s.target, STAT_MODIFIED)-1 // store the amount taken away
                        call SetUnitMaxState(s.target, STAT_MODIFIED, 1)
                    else
                        set s.hptaken=Stat_Taken(s.level) // store the amount taken away
                        call AddUnitMaxState(s.target, STAT_MODIFIED, -Stat_Taken(s.level))
                    endif
                else // relative max hp loss
                    if GetUnitState(s.target, STAT_MODIFIED)*(1.-Stat_Taken(s.level))<1. then
                        set s.hptaken=GetUnitState(s.target, STAT_MODIFIED)-1 // store the amount taken away
                        call SetUnitMaxState(s.target, STAT_MODIFIED, 1)
                    else
                        set s.hptaken=Stat_Taken(s.level)*GetUnitState(s.target, STAT_MODIFIED)
                        call AddUnitMaxState(s.target, STAT_MODIFIED, -s.hptaken)
                    endif
                endif
            endif

            if SHOW_TT and s.hptaken!=0. then
                loop
                    exitwhen i>=PatternLength
                    if SubString(TT_PATTERN, i, i+1)=="&" and i+1<PatternLength then
                        if SubString(TT_PATTERN, i+1, i+2)=="d" or SubString(TT_PATTERN, i+1, i+2)=="D" then
                            if s.hptaken<0. then
                                set str=str+TT_POSITIVE_HP_BONUS_STRING
                            else
                                set str=str+TT_NEGATIVE_HP_BONUS_STRING
                            endif
                            set str=str+I2S(R2I(RAbsBJ(s.hptaken)))
                            set i=i+1
                        else
                            set str=str+"&"
                        endif
                    else
                        set str=str+SubString(TT_PATTERN, i, i+1)
                    endif
                    set i=i+1
                endloop
                call TextTag_Unit(s.target, str, TT_COLOR)
            endif

            // initialize the struct here
            set .Structs[.Count]=s
            set s.i=.Count
            if .Count==0 then
                call TimerStart(.T, TICK, true, function thistype.Callback)
            endif
            set .Count=.Count+1
            return s
        endmethod

        private static method onInit takes nothing returns nothing
            set .BlindnessDummy=xecast.create()
            set .BlindnessDummy.abilityid=BLINDNESS_DUMMY_AID
            set .BlindnessDummy.orderstring=BLINDNESS_DUMMY_ORDER
            set .BlindnessDummy.recycledelay=1.0

            set .DamageFilter=Condition(function thistype.DamageFilterFunc)

            call Preload(FX)
            call PreloadStart()
            call XE_PreloadAbility(CAST_AID)
            call XE_PreloadAbility(DUMMY_AID)
            call XE_PreloadAbility(BLINDNESS_DUMMY_AID)

            call SetUpCOOLDOWN()
            call SetUpDAMAGE()
            call SetUpSECONDARY_DAMAGE()
            call SetUpSTAT_TAKEN()
        endmethod
    endstruct

    private function Cast takes nothing returns nothing
        call Data.create()
    endfunction

    globals
        private integer array LearnedAbilityLevel
    endglobals

    private function IsLearnAbility takes nothing returns boolean
        return GetLearnedSkill()==LEARN_AID
    endfunction

    private function Learning takes nothing returns nothing
    local unit u=GetLearningUnit()
        if GetLearnedSkillLevel()==1 then
            call UnitAddAbility(u, CAST_AID)
            call UnitMakeAbilityPermanent(u, true, CAST_AID)
        endif
        if Data.CooldownActive[GetUnitId(u)] then
            call SetUnitAbilityLevel(u, DUMMY_AID, GetLearnedSkillLevel())
        else
            call SetUnitAbilityLevel(u, CAST_AID, GetLearnedSkillLevel())
        endif
        set LearnedAbilityLevel[GetUnitId(u)]=GetLearnedSkillLevel()
        set u=null
    endfunction

    private function UnlearnedAbility takes nothing returns boolean
        return GetUnitAbilityLevel(GetTriggerUnit(), LEARN_AID)!=LearnedAbilityLevel[GetUnitId(GetTriggerUnit())]
    endfunction

    private function ResetAbility takes nothing returns nothing
        call UnitRemoveAbility(GetTriggerUnit(), CAST_AID)
        call UnitRemoveAbility(GetTriggerUnit(), DUMMY_AID)
    endfunction

    private function Init takes nothing returns nothing
    local trigger t=CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_HERO_SKILL)
        call TriggerAddCondition(t, Condition(function IsLearnAbility))
        call TriggerAddAction(t, function Learning)

        set t=CreateTrigger() // just in case someone uses that damn tome of relearning // untested code
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM)
        call TriggerAddCondition(t, Condition(function UnlearnedAbility))
        call TriggerAddAction(t, function ResetAbility)

        call RegisterSpellCastResponse(CAST_AID, Cast) // why trigger on cast? --
        // well, when using SPELL_EFFECT the hero can be interrupted before actually
        // reaching the Cast Point (where SPELL_EFFECT is triggered).
        // This spell ignores the time the hero takes to reach the cast point.
    endfunction

endlibrary
Rating - 5.00 (1 vote)
(Hover and click)
Moderator Comments
Highly Recommended
21:06, 29th Aug 2009
hvo-busterkomo: My only complaint (opinion, meh) is that Null Blast tried to produce too many effects. Anyways, the spells are great, approved.

This spell is approved and works properly.


Download Warlock_Spells_1.3.7.w3x
(126.19 KB, 1839 Downloads)

Old 08-26-2009, 02:09 AM   #2 (permalink)
Registered User Devalut
No machine spirits! nooo!
 
Devalut's Avatar
 
Join Date: Feb 2009
Posts: 276
Devalut has little to show at this moment (13)Devalut has little to show at this moment (13)
0/5
cant test it no countering units or hero's in the map
thus Fail
Devalut is offline   Reply With Quote
Old 08-26-2009, 02:21 AM   #3 (permalink)
Registered User Deaod
GUI sucks. Don't use it.
 
Join Date: Nov 2007
Posts: 854
Deaod has disabled reputation
ah, but you DO see the messages at the beginning, right?

and the hidden box titled In-Game-Commands isnt too hard to miss either.
Deaod is offline   Reply With Quote
Old 08-26-2009, 03:06 AM   #4 (permalink)
Registered User busterkomo
 
busterkomo's Avatar
 
Join Date: Jun 2007
Posts: 1,474
busterkomo is just really nice (295)busterkomo is just really nice (295)busterkomo is just really nice (295)busterkomo is just really nice (295)busterkomo is just really nice (295)
I'll give these spells a full review tommorow but I'll just say this; if you're aiming at maximum modularity then you might want to use TimedLoop.
busterkomo is offline   Reply With Quote
Old 08-26-2009, 05:26 AM   #5 (permalink)
Registered User Deaod
GUI sucks. Don't use it.
 
Join Date: Nov 2007
Posts: 854
Deaod has disabled reputation
No, thanks. TimedLoop couldnt be used in Null Blast (since instances of Null Blast might go on without being added to the looping). And using TimedLoop might make the looping slower than using, say KeyTimers2 + attaching. Also, TimedLoop doesnt allow the interval to be changed on a per-implementation basis (which might be necessary in bigger maps).
Deaod is offline   Reply With Quote
Old 08-26-2009, 06:18 AM   #6 (permalink)
Registered User Devalut
No machine spirits! nooo!
 
Devalut's Avatar
 
Join Date: Feb 2009
Posts: 276
Devalut has little to show at this moment (13)Devalut has little to show at this moment (13)
Quote:
Originally Posted by Deaod View Post
ah, but you DO see the messages at the beginning, right?

and the hidden box titled In-Game-Commands isnt too hard to miss either.

oh I'm sorry, maybe you should put in your "Hidden box" READ BEFORE PLAYING
and maybe it might not be so hard to miss and unless theres command in that "Hidden" Box of your's that says Spawn hero then there's no hero so....... yeah.
Devalut is offline   Reply With Quote
Old 08-26-2009, 08:53 AM   #7 (permalink)
Registered User Deuterium
-
 
Deuterium's Avatar
 
Join Date: Mar 2009
Posts: 1,981
Deuterium is a name known to all (669)Deuterium is a name known to all (669)Deuterium is a name known to all (669)
Hehe wow that's alot of systems :P good job on the spells...
Yet, imports could be avoided you know ;) just gotta use the creative part of your brain :P
__________________
Deuterium is offline   Reply With Quote
Old 08-26-2009, 11:24 AM   #8 (permalink)
Registered User Dark_Dragon
Behind the shadow...
 
Dark_Dragon's Avatar
 
Join Date: Jul 2007
Posts: 761
Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)
well nice spells Deaod!

they are quite readable and easy editable, but in my option the both spells core should have some more comments...

using nice amount of librarys, now i know what did you mean back then and yeah its nice and modular way so gj on that.

Quote:
Originally Posted by hvo-busterkomo View Post
I'll give these spells a full review tommorow but I'll just say this; if you're aiming at maximum modularity then you might want to use TimedLoop.
we should as well know that one line in vjass can be a far more lines in jass as well as adding extra objects and taking handle id-s! TimedLoop is actually quite slow, even loops by blizzard are extremely slow, the only loops which are fast are ForGroup and such, all this custom functions, loops and stuff in VM are really slow... and slowing them even more is really an bad idea (thats in my option)

now few things i would chage in this spells are (not needed but would make em little bit more faster):

insted of having multiple init global array variable functions... i would just make once Setup function and would set all init array variables there, as well as write few comments, then on your init function just call that setup one... well its coz functions take RAM but as i said its crazy so its not needed to chage...

i would avoid using functions like:

Jass:
call RegisterSpellEffectResponse(AID, CreateProxy)
        call RegisterSpellCastResponse(AID, CheckValidTarget)

this are converted as pointer functions and they take 4 handle id-s (each pointer function takes 4 ids)

1-trigger
2-triggeraction
3-triggercondition
4-conditionfunc

well thats bad coz many systems use GetHandleId(h)-MIN_H_ID and that can pass JASS_MAX_ARRAY_SIZE (8191)... we should know that many maps have a lot of trees and / or destructbales of any type... each destructable takes one id! as well as maps which have a lot of units like footman frenzy... i mean this

well units take id as long as they are in game... even if they are dead.

as well calling pointer functions is much slower then calling "already slow VM functions"
as well pointer functions take extra RAM coz they require extra VM functions + global variables which are basically arguments... in your case you have no arguments, so i skip this.


when assigning value to real or comparing...
Jass:
local real x = 0 //bad
local real x = 0. //good
local real x = .0//good

i found that my scripts crashed coz i did not do that! it happend two times in my life, quite rare but true...

Rating:
Creativity: 4/5
Documentation: 3/5
Coding: 4.5/5
MUI: true
Editable: 4.5/5
Externals: +Extra points

Overall: 5/5

once again gj on spells!
~DD
__________________
My Ultimate Spell Pack
Dark_Dragon is offline   Reply With Quote
Old 08-26-2009, 01:04 PM   #9 (permalink)
Registered User Deaod
GUI sucks. Don't use it.
 
Join Date: Nov 2007
Posts: 854
Deaod has disabled reputation
Quote:
i would avoid using functions like:
I wouldnt, since the alternative would consume even more handleids (creating a trigger with condition and action plus events). And i wouldnt have the speed advantage of using an event stack.

My thinking with the Array initializers is that since theyre only used once, they will get inlined. Plus, they are more easily changeable.

If your script crashes WC3 because of an implicit conversion from integer to real, you have serious problems.
I know it might not be good style, but w/e. I dont use it in a == or != comparison so its not that crucial.

Edit: Are there any parts of the script you dont understand? Tell me, and ill add comments to it for the next version.

Last edited by Deaod; 08-26-2009 at 01:24 PM.
Deaod is offline   Reply With Quote
Old 08-26-2009, 02:30 PM   #10 (permalink)
Registered User Dark_Dragon
Behind the shadow...
 
Dark_Dragon's Avatar
 
Join Date: Jul 2007
Posts: 761
Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)
Quote:
Originally Posted by Deaod View Post
I wouldnt, since the alternative would consume even more handleids (creating a trigger with condition and action plus events). And i wouldnt have the speed advantage of using an event stack.

My thinking with the Array initializers is that since theyre only used once, they will get inlined. Plus, they are more easily changeable.

If your script crashes WC3 because of an implicit conversion from integer to real, you have serious problems.
I know it might not be good style, but w/e. I dont use it in a == or != comparison so its not that crucial.

Edit: Are there any parts of the script you dont understand? Tell me, and ill add comments to it for the next version.
no no everything is fine, script is readable but i thought that you might want to add some comments for yourself and "other who may have lesser knowledge of vjass" but for me its readable and code is good.

ahh about this "pointer functions"! yeah i know what you want to say and its really not needed to update this, it was just "my suggestion"...

what i wanted to say is that when you load trigger by urself then u create:

trigger, triggeraction, triggercondition, conditionfunc! same as 1 pointer function... however if you use two of them

Jass:
call RegisterSpellEffectResponse(AID, CreateProxy)
        call RegisterSpellCastResponse(AID, CheckValidTarget)

this is what i did mean! anyway this are two triggers, in jass you could have add this events to only one trigger and use GetTriggerEventId! its more advanced and lesser readable thats why i said its really not needed to change...

ehh about that real 0.! yeah i still dont know why it crashed but well... it was fixed, i think its blizzards own work with pointers thinking that real was basically integer... since in truth real is same as integer (long) difference is that real is an (long pointer at float) so it might have chage that pointer or smth...

anyway i think ur spells are good enough already, well maybe as i said add comments and so but not needed for me xD

as well about functions which set array or smth! i know some of them are inlined but i thought that reducing few lines and not declaring funcs would save a little of RAM... however all stuff i pointed out was unnecessary to change :)

Greets!
~DD
__________________
My Ultimate Spell Pack
Dark_Dragon is offline   Reply With Quote
Old 08-26-2009, 02:50 PM   #11 (permalink)
Registered User Deaod
GUI sucks. Don't use it.
 
Join Date: Nov 2007
Posts: 854
Deaod has disabled reputation
Quote:
anyway this are two triggers, in jass you could have add this events to only one trigger and use GetTriggerEventId!
The problem is: You'd probably use something like TriggerRegisterAnyUnitEventBJ, which creates 16 handles. And youd use it twice. That makes 32 new handles. For events only.
I think using the event stack is better.
Deaod is offline   Reply With Quote
Old 08-26-2009, 04:17 PM   #12 (permalink)
Registered User Dark_Dragon
Behind the shadow...
 
Dark_Dragon's Avatar
 
Join Date: Jul 2007
Posts: 761
Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)Dark_Dragon is just really nice (417)
Quote:
Originally Posted by Deaod View Post
The problem is: You'd probably use something like TriggerRegisterAnyUnitEventBJ, which creates 16 handles. And youd use it twice. That makes 32 new handles. For events only.
I think using the event stack is better.
indeed better! and i was just thinking and found solution to all this event and trigger id-s to reduce by max amount!

Jass:
function onSpellEffect takes code func returns nothing

this would create only one trigger action... and i think ill do that, for example ill just create one trigger and attach actions to him... as well ill just once register events and hurry no loops, no global variables, pointer functions...

the only rule would be not to use sleeps! but anyway pointer functions which are called by .evaluate() as well cant use sleeps, only .execute()

anyway your pointer functions are deff better then "my suggestion" coz of this extra events.
__________________
My Ultimate Spell Pack
Dark_Dragon is offline   Reply With Quote
Old 08-28-2009, 05:34 AM   #13 (permalink)
Registered User Deaod
GUI sucks. Don't use it.
 
Join Date: Nov 2007
Posts: 854
Deaod has disabled reputation
Version 1.3.0

Spells should now allow much better tactical use.

Version 1.3.1

Last edited by Deaod; 08-28-2009 at 10:10 PM.
Deaod is offline   Reply With Quote
Old 09-01-2009, 04:05 AM   #14 (permalink)
Registered User Archangel_Tidusx
The Guardian
 
Archangel_Tidusx's Avatar
 
Join Date: Feb 2007
Posts: 1,189
Archangel_Tidusx will become famous soon enough (108)Archangel_Tidusx will become famous soon enough (108)Archangel_Tidusx will become famous soon enough (108)
Quote:
Originally Posted by Devalut View Post
0/5
cant test it no countering units or hero's in the map
thus Fail
Try reading the description next time
__________________
Recruiting for my Unity3d Project! Check this thread --> Click Me!
Archangel_Tidusx is offline   Reply With Quote
Old 09-04-2009, 03:58 PM   #15 (permalink)
Registered User Deaod
GUI sucks. Don't use it.
 
Join Date: Nov 2007
Posts: 854
Deaod has disabled reputation
Version 1.3.2
Deaod is offline   Reply With Quote
Reply

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Warlock spec EMPerror World of Warcraft 3 05-11-2008 04:53 AM
Bandit Warlock What you don't know Texturing & Surfacing 9 03-26-2008 06:16 PM

All times are GMT. The time now is 02:47 AM.




Powered by vBulletin
Copyright 2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.5.1 PL2
Copyright © Ralle