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

Snake 1.0

Another spell made by me and again it has an outermost creative name^^

attachment.php


Requires:
Credits to Vexorian for "TimerUtils", "JassHelper" and "xe" and to Anitarf for "IsTerrainWalkable"

Please give proper credits to me, Anitarf and Vexorian if you use this spell in your map.

JASS:
                               //Snake\\
/*                        Made by: D1000
                               Version: 1.0
                               
                         //Requirements\\
                              
                              Systems:
                       TimerUtils (Vexorian)
                          xebasic (Vexorian)
                             xefx (Vexorian)
                        xedamage (Vexorian)
                        xepreload (Vexorian)
                  IsTerrainWalkable (Anitarf)
                      
                               Models:
                    dummy.mdx (Vexorian)
                            
                                    //Import\\
1) Copy this trigger and everything mentioned in "Requirements" into your map
                2) Create an ability with point- or unit-target
     and change "AbilityID" (Global in this trigger) to its ID (press Ctrl+D in the Object-Editor to get the ID)
  3) Follow the import-instructions in the "xebasic" and the "BoundSentinel"-trigger
                                  4) Have fun (-:

*/scope Snake
    //Changing Area:
    globals
        /*Basics*/
            private constant integer AbilityID = 'SNAK' //The ID of the dummy-spell
            private constant integer MAX_INSTANCES = 8190 //How many instances of the spell can exist at once
                                                                                           //ATTENTION: Each segment of the Snake uses its own instance!
            private constant real Interval = XE_ANIMATION_PERIOD //Self explanatory....
            
            private constant real PushDistance = 8 //How far targeted units will get pushed away. You can also use negative numbers
            private constant real PushDistanceAdd = 0 //The increase of the push-distance each level
            
            private constant real Duration = 40 //The duration of the spell
            private constant real DurationAdd = 8 //...
        
        /*Head and Movement*/
            private constant real Speed = 300 //How fast the snake moves. Uses the same values as the Object-Editor, but you can also use values higher than 522
            private constant real SpeedAdd = 75 //...
            
            private constant string HeadModel = "Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl" //The model of the snakes head
            private constant real HeadSize = 7.5 //The scale of the head
            private constant real HeadSizeAdd = 0 //...
            private constant real HeadZ = 60 //The flying-height of the head
            private constant real HeadZAdd = 0 //...
            private constant real HeadAngle = 0 //The angle of the the head in radians. If you use bj_PI, the head will move backwards
            private constant real HeadZAngle = 0 //The pitch angle in radians
            //The color of the head (0-255)
                  private constant integer HeadColorR = 0 //Red
                  private constant integer HeadColorG = 60 //Green
                  private constant integer HeadColorB = 0 //Blue
                  private constant integer HeadColorA = 255 //Alpha
            
            private constant string HeadCreationEffectModel = "Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl" //An effect, which appears when the head gets created
            //The following values are the same as by the model of the head.
            private constant real HeadCreationEffectSize= 1.5
            private constant real HeadCreationEffectSizeAdd= 0
            private constant real HeadCreationEffectZ = 60
            private constant real HeadCreationEffectZAdd = 0
            private constant real HeadCreationEffectAngle = 0
            private constant real HeadCreationEffectZAngle = -bj_PI
            private constant integer HeadCreationEffectColorR = 255
            private constant integer HeadCreationEffectColorG = 255
            private constant integer HeadCreationEffectColorB = 255
            private constant integer HeadCreationEffectColorA = 255
            
            private constant string HeadDeathEffectModel ="Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl" //An effect, which appears when the head gets destroyed
            //The following values are the same as by the model of the head.
            private constant real HeadDeathEffectSize= 1.5
            private constant real HeadDeathEffectSizeAdd= 0
            private constant real HeadDeathEffectZ = 60
            private constant real HeadDeathEffectZAdd = 0
            private constant real HeadDeathEffectAngle = 0
            private constant real HeadDeathEffectZAngle = -bj_PI
            private constant integer HeadDeathEffectColorR = 255
            private constant integer HeadDeathEffectColorG = 255
            private constant integer HeadDeathEffectColorB = 255
            private constant integer HeadDeathEffectColorA = 255
            
            private constant real DistanceToFirstSegment = 80 //The distance between the head and the first segment
            private constant real DistanceToFirstSegmentAdd = 0 //...
            
            private constant real DetectionRange = 800 //The distance within which the head can detect enemy units
            private constant real DetectionRangeAdd = 0 //...
            
            private constant real RandomMovement = 100 //Just try what it does^^
            
            private constant boolean IgnorePathing = true //Defines, if the head can ignore obstacles (the segments do this anyway)
            
            private constant real DistractionTime = 2 //After this time the head gets distracted from its target and follows another
            private constant real DistractionTimeAdd = 0.5 //...
        
        /*Segments*/
            private constant real SegmentSpeed = 400 //The speed of the segments. It´s recommend to set it to a higher speed than the head has, but don´t use to high values ´cause it´ll look weird
            private constant real SegmentSpeedAdd = 75 //...
            
            //The next three "blocks" of constant are just the same as for the head, but for the segments
            private constant string SegmentModel = "Abilities\\Weapons\\WardenMissile\\WardenMissile.mdl"
            private constant real SegmentSize = 5.5
            private constant real SegmentSizeAdd = 0
            private constant real SegmentZ = 60
            private constant real SegmentZAdd = 0
            private constant real SegmentAngle = 0
            private constant real SegmentZAngle = 0
            private constant integer SegmentColorR = 0
            private constant integer SegmentColorG = 255
            private constant integer SegmentColorB = 100
            private constant integer SegmentColorA = 255
            
            private constant string SegmentCreationEffectModel ="Objects\\Spawnmodels\\NightElf\\EntBirthTarget\\EntBirthTarget.mdl"
            private constant real SegmentCreationEffectSize= 1
            private constant real SegmentCreationEffectSizeAdd= 0
            private constant real SegmentCreationEffectZ = 0
            private constant real SegmentCreationEffectZAdd = 0
            private constant real SegmentCreationEffectAngle = 0
            private constant real SegmentCreationEffectZAngle = 0
            private constant integer SegmentCreationEffectColorR = 255
            private constant integer SegmentCreationEffectColorG = 150
            private constant integer SegmentCreationEffectColorB = 255
            private constant integer SegmentCreationEffectColorA = 255
            
            private constant string SegmentDeathEffectModel ="Objects\\Spawnmodels\\NightElf\\EntBirthTarget\\EntBirthTarget.mdl"
            private constant real SegmentDeathEffectSize= 1
            private constant real SegmentDeathEffectSizeAdd= 0
            private constant real SegmentDeathEffectZ = 0
            private constant real SegmentDeathEffectZAdd = 0
            private constant real SegmentDeathEffectAngle = 0
            private constant real SegmentDeathEffectZAngle = 0
            private constant integer SegmentDeathEffectColorR = 255
            private constant integer SegmentDeathEffectColorG = 150
            private constant integer SegmentDeathEffectColorB = 255
            private constant integer SegmentDeathEffectColorA = 255
            //End of the three blocks^^
            
            private constant real FoodNeeded = 250 //The damage which is needed to get a new segment.
            private constant real FoodNeededAdd = 0 //...
            private constant boolean SegmentOnKill = true //Defines, if the head gets a new segment for killing a unit
            
            private constant real DistanceBetweenSegments = 60 //The distance between the segments
            private constant real DistanceBetweenSegmentsAdd = 0 //...
            
            private constant integer StartSegments = 5 //The number of segments the snake has when it gets created
            private constant integer StartSegmentsAdd = 0 //...
            
            private constant integer MaxSegments = 12 //The maximal number of segments the snake can have
            private constant integer MaxSegmentsAdd = 3 //...
            
        /*Damage and targets*/
            // Hero you can specify the target options
            // Uses "xedamage", you can find the xedamage-readme in the "Systems"-Folder
            private constant boolean TargetMagicImmune = false //If you set this to "true", make sure that the damage-type is NOT Magic (else magic immune units will get pushed back but won´t receive damage)
            //! textmacro Snake_DamageSettings
                set .exception = UNIT_TYPE_FLYING
                set .dtype = DAMAGE_TYPE_MAGIC
                set .atype = ATTACK_TYPE_MAGIC
                set .damageNeutral = false
            //! endtextmacro
            
            private constant real HeadDPS = 30 //The damage per second the head does
            private constant real HeadDPSAdd = 6 //...
            
            private constant real HeadAoE = DistanceToFirstSegment //The AoE of the damage the head does
            private constant real HeadAoEAdd = DistanceToFirstSegmentAdd //...
        
            private constant real DPS = 25 //The damage per second the segments do
            private constant real DPSAdd = 5 //...
            
            private constant real AoE = DistanceBetweenSegments //The AoE of the damage the segments do
            private constant real AoEAdd = DistanceBetweenSegmentsAdd //...
            
    /*===============*/    
    //Do not Change anything below//
    /*===============*/
    endglobals
    
    private struct Snake[MAX_INSTANCES]
        timer tim
        real time
        real DistractionTimer
        unit caster
        integer level
        real NeededFood
        integer segments = 0
        unit target
        
        Snake next
        Snake previous
        delegate xefx fx
        
        static delegate xedamage dmg
        static group TempGroup = CreateGroup()
        static Snake TempSnake
        static boolexpr IsAllowed
        static boolexpr IsAllowed2
        
        static method StartSpell takes nothing returns boolean
            local Snake this
            local Snake head
            if GetSpellAbilityId() == AbilityID then
                set head = Snake.allocate()
            
                set head.tim = NewTimer()
                set head.caster = GetTriggerUnit()
                set head.level = GetUnitAbilityLevel(head.caster,AbilityID) - 1
                set head.NeededFood = FoodNeeded + FoodNeededAdd*head.level
                call SetTimerData(head.tim,head)
                
                if GetSpellTargetUnit() != null then
                    set head.DistractionTimer = DistractionTime + DistractionTimeAdd*head.level
                    set head.target = GetSpellTargetUnit()
                else
                    set head.DistractionTimer = 0
                endif
                
                set head.time = Atan2(GetSpellTargetY() - GetUnitY(head.caster), GetSpellTargetX() - GetUnitX(head.caster))
                
                if HeadCreationEffectModel != "" then
                    set head.fx = xefx.create(GetSpellTargetX(),GetSpellTargetY(),HeadCreationEffectAngle + head.time)
                    set head.fxpath = HeadCreationEffectModel
                    set head.scale = HeadCreationEffectSize + HeadCreationEffectSizeAdd*head.level
                    call head.recolor(HeadCreationEffectColorR,HeadCreationEffectColorG,HeadCreationEffectColorB,HeadCreationEffectColorA)
                    set head.zangle = HeadCreationEffectZAngle
                    set head.z = HeadCreationEffectZ + HeadCreationEffectZAdd*head.level
                    call head.fx.destroy()
                endif
            
                set head.fx = xefx.create(GetSpellTargetX(),GetSpellTargetY(),HeadAngle + head.time)
                set head.time = Duration + DurationAdd*head.level
                set head.fxpath = HeadModel
                set head.scale = HeadSize + HeadSizeAdd*head.level
                call head.recolor(HeadColorR,HeadColorG,HeadColorB,HeadColorA)
                set head.zangle = HeadZAngle
                set head.z = HeadZ + HeadZAdd*head.level
                set this = Snake.allocate()
                set head.next = this
                set .previous = head
                call .NewSegment(head.level,head.x - (DistanceToFirstSegment + DistanceToFirstSegmentAdd*head.level)*Cos(head.xyangle),head.y - (DistanceToFirstSegment + DistanceToFirstSegmentAdd*head.level)*Sin(head.xyangle),head.xyangle - HeadAngle)

                loop
                    
                    set .fxpath = SegmentModel
                    set .scale = SegmentSize + SegmentSizeAdd*head.level
                    call .recolor(SegmentColorR,SegmentColorG,SegmentColorB,SegmentColorA)
                    set .zangle = SegmentZAngle
                    set .z = SegmentZ + SegmentZAdd*head.level
                
                    set head.segments = head.segments + 1
                    exitwhen head.segments >= StartSegments + StartSegmentsAdd*head.level
                    
                    set .next = Snake.allocate()
                    set .next.previous = this
                    set this = .next
                    call .NewSegment(head.level,.previous.x - (DistanceBetweenSegments + DistanceBetweenSegmentsAdd*head.level)*Cos(.previous.xyangle),.previous.y - (DistanceBetweenSegments + DistanceBetweenSegmentsAdd*head.level)*Sin(.previous.xyangle),.previous.xyangle - SegmentAngle)
                endloop
                set .next = 0
                
                call TimerStart(head.tim,Interval,true,function Snake.Loop)
            endif
            return false
        endmethod
        
        static method Loop takes nothing returns nothing
            local Snake head = GetTimerData(GetExpiredTimer())
            local Snake this = head.next
            local unit u
            local real damage
            local real x
            local real y
            set head.time = head.time - Interval
            set head.DistractionTimer = head.DistractionTimer - Interval
            
            if head.time <= 0 then
                set damage = head.level
                call ReleaseTimer(head.tim)
                set head.NeededFood = head.xyangle
                set x = head.x
                set y = head.y
                call head.fx.destroy()
                
                if HeadDeathEffectModel != "" then
                    set head.fx = xefx.create(x,y,HeadDeathEffectAngle + head.NeededFood)
                    set head.fxpath = HeadDeathEffectModel
                    set head.scale = HeadDeathEffectSize + HeadDeathEffectSizeAdd*damage
                    call head.recolor(HeadDeathEffectColorR,HeadDeathEffectColorG,HeadDeathEffectColorB,HeadDeathEffectColorA)
                    set head.zangle = HeadDeathEffectZAngle
                    set head.z = HeadDeathEffectZ + HeadDeathEffectZAdd*damage
                    call head.fx.destroy()
                endif
                call head.destroy()
                
                loop
                    set head = .next
                    call .DestroySegment(R2I(damage),.x,.y,.xyangle-SegmentAngle)
                    exitwhen head == 0
                    set this = head
                endloop
                
                return
            endif
            
            if (head.DistractionTimer <= 0 and DistractionTime + DistractionTimeAdd*head.level >= 0) or head.target == null or GetUnitState(head.target,UNIT_STATE_LIFE) < 0.405 then
                set .TempSnake = head
                call GroupEnumUnitsInRangeCounted(.TempGroup,head.x,head.y,DetectionRange + DetectionRangeAdd,.IsAllowed2,1)
                set head.target = FirstOfGroup(.TempGroup)
                set head.DistractionTimer = DistractionTime + DistractionTimeAdd*head.level
            endif
                
            if head.target == null then
                set head.xyangle = HeadAngle + Atan2(head.y + 10*Sin(head.xyangle-HeadAngle) + GetRandomReal(-RandomMovement,RandomMovement) - head.y,head.x + 10*Cos(head.xyangle-HeadAngle) + GetRandomReal(-RandomMovement,RandomMovement) - head.x)
            else
                set head.xyangle = HeadAngle + Atan2(GetUnitY(head.target) + GetRandomReal(-RandomMovement,RandomMovement) - head.y,GetUnitX(head.target) + GetRandomReal(-RandomMovement,RandomMovement) - head.x)
            endif
            set x = head.x + (Speed + SpeedAdd*head.level)*Interval * Cos(head.xyangle-HeadAngle)
            set y = head.y + (Speed + SpeedAdd*head.level)*Interval * Sin(head.xyangle-HeadAngle)
            if (not IgnorePathing and IsTerrainWalkable(x,y)) or (IgnorePathing and RectContainsCoords(bj_mapInitialPlayableArea,x,y)) then
                set head.x = x
                set head.y = y
            else
                set head.xyangle = head.xyangle + GetRandomReal(-bj_PI/2*3,-bj_PI/2)
            endif
                
            call GroupEnumUnitsInRange(.TempGroup,head.x,head.y,HeadAoE+HeadAoEAdd*head.level,.IsAllowed)
            loop
                set u = FirstOfGroup(.TempGroup)
                exitwhen u == null
                call GroupRemoveUnit(.TempGroup,u)
                
                set damage = GetUnitState(u,UNIT_STATE_LIFE)
                call .damageTarget(head.caster,u,(HeadDPS + HeadDPSAdd*head.level)*Interval)
                set head.NeededFood = head.NeededFood + GetUnitState(u,UNIT_STATE_LIFE) - damage
                
                if SegmentOnKill and GetUnitState(u,UNIT_STATE_LIFE) < 0.405 then
                    set head.NeededFood = head.NeededFood - FoodNeeded - FoodNeededAdd*head.level
                endif
                
                if PushDistance + PushDistanceAdd*head.level != 0 then
                    set x = GetUnitX(u)+(PushDistance + PushDistanceAdd*head.level)*Cos(damage)
                    set y = GetUnitY(u)+(PushDistance + PushDistanceAdd*head.level)*Sin(damage)
                    if IsTerrainWalkable(x,y) or IsUnitType(u,UNIT_TYPE_FLYING) then
                        set damage = Atan2(GetUnitY(u) - head.y, GetUnitX(u) - head.x)
                        call SetUnitX(u,x)
                        call SetUnitY(u,y)
                    endif
                endif
            endloop
            
            if SquareRoot((head.x-.x)*(head.x-.x) + (head.y-.y)*(head.y-.y)) > DistanceToFirstSegment + DistanceToFirstSegmentAdd*head.level then
                set .xyangle = SegmentAngle + Atan2(head.y - .y, head.x - .x)
                set .x = .x + (SegmentSpeed + SegmentSpeedAdd*head.level)*Interval*Cos(.xyangle-SegmentAngle)
                set .y = .y + (SegmentSpeed + SegmentSpeedAdd*head.level)*Interval*Sin(.xyangle-SegmentAngle)
            endif
            
            call GroupEnumUnitsInRange(.TempGroup,.x,.y,AoE+AoEAdd*head.level,.IsAllowed)
            loop
                set u = FirstOfGroup(.TempGroup)
                exitwhen u == null
                call GroupRemoveUnit(.TempGroup,u)
                
                set damage = GetUnitState(u,UNIT_STATE_LIFE)
                call .damageTarget(head.caster,u,(DPS + DPSAdd*head.level)*Interval)
                set head.NeededFood = head.NeededFood + GetUnitState(u,UNIT_STATE_LIFE) - damage
                
                if SegmentOnKill and GetUnitState(u,UNIT_STATE_LIFE) < 0.405 then
                    set head.NeededFood = head.NeededFood - FoodNeeded - FoodNeededAdd*head.level
                endif
                
                if PushDistance + PushDistanceAdd*head.level != 0 then
                    set x = GetUnitX(u)+(PushDistance + PushDistanceAdd*head.level)*Cos(damage)
                    set y = GetUnitY(u)+(PushDistance + PushDistanceAdd*head.level)*Sin(damage)
                    if IsTerrainWalkable(x,y) or IsUnitType(u,UNIT_TYPE_FLYING) then
                        set damage = Atan2(GetUnitY(u) - head.y, GetUnitX(u) - head.x)
                        call SetUnitX(u,x)
                        call SetUnitY(u,y)
                    endif
                endif
            endloop
            
            set this = .next
            loop
                if SquareRoot((.previous.x-.x)*(.previous.x-.x) + (.previous.y-.y)*(.previous.y-.y)) > DistanceBetweenSegments + DistanceBetweenSegmentsAdd*head.level then
                    set .xyangle = SegmentAngle + Atan2(.previous.y - .y, .previous.x - .x)
                    set .x = .x + (SegmentSpeed + SegmentSpeedAdd*head.level)*Interval*Cos(.xyangle-SegmentAngle)
                    set .y = .y + (SegmentSpeed + SegmentSpeedAdd*head.level)*Interval*Sin(.xyangle-SegmentAngle)
                endif
                
                call GroupEnumUnitsInRange(.TempGroup,.x,.y,AoE+AoEAdd*head.level,.IsAllowed)
                loop
                    set u = FirstOfGroup(.TempGroup)
                    exitwhen u == null
                    call GroupRemoveUnit(.TempGroup,u)
                
                    set damage = GetUnitState(u,UNIT_STATE_LIFE)
                    call .damageTarget(head.caster,u,(DPS + DPSAdd*head.level)*Interval)
                    set head.NeededFood = head.NeededFood + GetUnitState(u,UNIT_STATE_LIFE) - damage
                
                    if SegmentOnKill and GetUnitState(u,UNIT_STATE_LIFE) < 0.405 then
                        set head.NeededFood = head.NeededFood - FoodNeeded + FoodNeededAdd*head.level
                    endif
                
                    if PushDistance + PushDistanceAdd*head.level != 0 then
                        set x = GetUnitX(u)+(PushDistance + PushDistanceAdd*head.level)*Cos(damage)
                        set y = GetUnitY(u)+(PushDistance + PushDistanceAdd*head.level)*Sin(damage)
                        if IsTerrainWalkable(x,y) or IsUnitType(u,UNIT_TYPE_FLYING) then
                            set damage = Atan2(GetUnitY(u) - head.y, GetUnitX(u) - head.x)
                            call SetUnitX(u,x)
                            call SetUnitY(u,y)
                        endif
                    endif
                endloop
                
                exitwhen .next == 0
                set this = .next
            endloop
            
            if head.NeededFood <= 0 and (MaxSegments + MaxSegmentsAdd*head.level <= 0 or MaxSegments + MaxSegmentsAdd*head.level > head.segments) then
                set head.NeededFood = head.NeededFood + FoodNeeded + FoodNeededAdd*head.level
                set head.segments = head.segments + 1
                set .next = Snake.allocate()
                set .next.previous = this
                set this = .next
                set .next = 0
            
                call .NewSegment(head.level,.previous.x,.previous.y,.previous.xyangle - SegmentAngle)
                set .fxpath = SegmentModel
                set .scale = SegmentSize + SegmentSizeAdd*head.level
                call .recolor(SegmentColorR,SegmentColorG,SegmentColorB,SegmentColorA)
                set .zangle = SegmentZAngle
                set .z = SegmentZ + SegmentZAdd*head.level
                
            endif
        endmethod
        
        static method IsTargetAllowed takes nothing returns boolean
            return .allowedTarget(.TempSnake.caster,GetFilterUnit()) and (IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE) == false or TargetMagicImmune) and IsUnitVisible(GetFilterUnit(),GetOwningPlayer(.TempSnake.caster))
        endmethod
        
        static method IsTargetAllowed2 takes nothing returns boolean
            return .allowedTarget(.TempSnake.caster,GetFilterUnit()) and (IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE) == false or TargetMagicImmune) and IsUnitVisible(GetFilterUnit(),GetOwningPlayer(.TempSnake.caster)) and GetFilterUnit() != .TempSnake.target
        endmethod
        
        method NewSegment takes integer level, real x, real y, real angle returns nothing
            if SegmentCreationEffectModel != "" then
                set .fx = xefx.create(x,y,SegmentCreationEffectAngle + angle)
                set .fxpath = SegmentCreationEffectModel
                set .scale = SegmentCreationEffectSize + SegmentCreationEffectSizeAdd*level
                call .recolor(SegmentCreationEffectColorR,SegmentCreationEffectColorG,SegmentCreationEffectColorB,SegmentCreationEffectColorA)
                set .zangle = SegmentCreationEffectZAngle
                set .z = SegmentCreationEffectZ + SegmentCreationEffectZAdd*level
                call .fx.destroy()
            endif
                
            set .fx = xefx.create(x,y,SegmentAngle + angle)
        endmethod
        
        method DestroySegment takes integer level, real x, real y, real angle returns nothing
            call .fx.destroy()
            
            if SegmentDeathEffectModel != "" then
                set .fx = xefx.create(x,y,SegmentDeathEffectAngle + angle)
                set .fxpath = SegmentDeathEffectModel
                set .scale = SegmentDeathEffectSize + SegmentDeathEffectSizeAdd*level
                call .recolor(SegmentDeathEffectColorR,SegmentDeathEffectColorG,SegmentDeathEffectColorB,SegmentDeathEffectColorA)
                set .zangle = SegmentDeathEffectZAngle
                set .z = SegmentDeathEffectZ + SegmentDeathEffectZAdd*level
            
                call .fx.destroy()
            endif
            
            call .destroy()
        endmethod
        
        static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            
            set Snake.IsAllowed = Condition(function Snake.IsTargetAllowed)
            set Snake.IsAllowed2 = Condition(function Snake.IsTargetAllowed2)
        
            set .dmg = xedamage.create()
            
            //! runtextmacro Snake_DamageSettings()
            
            call XE_PreloadAbility(AbilityID)
            
            call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT )
            call TriggerAddCondition(t,Condition(function Snake.StartSpell))
            set t = null
        endmethod
    endstruct
