Spellpack Movement Based Spells

emjlr3

Change can be a good thing
Reaction score
395
Playing around with the WE today, and this is what happened:

Twisteroo v1.01

Import Difficulty: Low

Units Affected:
Enemy, ground, non-structure, non-magic immune

Target Type: Single unit - Enemy, ground, organic

Spell Info
:

Magical energy consumes the targeted unit, throwing its equilibrium out of orbit. Enemies in its rotation path are thrust away, and both units take minor damage.

Level 1 - 2 second rotation, 20 collision damage.
Level 2 - 3 second rotation, 30 collision damage.
Level 3 - 4 second rotation, 40 collision damage.


Requirements
:

Timer Utils
Group Utils
UnitAlive native
Would also be a good idea to make use of Bound Sentinel

Code
JASS:
scope Twisteroo initializer Init

// The main target is stunned via the storm bolt active for the duration of the spell.  The stun duration can be changed via this ability 
// in the object editor.  You could also added effects to the main target, along with initial cast damage, etc. via the object editor.

// This spell requires the "UnitAlive" native.  If this is not already in your map, declare it as seen in this map's custom script section.
// This spell also requires the GroupUtils and TimerUtils systems.  Similarly, as with all movement based spells, it is a good idea to have
// the BoundSentinel system installed and operational in your map as well.  

globals
    // Rawcode for caster ability
    private constant integer AbilId = 'A000'
    // Effect to create at the feet of sliding units
    private constant string SlideFX = "Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl"
    // Attachment point for SlideFX
    private constant string SlideFXAttachmentPoint = "origin"
    // Effect to create at the feet of the main target on collision
    private constant string CollisionFX = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"
    // Attachment point for CollisionFX
    private constant string CollisionFXAttachmentPoint = "origin"
    // Interval for periodic timers.  This doesn't really need to be changed, but its here nonetheless...
    private constant real TimerInterval = .04
    // Attack type for collision damage
    private constant attacktype AttackType = ATTACK_TYPE_MAGIC
    // Damage type for collision damage
    private constant damagetype DamageType = DAMAGE_TYPE_MAGIC
    // Whether you want the main unit to fade to black, then back again during the effects
    private constant boolean DoVertexColorChange = true
endglobals
// Duration of the rotation effect
private constant function Duration takes integer lvl returns real
    return 1.+lvl
endfunction
// Damage to main target and collidee
private constant function CollisionDamage takes integer lvl returns real
    return 10.*lvl
endfunction
// Area of effect within which collision take place
private constant function CollisionAoE takes integer lvl returns real
    return 125.
endfunction
// Angle between the main target and its initial location will increase at this rate per TimerInterval
private constant function RotationAngleIncrease takes integer lvl returns real
    return 10.
endfunction
// Distance between the main target and its initial location will increase at this rate per TimerInterval
private constant function RotationDistanceIncrease takes integer lvl returns real
    return 4.
endfunction
// Main targets post rotation slide speed will begin at this rate per TimerInterval
private constant function TargetSlideSpeedStart takes integer lvl returns real
    return 35.
endfunction
// Main targets post rotation slide speed will decrease at this rate per TimerInterval
private constant function TargetSlideSpeedDeceleration takes integer lvl returns real
    return 1.
endfunction
// Collidee targets collision slide speed will begin at this rate per TimerInterval
private constant function CollisionSlideSpeedStart takes integer lvl returns real
    return 13.
endfunction
// Collidee targets collision slide speed will decrease at this rate per TimerInterval
private constant function CollisionSlideSpeedDeceleration takes integer lvl returns real
    return .4
endfunction

//== No touching past this point ==\\
globals
    private boolexpr B
    private integer Temp_data
    private unit Targ
endglobals
private struct data
    unit cast
    unit targ
    player owner
    timer t
    integer lvl
    real duration    
    real angle
    real angle_change
    real distance = 0.
    real distance_change
    real startx 
    real starty 
    real damage
    real slide_distance
    real collision
    real decel
    integer vertex = 255
    integer vertex_interval
    boolean switch = false
    group g
    
    method onDestroy takes nothing returns nothing
        call ReleaseTimer(.t)
        call ReleaseGroup(.g)
        call SetUnitPathing(.targ,true)
        if DoVertexColorChange then 
            call SetUnitVertexColor(.targ,255,255,255,255)
        endif
    endmethod
