1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. Travel to distant realms and encounter scenes unknown to the common folk. The Greatest of Adventures is upon us with the 8th Cinematic Contest. Join in on a fun ride.
    Dismiss Notice
  5. The 18th Icon Contest is ON! Choose any ingame unit and give him/her Hero abilities. Good luck to all.
    Dismiss Notice
  6. Contestants are to create a scene set in the Stone Age. Come and see what you can come up with. We wish you the best of luck!
    Dismiss Notice
  7. Colour outside the lines! Techtree Contest #13 is a go. The contest is optionally paired.
    Dismiss Notice
  8. Greetings cerebrates, our Swarm needs new spawners that will have numerous children. Join the HIVE's 31st Modeling Contest - Spawners and Spawned! The contest is optionally paired.
    Dismiss Notice
  9. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Snake 1.0

Submitted by D1000
This bundle is marked as approved. It works and satisfies the submission rules.
Another spell made by me and again it has an outermost creative name^^

Tooltip
[​IMG]


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.

Code
Code (vJASS):
                               //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


Changelog
• 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
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.
  1. 15:47, 4th Oct 2009
    TriggerHappy187:

    Some improvements can be made, though they are minor and this spell is good enough to be approved.
     
  2. Foopad

    Foopad

    Joined:
    Jun 15, 2008
    Messages:
    171
    Resources:
    3
    Maps:
    1
    Spells:
    2
    Resources:
    3
    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:
     
  3. Sinthoras

    Sinthoras

    Joined:
    Sep 1, 2009
    Messages:
    19
    Resources:
    1
    Spells:
    1
    Resources:
    1
    That's a nice spell. Only thing I didn't like was that duration of the snake seemed to be too long for me but I know thats easily changeable so I give 5/5
     
  4. aaron

    aaron

    Joined:
    Oct 18, 2008
    Messages:
    512
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    very cool 5/5 ^^ not that bad of jass coding as i can tell.
     
  5. D1000

    D1000

    Joined:
    Jun 22, 2008
    Messages:
    53
    Resources:
    3
    Spells:
    3
    Resources:
    3
    Thanks to all of you

    It´s not bug, it´s a feature
    Thanks, I´ll change that
     
  6. D4RK_G4ND4LF

    D4RK_G4ND4LF

    Joined:
    Feb 4, 2009
    Messages:
    1,196
    Resources:
    20
    Models:
    3
    Spells:
    15
    Tutorials:
    2
    Resources:
    20
    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
     
  7. NFWar

    NFWar

    Joined:
    Jul 27, 2008
    Messages:
    1,314
    Resources:
    227
    Models:
    1
    Icons:
    215
    Packs:
    1
    Skins:
    2
    Spells:
    6
    Tutorials:
    2
    Resources:
    227
    After changing model files of head and tail segments and pressing test button, WorldEditor.exe got crashed! Explain...
     
  8. D1000

    D1000

    Joined:
    Jun 22, 2008
    Messages:
    53
    Resources:
    3
    Spells:
    3
    Resources:
    3
    Do you use the JNGP?
    And please post the path of the models you tried to use
     
  9. NFWar

    NFWar

    Joined:
    Jul 27, 2008
    Messages:
    1,314
    Resources:
    227
    Models:
    1
    Icons:
    215
    Packs:
    1
    Skins:
    2
    Spells:
    6
    Tutorials:
    2
    Resources:
    227
    I know to code GUI, not JASS. So I dont use JNGP.
     
  10. Reaper2008

    Reaper2008

    Joined:
    Jul 27, 2008
    Messages:
    1,117
    Resources:
    1
    Spells:
    1
    Resources:
    1
    This system is vJASS though, and it requires JNPG.

    Nice spell btw.
     
  11. -JonNny

    -JonNny

    Joined:
    Jan 31, 2007
    Messages:
    486
    Resources:
    12
    Icons:
    3
    Maps:
    4
    Spells:
    4
    Tutorials:
    1
    Resources:
    12
    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
     
  12. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,654
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    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.
     
  13. cedi

    cedi

    Joined:
    May 19, 2008
    Messages:
    165
    Resources:
    7
    Icons:
    2
    Spells:
    5
    Resources:
    7
    Cute spell, like it. But sometimes there is a big distance between some of the segments. That looks a bit ugly.

    cedi
     
  14. manstie

    manstie

    Joined:
    Mar 10, 2008
    Messages:
    847
    Resources:
    1
    Maps:
    1
    Resources:
    1
    The snake sometimes splits up, and it would be great if the sound that it makes could be removed.
     
  15. D1000

    D1000

    Joined:
    Jun 22, 2008
    Messages:
    53
    Resources:
    3
    Spells:
    3
    Resources:
    3
    I know, but I don´t know how to fix it
    The sound is from the model, just change it
     
  16. manstie

    manstie

    Joined:
    Mar 10, 2008
    Messages:
    847
    Resources:
    1
    Maps:
    1
    Resources:
    1
    I think that if you add blood spurts it would be more realistic.
     
  17. .OmG.

    .OmG.

    Joined:
    May 9, 2010
    Messages:
    256
    Resources:
    2
    Spells:
    2
    Resources:
    2
    Ok, good idea, but it looks good in test map with human peasants...
    If unit can to atack, that looks horrible...
    4/5
     
  18. illegalpie

    illegalpie

    Joined:
    Aug 20, 2009
    Messages:
    90
    Resources:
    0
    Resources:
    0
    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.
     
  19. D4RK_G4ND4LF

    D4RK_G4ND4LF

    Joined:
    Feb 4, 2009
    Messages:
    1,196
    Resources:
    20
    Models:
    3
    Spells:
    15
    Tutorials:
    2
    Resources:
    20
    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