endscope

• v. 1.0:
-Made the Spell and uploaded it on wc3c and HiveWorkshop


Keywords:
Snake, crawl, green, funny, D1000, damage, arcade game
Contents

Snake (Map)

Reviews
15:47, 4th Oct 2009 TriggerHappy187: Some improvements can be made, though they are minor and this spell is good enough to be approved.

Moderator

M

Moderator

15:47, 4th Oct 2009
TriggerHappy187:

Some improvements can be made, though they are minor and this spell is good enough to be approved.
 
Level 6
Joined
Jun 15, 2008
Messages
175
Interresting idea - I will check it out.
[Edit] A fun spell to play around with. The code was too advanced for me to judge it though.
The units kind of bug when the snake hits them, they move really weird.
The description of the spell is somewhat confusing " if you´ve casted the spell on a unit, the targeted unit with a speed of 300.", yes then what? I found one spelling mistake "Please give credits if you use this spells in your map." Spells is the word I am after. I only saw the snake spell, unless you want credits for the blink spell :p. The blink spell has the same hotkey as the snake spell ><
Otherwise this is a nice spell, I like it! I haven't seen the idea before and it has a nice touch. GJ! :thumbs_up:
 
Level 4
Joined
Jun 22, 2008
Messages
49
Thanks to all of you