endstruct
private struct slide
    unit targ
    real distance
    real cos
    real sin
    real decel
    timer t
    integer i
    
    method onDestroy takes nothing returns nothing
        local data d = .i
        
        call ReleaseTimer(.t)
        call GroupRemoveUnit(d.g,d.targ)
    endmethod
endstruct

private function Slide takes nothing returns nothing
    local slide s = GetTimerData(GetExpiredTimer())
    
    call SetUnitPosition(s.targ,GetUnitX(s.targ)+s.distance*s.cos,GetUnitY(s.targ)+s.distance*s.sin)
    call DestroyEffect(AddSpecialEffectTarget(SlideFX,s.targ,SlideFXAttachmentPoint))
    set s.distance = s.distance - s.decel
    if s.distance<s.decel then
        call s.destroy()
    endif
endfunction
private function Filt takes nothing returns boolean
    local data d = Temp_data
    local slide s
    local real ang
    set Targ = GetFilterUnit()
        
    if Targ!=d.targ and not IsUnitInGroup(Targ,d.g) and IsUnitEnemy(Targ,d.owner) and UnitAlive(Targ) and IsUnitType(Targ,UNIT_TYPE_STRUCTURE)==false and IsUnitType(Targ,UNIT_TYPE_MAGIC_IMMUNE)==false then
        call UnitDamageTarget(d.cast,d.targ,d.damage,false,false,AttackType,DamageType,null)
        call UnitDamageTarget(d.cast,Targ,d.damage,false,false,AttackType,DamageType,null)
        call DestroyEffect(AddSpecialEffectTarget(CollisionFX,d.targ,CollisionFXAttachmentPoint))
        call GroupAddUnit(d.g,Targ)
        
        set s = slide.create()
        set s.targ = Targ
        set ang = Atan2(GetUnitY(s.targ) - GetUnitY(d.targ), GetUnitX(s.targ) - GetUnitX(d.targ))
        set s.cos = Cos(ang)
        set s.sin = Sin(ang)
        set s.distance = CollisionSlideSpeedStart(d.lvl)
        set s.decel = CollisionSlideSpeedDeceleration(d.lvl)
        set s.t = NewTimer()
        set s.i = d
        
        call SetTimerData(s.t,s)
        call TimerStart(s.t,TimerInterval,true,function Slide)
    endif
    return false
endfunction
private function Effects takes nothing returns nothing
    local data d = GetTimerData(GetExpiredTimer())
    local real x 
    local real y 
    
    if d.duration<TimerInterval then 
        if not d.switch then
            set d.switch = not d.switch
            set d.angle = (d.angle+90.)*bj_DEGTORAD
            if DoVertexColorChange then
                set d.vertex_interval = R2I(255./(d.slide_distance/d.decel))
            endif
        endif
    
        set x = GetUnitX(d.targ)+d.slide_distance*Cos(d.angle)
        set y = GetUnitY(d.targ)+d.slide_distance*Sin(d.angle)
        call SetUnitPosition(d.targ,x,y)
        call DestroyEffect(AddSpecialEffectTarget(SlideFX,d.targ,SlideFXAttachmentPoint))
        
        if DoVertexColorChange then
            set d.vertex = d.vertex + d.vertex_interval
            call SetUnitVertexColor(d.targ,d.vertex,d.vertex,d.vertex,255)
        endif
        
        set d.slide_distance = d.slide_distance - d.decel
        if d.slide_distance<d.decel then
            call d.destroy()
        endif
    else
        set x = d.startx+d.distance*Cos(d.angle*bj_DEGTORAD)
        set y = d.starty+d.distance*Sin(d.angle*bj_DEGTORAD)
        call SetUnitX(d.targ,x)
        call SetUnitY(d.targ,y)
        
        if DoVertexColorChange then
            set d.vertex = d.vertex - d.vertex_interval
            call SetUnitVertexColor(d.targ,d.vertex,d.vertex,d.vertex,255)
        endif
    
        call GroupClear(ENUM_GROUP)
        set Temp_data = d
        call GroupEnumUnitsInArea(ENUM_GROUP, x, y, d.collision, B)
        
        set d.angle = d.angle + d.angle_change
        set d.distance = d.distance + d.distance_change
        set d.duration = d.duration - TimerInterval
    endif
endfunction
private function Actions takes nothing returns nothing
    local data d = data.create()
    
    set d.cast = GetTriggerUnit()
    set d.targ = GetSpellTargetUnit()
    set d.owner = GetOwningPlayer(d.cast)
    set d.lvl = GetUnitAbilityLevel(d.cast,AbilId)
    set d.duration = Duration(d.lvl)
    set d.g = NewGroup()
    set d.angle = GetRandomReal(0.,360.)
    set d.angle_change = RotationAngleIncrease(d.lvl)
    set d.distance_change = RotationDistanceIncrease(d.lvl)
    set d.startx = GetUnitX(d.targ)
    set d.starty = GetUnitY(d.targ)
    set d.damage = CollisionDamage(d.lvl)
    set d.collision = CollisionAoE(d.lvl)
    set d.slide_distance = TargetSlideSpeedStart(d.lvl)
    set d.decel = TargetSlideSpeedDeceleration(d.lvl)
    if DoVertexColorChange then
        set d.vertex_interval = R2I(255./(d.duration/TimerInterval))
    endif
    set d.t = NewTimer()
    
    call SetUnitPathing(d.targ,false)

    call SetTimerData(d.t,d)
    call TimerStart(d.t, TimerInterval, true, function Effects)
endfunction

private function SpellConditions takes nothing returns boolean
    if GetSpellAbilityId() == AbilId then
        call Actions()
    endif
    return false
endfunction
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    
    loop
        exitwhen i>bj_MAX_PLAYERS
        call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
        set i = i + 1
    endloop
    call TriggerAddCondition(t, Condition( function SpellConditions ))
    set B = Condition(function Filt)
endfunction

endscope


Electric Explosion v1.01

Import Difficulty: Low

Units Affected:
Enemy, ground, non-structure, non-magic immune

Target Type: AoE - Enemy, ground, organic

Spell Info
:

Summons a torrent of electrical activity at the target area. Pillars of energy attract all nearby enemies, then eject them in a powerful blast.

Level 1 - Small area, 100 damage.
Level 2 - Medium area, 100 damage.
Level 3 - Large area, 300 damage.


Requirements
:

Timer Utils
Group Utils
Would also be a good idea to make use of Bound Sentinel
A capped limit of 100 units affected per instance of this spell is in effect. If this is a problem for someone, use less units ;Þ.

Code
JASS:
scope ElectricExplosion initializer Init

// This spell requires the GroupUtils and TimerUtils systems.  Similarly, as with all movement based spells, it is a good idea to have
// the BoundSentinel system installed and operational in your map as well.  

// I inacted a limit of 100 units affected per instance of this spell.  If this becomes a problem, use less units :Þ
// As such, given the internal limitations of structs, this also imposes an 81 spell instance limit as well.

globals
    // Rawcode for caster ability
    private constant integer AbilId = 'A001'
    // Effect to create at the feet of sliding units
    private constant string SlideFX = "Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl"
    // Attachment point for SlideFX
    private constant string SlideFXAttachmentPoint = "origin"
    // Effect to create when units are initially trapped by the lightning beams
    private constant string InitialSFX = "Abilities\\Weapons\\ChimaeraLightningMissile\\ChimaeraLightningMissile.mdl"
    // Attachment point for InitialFX
    private constant string InitialFXAttachmentPoint = "chest"
    // Effect to create for the explosion
    private constant string ExplosionSFX = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
    // Type of lightning effect to create on affected units
    private constant string LightningSFX = "FORK"
    // Z axis height for lightning
    private constant real LightningZ = 35.
    // Interval for periodic timer.  This doesn't really need to be changed, but its here nonetheless...
    private constant real TimerInterval = .04
    // Attack type for explosion damage
    private constant attacktype AttackType = ATTACK_TYPE_MAGIC
    // Damage type for explosion damage
    private constant damagetype DamageType = DAMAGE_TYPE_MAGIC