Interresting idea - I will check it out.
The units kind of bug when the snake hits them, they move really weird.
It´s not bug, it´s a feature
The description of the spell is somewhat confusing " if you´ve casted the spell on a unit, the targeted unit with a speed of 300.", yes then what? I found one spelling mistake "Please give credits if you use this spells in your map." Spells is the word I am after. I only saw the snake spell, unless you want credits for the blink spell :p. The blink spell has the same hotkey as the snake spell ><
Otherwise this is a nice spell, I like it! I haven't seen the idea before and it has a nice touch. GJ! :thumbs_up:
Thanks, I´ll change that
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
I once made a worm out of forgotten one's rotated by 90 °
that was fun :grin:

I made it in GUI and the movement like that:
if the distance between the segments is bigger then e.g. 20 the segments won't be moved else the segment shall be moved near to the previous one

imho it would look a little smoother if it was done that way but this one is nice too

edit: and there are typos all around and massing testunits increases map size quite a lot
 
Level 15
Joined
Jan 31, 2007
Messages
502
looks quite funny , i kinda like it but it seems to drain alot resources

even one cast with many units created a recognizeable fps drop for me

the code looks neat and has alot of configurations :O
and btw - you gave me a great idea for a "similar" system with a snake because i thought at first yours would work like that after i took a look at the screnshot
 
Spell looks very interesting, though minor code adjustments could be done.

  • Nulling triggers is unneeded, though it's harmless.
  • GetUnitState should be changed to GetWidgetLife.
  • Configurable globals are generally names in ALL_CAPITALS, this way they stand out in the code and makes easier readablity. Just a suggesion for future spells.
  • All of your static math forumulas should be stored somewhere, this saves speed.
  • Why use RectContainsCoords, I know it gives the code better readability but efficiency is more important. You can even use the multi-line comment feature to make the condition in two lines.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
When I import, it does the damage and the unit gets knocked continuously, I did everything in import instructions, however, it doesn't show the snake.

most likely you did not import the model
the ingame model has a weird sound so he imported a custom model with that sound removed
however you can still use the ingame model by changing the dummy unit's model path
 
Level 4
Joined
Jun 22, 2008
Messages
49
so he imported a custom model with that sound removed
Thanks for answering him, but no, I didn't ^^" (But it is correct, that I importat a model, the xe-dummy model)

When I import, it does the damage and the unit gets knocked continuously, I did everything in import instructions, however, it doesn't show the snake.
Did you import the xe-dummy-model? (I forgot its name xD haven't done anything in wc3 for ages)
 
Top