endglobals
// Damage to targets after explosion
private constant function ExplosionDamage takes integer lvl returns real
    return 100.*lvl
endfunction
// Area of effect within which collision take place
private constant function EffectArea takes integer lvl returns real
    return 125.+lvl*75.
endfunction
// Duration for lightning pull effect
private constant function InitialSlideDuration takes integer lvl returns real
    return 1.
endfunction
// Initial slide speed for lightning pull effect per TimerInterval
private constant function InitialSlideSpeed takes integer lvl returns real
    return 10.
endfunction
// Initial slide speed after explosion per TimerInterval
private constant function ExplosionInitialSlideSpeed takes integer lvl returns real
    return 30.
endfunction
// Deceleration slide speed after explosion per TimerInterval
private constant function ExplosionDecelerationSlideSpeed takes integer lvl returns real
    return .6
endfunction

//== No touching past this point ==\\
globals
    private boolexpr B
    private location L = Location(0.,0.)
    private integer Temp_data
    private unit Targ
endglobals
private struct data
    unit cast
    player owner
    timer t
    integer lvl
    integer count = 0
    lightning array light[100]
    unit array targ[100]
    real duration
    real array cos[100]
    real array sin[100]
    real array distance[100]
    real z
    real x
    real y
    real speed
    real decel
    real damage
    boolean in = false
    
    method onDestroy takes nothing returns nothing
        call ReleaseTimer(.t)        
    endmethod
endstruct

private function Filt takes nothing returns boolean
    local data d = Temp_data
    local real x
    local real y
    local real dx
    local real dy
    local real ang
    set Targ = GetFilterUnit()
        
    if IsUnitEnemy(Targ,d.owner) and UnitAlive(Targ) and IsUnitType(Targ,UNIT_TYPE_STRUCTURE)==false and IsUnitType(Targ,UNIT_TYPE_MAGIC_IMMUNE)==false then
        set d.count = d.count + 1
        
        set x = GetUnitX(Targ)
        set y = GetUnitY(Targ)
        call MoveLocation(L,x,y)
        set d.light[d.count] = AddLightningEx(LightningSFX,true,d.x,d.y,d.z,x,y,GetLocationZ(L)+LightningZ)
        
        set d.targ[d.count] = Targ
        set ang = Atan2(y - d.y, x - d.x)
        set d.cos[d.count] = Cos(ang)
        set d.sin[d.count] = Sin(ang)
        set dx = x-d.x
        set dy = y-d.y
        set d.distance[d.count] = SquareRoot(dx*dx+dy*dy)
        
        call DestroyEffect(AddSpecialEffectTarget(InitialSFX,d.targ[d.count],InitialFXAttachmentPoint))        
        call SetUnitPathing(d.targ[d.count],false)
        
        return true       
    endif
    return false
endfunction
private function Effects takes nothing returns nothing
    local data d = GetTimerData(GetExpiredTimer())
    local integer i = d.count
    local real x
    local real y
    
    if not d.in then
        loop
            exitwhen i==0        
            
            set d.distance<i> = d.distance<i> - d.speed
            if d.distance<i>&gt;d.speed then
                set x = GetUnitX(d.targ<i>)-d.speed*d.cos<i>
                set y = GetUnitY(d.targ<i>)-d.speed*d.sin<i>
                call SetUnitPosition(d.targ<i>,x,y)
            else
                set x = d.x
                set y = d.y
                call SetUnitPosition(d.targ<i>,d.x,d.y)
            endif
            call MoveLocation(L,x,y)
            call MoveLightningEx(d.light<i>,true,d.x,d.y,d.z,x,y,GetLocationZ(L)+LightningZ)
        
            set i = i - 1
        endloop
        
        set d.duration = d.duration - TimerInterval
        if d.duration&lt;TimerInterval then
            set d.in = not d.in
            set d.speed = ExplosionInitialSlideSpeed(d.lvl)
            set d.decel = ExplosionDecelerationSlideSpeed(d.lvl)
            call DestroyEffect(AddSpecialEffect(ExplosionSFX,d.x,d.y))
            
            set i = d.count
            loop
                exitwhen i==0
            
                call DestroyLightning(d.light<i>)
                call SetUnitPathing(d.targ<i>,true)
                call UnitDamageTarget(d.cast,d.targ<i>,d.damage,false,false,AttackType,DamageType,null)
            
                set i = i - 1
            endloop
        endif
    else
        loop
            exitwhen i==0
        
            set x = GetUnitX(d.targ<i>)+d.speed*d.cos<i>
            set y = GetUnitY(d.targ<i>)+d.speed*d.sin<i>
            call SetUnitPosition(d.targ<i>,x,y)
            call DestroyEffect(AddSpecialEffectTarget(SlideFX,d.targ<i>,SlideFXAttachmentPoint))
        
            set i = i - 1
        endloop
        
        set d.speed = d.speed - d.decel
        if d.speed&lt;d.decel then
            call d.destroy()
        endif
    endif
endfunction
private function Actions takes nothing returns nothing
    local data d = data.create()
    
    set d.cast = GetTriggerUnit()
    set d.owner = GetOwningPlayer(d.cast)
    set d.lvl = GetUnitAbilityLevel(d.cast,AbilId)
    set d.x = GetSpellTargetX()
    set d.y = GetSpellTargetY()
    call MoveLocation(L,d.x,d.y)
    set d.z = GetLocationZ(L)+LightningZ
    set d.damage = ExplosionDamage(d.lvl)
    set d.speed = InitialSlideSpeed(d.lvl)
    set d.duration = InitialSlideDuration(d.lvl)
    set d.t = NewTimer()
    
    call GroupClear(ENUM_GROUP)
    set Temp_data = d
    call GroupEnumUnitsInArea(ENUM_GROUP, d.x, d.y, EffectArea(d.lvl), B)
    
    if d.count&gt;0 then
        call SetTimerData(d.t,d)
        call TimerStart(d.t, TimerInterval, true, function Effects)
    else
        call d.destroy()
    endif
endfunction

private function SpellConditions takes nothing returns boolean
    if GetSpellAbilityId() == AbilId then
        call Actions()
    endif
    return false
endfunction
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    
    loop
        exitwhen i&gt;bj_MAX_PLAYERS
        call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
        set i = i + 1
    endloop
    call TriggerAddCondition(t, Condition( function SpellConditions ))
    set B = Condition(function Filt)
endfunction

endscope</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>


Updates:
1.01
  • Added some extra configurables
  • Updated distance check in Electric Explosion to a. actually work, and b. be far more efficient
  • Added a vertex fade to Twisteroo, which is toggleable (forgot to incorporate before initial release
1.00
  • Initial release
 

Attachments

  • Twisteroo.jpg
    Twisteroo.jpg
    53.8 KB · Views: 598
  • Electric Explosion.jpg
    Electric Explosion.jpg
    59.8 KB · Views: 584
  • emjlr3 - Movement Spells.w3x
    103.2 KB · Views: 544

Weep

Godspeed to the sound of the pounding
Reaction score
401
Attempting to play the map simply dumps me back to the menu. Did you forget to process it with JassHelper before uploading?
 

emjlr3

Change can be a good thing
Reaction score
395
Attempting to play the map simply dumps me back to the menu. Did you forget to process it with JassHelper before uploading?

thats entirely possible

I renamed the map on the last save before uploading, so it may have skipped the vJASS compiling all together, and me being such an observant mapper, would surely have missed it

try it again, should work now
 

BlackRose

Forum User
Reaction score
239
It's become a standard that global constants are [ljass]CAPITAL[/ljass].
Why not just make use of the struct's [ljass]create[/ljass] method instead of using [ljass]Actions[/ljass].
You should encapsulate all the functions into their corresponding structs for better organisation and readability.

Twisteroo

• You should be able to modify the attachment point of the [ljass]SlideFX[/ljass] and [ljass]CollisionFX[/ljass]
• [ljass]set d.owner = GetOwningPlayer(d.cast)[/ljass], I think you can just use [ljass]GetTriggerPlayer()[/ljass].

Electric Explosion

• You should make configurable attachment points for [ljass]InitialSFX[/ljass] and [ljass]SlideFX[/ljass].
• You can square [ljass]d.speed[/ljass] to save the many [ljass]SquareRoot()[/ljass] calls in the loop.
JASS:
if SquareRoot(dx * dx + dy * dy)&gt;d.speed then
    call SetUnitPosition(d.targ<i>,x,y)
else
    call SetUnitPosition(d.targ<i>,d.x,d.y)
endif</i></i>

• You should allow an option to set the base lightning height.
• Perhaps you should make the slide speed configured as Warcraft III range units as it's easier for users to adjust.

Why not just use [ljass]SetUnitX/Y[/ljass] instead of [ljass]SetUnitPosition[/ljass]? It still has awkward movement even when collision is turned off (when I tested, enemies didn't slide smoothly).
 

emjlr3

Change can be a good thing
Reaction score
395
It's become a standard that global constants are [ljass]CAPITAL[/ljass].

its been that way for a while, I was just never one to confirm with the masses - sufficient to say, all globals start with a capital letter, and all locals/struct globals are completely lower case

Why not just make use of the struct's [ljass]create[/ljass] method instead of using [ljass]Actions[/ljass].
You should encapsulate all the functions into their corresponding structs for better organisation and readability.

never did much care for those, anyway, a spell release is more about functionality then anything, which these have an overabundance of

Twisteroo

• You should be able to modify the attachment point of the [ljass]SlideFX[/ljass] and [ljass]CollisionFX[/ljass]
• [ljass]set d.owner = GetOwningPlayer(d.cast)[/ljass], I think you can just use [ljass]GetTriggerPlayer()[/ljass].

knew I missed something

not sure if [ljass]GetTriggerPlayer()[/ljass] would work there, since its a unit event, not a player one - I've always seen it done the way I have it

surprised you're not slamming me for not running everything off of one timer, I just plum didn't feel like going through the extra hassle
Electric Explosion

• You should make configurable attachment points for [ljass]InitialSFX[/ljass] and [ljass]SlideFX[/ljass].
• You can square [ljass]d.speed[/ljass] to save the many [ljass]SquareRoot()[/ljass] calls in the loop.
JASS:
if SquareRoot(dx * dx + dy * dy)&gt;d.speed then
    call SetUnitPosition(d.targ<i>,x,y)
else
    call SetUnitPosition(d.targ<i>,d.x,d.y)
endif</i></i>

• You should allow an option to set the base lightning height.


all true
• Perhaps you should make the slide speed configured as Warcraft III range units as it's easier for users to adjust.

isn't that how it is? slide range per timerinterval, or are you referring instead to slide distance/sec, from which I would need to extrapolate my own slide distance per TimerInterval

Why not just use [ljass]SetUnitX/Y[/ljass] instead of [ljass]SetUnitPosition[/ljass]? It still has awkward movement even when collision is turned off (when I tested, enemies didn't slide smoothly).

I used SetUnitPosition only when I did not want units to be able to "fight" the movement effect - if you noticed, while the storm bolt has the main target stunned in Twisteroo, I use SetUnitX/Y, which is the faster of the two, and ignores pathing - however, doing so for the other instances would allow all units to "fight" against the movements, and unless I were to pause them, or through some other method render them immovable, which has its own issues I did not feel like tackling, I would need to use SetUnitPosition to avoid further issues.
 

Komaqtion

You can change this now in User CP.
Reaction score
469
isn't that how it is? slide range per timerinterval, or are you referring instead to slide distance/sec, from which I would need to extrapolate my own slide distance per TimerInterval

I would believe that he meant you should change it to range/second, instead of range/interval ;)
 

emjlr3

Change can be a good thing
Reaction score
395
updated per BlackRose's suggestions
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
very nice eye candy but i doubt they are of much use for an actual pvp game because of the fact they are pretty overpowered.
they render their target stunned for the whole duration of the skill, push it back, cancel all skills the enemy might be casting right now, damages them and and enemys within the area of effect.

i just cant imagine any player who likes to fight against a hero with that ability.

by the way, i encountered no flaws nor any bugs, works like a charm, good work.
 

BlackRose

Forum User
Reaction score
239
its been that way for a while, I was just never one to confirm with the masses - sufficient to say, all globals start with a capital letter, and all locals/struct globals are completely lower case

*Shrugs*. Although I think the configurable section is kind of messy - all I see is green line / variable / green line. Meh.

never did much care for those, anyway, a spell release is more about functionality then anything, which these have an overabundance of

For more complicated spells which require a lot of coding, you'll want to encapsulate it well but ;)

not sure if [ljass]GetTriggerPlayer()[/ljass] would work there, since its a unit event, not a player one - I've always seen it done the way I have it

Well. I just followed PurgeAndFire ;) It works too also.

surprised you're not slamming me for not running everything off of one timer, I just plum didn't feel like going through the extra hassle

I've only commented on small things ;) I leave things I'm unsure of to other people :D

isn't that how it is? slide range per timerinterval, or are you referring instead to slide distance/sec, from which I would need to extrapolate my own slide distance per TimerInterval

Yeah. Slide Distance per second is what I mean't.

I used SetUnitPosition only when I did not want units to be able to "fight" the movement effect - if you noticed, while the storm bolt has the main target stunned in Twisteroo, I use SetUnitX/Y, which is the faster of the two, and ignores pathing - however, doing so for the other instances would allow all units to "fight" against the movements, and unless I were to pause them, or through some other method render them immovable, which has its own issues I did not feel like tackling, I would need to use SetUnitPosition to avoid further issues.

Makes sense I guess. Although I do think something should be done about the awkward movement with [ljass]SetUnitPosition[/ljass]. But what?

Anyways;

Twisteroo

JASS:
.
        if DoVertexColorChange then
            set d.vertex = d.vertex + d.vertex_interval
            call SetUnitVertexColor(d.targ,d.vertex,d.vertex,d.vertex,255)
        endif


Because [ljass]DoVertexColorChange[/ljass] is a constant boolean, you can change that to a static if. However changing a unit's colouring is not a good idea is it? I mean, what if some unit was mean't to have 200/200/200 default colouring. The ability won't keep track of that.
 

emjlr3

Change can be a good thing
Reaction score
395
Because DoVertexColorChange is a constant boolean, you can change that to a static if. However changing a unit's colouring is not a good idea is it? I mean, what if some unit was mean't to have 200/200/200 default colouring. The ability won't keep track of that.

let me get this straight

if false, it would remove that section of code?

and it true, it would remove the if statement but leave what it contained???

anyway, I give the user the ability to turn off that functionality, if that could cause the issues you described above to occur

Makes sense I guess. Although I do think something should be done about the awkward movement with SetUnitPosition. But what?

your guess is as good as mine
 

BlackRose

Forum User
Reaction score
239
Rome said:
There also seems to be some confusion about static ifs:

JASS:
globals
    constant boolean BOOL1 = false
    constant boolean BOOL2 = true
endglobals

function ExampleFunc takes nothing returns nothing
    static if BOOL1 then
        call KillUnit(GetTriggerUnit())
    endif
    static if BOOL2 then
        call GetRandomReal(2, 4)
    endif
endfunction


Compiles to:

JASS:
globals
    constant boolean BOOL1 = false
    constant boolean BOOL2 = true
endglobals

function ExampleFunc takes nothing returns nothing
//    static if BOOL1 then
//        call KillUnit(GetTriggerUnit())
//    endif
//    static if BOOL2 then
        call GetRandomReal(2, 4)
//    endif
endfunction


More efficient? Oh yes.

:thup: Yes you are right. It's a constant too, can't change so it is harmless.
 

TERRYperfect

New Member
Reaction score
0
JASS:
library GroupUtils initializer Init requires optional xebasic



syntax error? Why does my WE show that?
 

TERRYperfect

New Member
Reaction score
0
How to update correctly?

I just downloaded the newer jasshelper
and replace the three files (clijasshelper.exe \ jasshelper.conf \ jasshelper.exe) with the newer one only...

but new errors occured...
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top