Spell Panda Roll

Romek

Super Moderator
Reaction score
963
Panda Roll!
By Romek

Code: vJASS
MUI / MPI: MUI
Leaks: None
Import Difficulty: Easy / Average
Targets: Instant Cast - Self Buff
Description: The Panda ignites and rolls around the field, leaving a trial of fire which damages enemy units. Destroys trees. Lasts 10 / 15 / 20 seconds

Inspired by a vid I saw on youtube ;)

I Bring Pandemonium!

Screenshot:
Roller.png


To Use:
  • Copy Vexorians Dummy.mdx into your map if you don't already have it
  • Copy the dummy unit into your map
  • Copy ABC into your map if you don't already have it
  • Create a new trigger
  • Convert it to Custom Text
  • Copy this code into that trigger

The Code:
JASS:
scope Roller initializer Init
globals
// =================================
// === C O N F I G U R A T I O N ===
// =================================
      // == G L O B A L S == \\

//  -- General Config --  \\

    // The Raw code of the spell
    private constant integer ID = 'A000'
        
    // The raw code of the dummy unit.
    private constant integer DUMMY = 'dmmy'
        
    // The raw code of Crow Form.
    private constant integer CROW = 'Amrf' // Will probably be the same for every map unless you've
                                           // modified the "Crow Form" ability.
    // Should it knock down trees?
    private constant boolean TREES = true
        
    // The raw code of a unit used to check for trees
    private constant integer TREEDUMMY = 'nmpe' // Ignore if TREES is false
    
    // Raw code of Harvest
    private constant integer HARVEST = 'Ahrl'  // Ignore if TREES is false
        
    // The height of the effects
    private constant real HEIGHT = 60.
        
    // The effect the unit becomes
    private constant string UNITEFFECT = "Units\\Creeps\\FirePandarenBrewmaster\\FirePandarenBrewmaster_Missile.mdl"
        
    // An alternate effect attached to the unit
    private constant string ANOTHEREFFECT = "Abilities\\Spells\\Other\\ImmolationRed\\ImmolationRedTarget.mdl"
                
    // The alpha value of the caster during the spell
    private constant integer ALPHA = 1  // A number between 0 and 255
        
    // How often the timer expires
    private constant real TIMEOUT = 0.03125
        
    // How quickly the unit rolls (Per second)
    private constant real SPEED = 500.
        
//  -- Trail Config --  \\
        
    // The trail created by the caster
    private constant string BURNEFFECT = "Environment\\SmallBuildingFire\\SmallBuildingFire2.mdl"
    
    // How long the trail lasts
    private constant real BURNEFFECT_DURATION = 2.5
        
    // How close you need to be to the trail to take damage
    private constant real BURN_RADIUS = 50.
        
    // Should it damage allies
    private constant boolean BURN_ALLY = true
        
    // Should it damage the caster
    private constant boolean BURN_CASTER = false
        
    // Damage Type of trail
    private constant damagetype BURNDAMAGE = DAMAGE_TYPE_UNKNOWN
        
    // Weapon type of trail
    private constant weapontype BURNWEAPON = WEAPON_TYPE_WHOKNOWS
        
    // Attack type of trail
    private constant attacktype BURNATTACK = ATTACK_TYPE_CHAOS
        
//  -- Hit Config --  \\
        
    // How close you need to be to the caster to take damage
    private constant real TOUCH_RADIUS = 100.
        
    // Should it damage allies
    private constant boolean TOUCH_ALLY = true
        
    // Damage Type of damage
    private constant damagetype TOUCHDAMAGE = DAMAGE_TYPE_UNKNOWN
        
    // Weapon type of damage
    private constant weapontype TOUCHWEAPON = WEAPON_TYPE_WHOKNOWS
        
    // Attack type of damage
    private constant attacktype TOUCHATTACK = ATTACK_TYPE_CHAOS
    
endglobals

// =================================
// === C O N F I G U R A T I O N ===
// =================================
    // == F U N C T I O N S == \\
    
//  -- General Config --  \\
    
    // How long the spell lasts. 'level' is the ability level.
    private constant function DURATION takes integer level returns real
        return 5 + level * 5.
        // 10, 15, 20 seconds
    endfunction
    
//  -- Trial Config --  \\    
    
    // Which units should be affected
    private constant function BurnDamageFilter takes nothing returns boolean
        return IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING) == false
    endfunction
    
    // How much damage is taken, per second.
    private constant function BURNDAMAGE_AMOUNT takes integer level returns real
        return level * 100.
        // 100, 200, 300
    endfunction
    
//  -- Hit Config --  \\     
    
    // Which units should be affected
    private constant function TouchDamageFilter takes nothing returns boolean
        return IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING) == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false
    endfunction
    
    // How much damage is taken, per second.
    private constant function TOUCHDAMAGE_AMOUNT takes integer level returns real
        return level * 200.
        // 200, 400, 600
    endfunction
    
// ============================================================== \\
//  =  D O   N O T   E D I T   B E L O W   T H I S   L I N E   =  \\
// ============================================================== \\
    
    globals
        private boolexpr FiltTrue
        private boolexpr DamageFilt
        private boolexpr TouchFilt
        private boolexpr FiltTree
        private real MinX = GetRectMinX(bj_mapInitialPlayableArea)
        private real MinY = GetRectMinY(bj_mapInitialPlayableArea)
        private real MaxX = GetRectMaxX(bj_mapInitialPlayableArea)
        private real MaxY = GetRectMaxY(bj_mapInitialPlayableArea)
        private unit TREE
        private trigger Trig
        private group Casters
    endglobals
    
    private struct Data
        unit caster
        unit dummy
        effect main
        effect another
        real x
        real y
        real facing
        real ticks
        static group G = CreateGroup()
        
        private static method Turn takes nothing returns nothing
            local unit u = GetTriggerUnit()
            call SetUnitFacing(u, (bj_RADTODEG * Atan2(GetOrderPointY() - GetUnitY(u), GetOrderPointX() - GetUnitX(u))))
            call TriggerSleepAction(0)
            call IssueImmediateOrder(u, "stop")
            set u = null
        endmethod
        
        private static method Cond takes nothing returns boolean
            return GetIssuedOrderId() == OrderId("move") or GetIssuedOrderId() == OrderId("smart") or GetIssuedOrderId() == OrderId("patrol") or GetIssuedOrderId() == OrderId("attack") and IsUnitInGroup(GetTriggerUnit(), Casters)
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call DestroyEffect(.main)
            call DestroyEffect(.another)
            call ShowUnit(.dummy, false)
            call KillUnit(.dummy)
            call SetUnitVertexColor(.caster, 255, 255, 255, 255)
            call SetUnitPathing(.caster, true)
            call GroupRemoveUnit(Casters, .caster)
        endmethod
        
        public static method create takes unit u returns Data
            local Data this = Data.allocate()
            set .caster = u
            set .x = GetUnitX(.caster)
            set .y = GetUnitY(.caster)
            set .facing = GetUnitFacing(.caster)
            set .ticks = 0.
            call GroupAddUnit(Casters, .caster)
            call SetUnitPathing(.caster, false)
            return this
        endmethod
        
        private static method onInit takes nothing returns nothing
            set Trig = CreateTrigger()
            call TriggerAddCondition(Trig, Filter( function Data.Cond))
            call TriggerAddAction(Trig, function Data.Turn)
        endmethod
        
    endstruct
    
    private function True takes nothing returns boolean
        return true
    endfunction
    
    private struct TimedEffect
        effect eff
        timer stop
        unit caster
        real ticks
        real x
        real y
        static group G = CreateGroup()
        
        private method onDestroy takes nothing returns nothing
            // ABC Function:
            call ClearTimerStructA(.stop)
            // ------------
            call DestroyEffect(.eff)
            call PauseTimer(.stop)
            call DestroyTimer(.stop)
        endmethod
        
    endstruct
    
    private function TimedEffectB takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local unit u = null
        // ABC Function:
        local TimedEffect a = GetTimerStructA(t)
        // ------------
        if a.ticks >= BURNEFFECT_DURATION then
            set t = null
            call a.destroy()
            return
        endif
        call GroupEnumUnitsInRange(a.G, a.x, a.y, BURN_RADIUS, DamageFilt)
        loop
            set u = FirstOfGroup(a.G)
            exitwhen u == null
            if IsUnitEnemy(u, GetOwningPlayer(a.caster)) then
                call UnitDamageTarget(a.caster, u, BURNDAMAGE_AMOUNT(GetUnitAbilityLevel(a.caster, ID)) * 0.1, false, false, BURNATTACK, BURNDAMAGE, BURNWEAPON)
            elseif BURN_ALLY and u != a.caster then
                call UnitDamageTarget(a.caster, u, BURNDAMAGE_AMOUNT(GetUnitAbilityLevel(a.caster, ID)) * 0.1, false, false, BURNATTACK, BURNDAMAGE, BURNWEAPON)
            elseif BURN_CASTER and u == a.caster then
                call UnitDamageTarget(a.caster, u, BURNDAMAGE_AMOUNT(GetUnitAbilityLevel(a.caster, ID)) * 0.1, false, false, BURNATTACK, BURNDAMAGE, BURNWEAPON)
            endif
            call GroupRemoveUnit(a.G, u)
        endloop
        set t = null
        set a.ticks = a.ticks + 0.1
    endfunction
    
    private function TimedEffectA takes real x, real y, unit u returns nothing
        local TimedEffect a = TimedEffect.create()
        set a.stop = CreateTimer()
        set a.eff = AddSpecialEffect(BURNEFFECT, x, y)
        set a.caster = u
        set a.ticks = 0.
        set a.x = x
        set a.y = y
        // ABC Function:
        call SetTimerStructA(a.stop, a)
        // ------------
        call TimerStart(a.stop, 0.1, true, function TimedEffectB)
    endfunction
    
    // Credits to PitzerMike. Modified slightly.
    private function TreeFilter takes nothing returns boolean
        local destructable d = GetFilterDestructable()
        local boolean b
        call ShowUnit(TREE, true)
        call SetUnitX(TREE, GetWidgetX(d))
        call SetUnitY(TREE, GetWidgetY(d))
        set b = IssueTargetOrder(TREE, "harvest", d)
        call IssueImmediateOrder(TREE, "stop")
        call ShowUnit(TREE, false)
        if b then
            call KillDestructable(d)
        endif
        set d = null
        return false
    endfunction
    
    private function SafeX takes real x returns real
        if x > MaxX then
            return MaxX
        elseif x < MinX then
            return MinX
        endif
        return x
    endfunction
    
    private function SafeY takes real y returns real
        if y > MaxY then
            return MaxY
        elseif y < MinY then
            return MinY
        endif
        return y
    endfunction
    
    private function Expire takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local unit u
        local rect r = null
        // ABC Function:
        local Data d = GetTimerStructA(t)
        // ------------
        call TimedEffectA(d.x, d.y, d.caster)
        set d.facing = GetUnitFacing(d.caster)
        set d.x = SafeX(d.x + SPEED * TIMEOUT * Cos(d.facing * bj_DEGTORAD))
        set d.y = SafeY(d.y + SPEED * TIMEOUT * Sin(d.facing * bj_DEGTORAD))
        call SetUnitX(d.dummy, d.x)
        call SetUnitY(d.dummy, d.y)
        call SetUnitX(d.caster, d.x)
        call SetUnitY(d.caster, d.y)
        call GroupEnumUnitsInRange(d.G, d.x, d.y, TOUCH_RADIUS, TouchFilt)
        loop
            set u = FirstOfGroup(d.G)
            exitwhen u == null
            if IsUnitEnemy(u, GetOwningPlayer(d.caster)) then
                call UnitDamageTarget(d.caster, u, TOUCHDAMAGE_AMOUNT(GetUnitAbilityLevel(d.caster, ID)) * TIMEOUT, false, false, TOUCHATTACK, TOUCHDAMAGE, TOUCHWEAPON)
            elseif TOUCH_ALLY and u != d.caster then
                call UnitDamageTarget(d.caster, u, TOUCHDAMAGE_AMOUNT(GetUnitAbilityLevel(d.caster, ID)) * TIMEOUT, false, false, TOUCHATTACK, TOUCHDAMAGE, TOUCHWEAPON)
            endif
            call GroupRemoveUnit(d.G, u)
        endloop
        if TREES then
            set r = Rect(d.x - TOUCH_RADIUS, d.y - TOUCH_RADIUS, d.x + TOUCH_RADIUS, d.y + TOUCH_RADIUS)
            call EnumDestructablesInRect(r, FiltTree, function DoNothing)
            call RemoveRect(r)
            set r = null
        endif
        call SetUnitFacing(d.dummy, d.facing)
        set d.ticks = d.ticks + TIMEOUT
        if d.ticks > DURATION(GetUnitAbilityLevel(d.caster, ID)) or GetWidgetLife(d.caster) <= 0.405 then
            // ABC Function:
            call ClearTimerStructA(t)
            // ------------
            call PauseTimer(t)
            call DestroyTimer(t)
            call d.destroy()
        endif
        set t = null
    endfunction
    
    private function Action takes nothing returns nothing
        local Data d = Data.create(GetTriggerUnit())
        local timer t = CreateTimer()
        set d.dummy = CreateUnit(GetOwningPlayer(d.caster), DUMMY, d.x, d.y, d.facing)
        call UnitAddAbility(d.dummy, CROW)
        call UnitRemoveAbility(d.dummy, CROW)
        call SetUnitFlyHeight(d.dummy, HEIGHT, 0.)
        call SetUnitVertexColor(d.caster, 255, 255, 255, ALPHA)
        set d.main = AddSpecialEffectTarget(UNITEFFECT, d.dummy, "origin")
        set d.another = AddSpecialEffectTarget(ANOTHEREFFECT, d.dummy, "origin")
        // ABC Function:
        call SetTimerStructA(t, d)
        // ------------
        call TimerStart(t, TIMEOUT, true, function Expire)
        set t = null
    endfunction
    
    private function Cond takes nothing returns boolean
        return GetSpellAbilityId() == ID
    endfunction

    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i = 0
        set MinX = GetRectMinX(bj_mapInitialPlayableArea)
        set MinY = GetRectMinY(bj_mapInitialPlayableArea)
        set MaxX = GetRectMaxX(bj_mapInitialPlayableArea)
        set MaxY = GetRectMaxY(bj_mapInitialPlayableArea)
        set FiltTrue = Filter(function True)
        set DamageFilt = Filter(function BurnDamageFilter)
        set TouchFilt = Filter(function TouchDamageFilter)
        set FiltTree = Filter(function TreeFilter)
        loop
            exitwhen i > 15
            call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, FiltTrue)
            call TriggerRegisterPlayerUnitEvent(Trig, Player(i), EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, FiltTrue)
            set i = i + 1
        endloop
        call TriggerAddAction(t, function Action)
        call TriggerAddCondition(t, Filter(function Cond))
        set TREE = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), TREEDUMMY, 0, 0, 0)
        call SetUnitPathing(TREE, false)
        call UnitAddAbility(TREE, 'Aloc')
        call UnitAddAbility(TREE, HARVEST)
        call ShowUnit(TREE, false)
        call Preload(BURNEFFECT)
        call Preload(UNITEFFECT)
        call Preload(UNITEFFECT)
        call PreloadEnd(0.5)
        set Casters = CreateGroup()
    endfunction

endscope


Requires ABC

The Map:
 

Attachments

  • [Spell] Roller.w3x
    51.5 KB · Views: 485
  • [Spell] Roller v2.w3x
    45.3 KB · Views: 653

Kenny

Back for now.
Reaction score
202
Hahaha, man i was just thinking of making this spell, weird how something like this always seems to happen. Ah well, looks awesome from the picture, and by the look of the code, a bit more complicated then i imagined mine. I shall test it when i can, nice work. +rep.

*EDIT*

Just tried it, and its a bit different to what i thought it would be. I didn't exactly read the post lol. But its still heaps mad. I like how it just keeps rolling around, and the line of fire makes it a bit more fun too. One thing you may want to fix is that if u use the spell again before its over, you will have another panda just standing there floating around. Not massive, because you can just make the cd longer, but yeah can't be too hard to fix.
 

Romek

Super Moderator
Reaction score
963
Hahaha, man i was just thinking of making this spell, weird how something like this always seems to happen. Ah well, looks awesome from the picture, and by the look of the code, a bit more complicated then i imagined mine. I shall test it when i can, nice work. +rep.

Thanks :) A lot of the extra code is for the trees and the trial.
Rolling around itself would make the code half as long. I literally made a mini-system for the effects :p

Just tried it, and its a bit different to what i thought it would be. I didn't exactly read the post lol. But its still heaps mad. I like how it just keeps rolling around, and the line of fire makes it a bit more fun too. One thing you may want to fix is that if u use the spell again before its over, you will have another panda just standing there floating around. Not massive, because you can just make the cd longer, but yeah can't be too hard to fix.

Just make the cooldown longer. Thanks for the comments :)
 

Furby

Current occupation: News poster
Reaction score
144
Looks interesting!:thup:
And it is originally
;)+rep
 

Romek

Super Moderator
Reaction score
963

Romek

Super Moderator
Reaction score
963
Do a panda roll!
Haven't you got anything more to say than that?

Comments on the Spell / EyeCandy / Code?

Edit: Added Preloading functions to the spell :)
 

gameman

It's been a long, long time.
Reaction score
95
I love your spell, mainly Its because It sets a fire trail! Now that's eye candy.
 

Romek

Super Moderator
Reaction score
963
I love your spell, mainly Its because It sets a fire trail! Now that's eye candy.
Thanks.
Noone has commented on the actual code yet. :)
 

Viikuna

No Marlo no game.
Reaction score
265
I didnt read your code fully trought, but it looks good. What else you want us to say?


EDIT. Actually it reminded me that I should not forgot preloading my effects. gj :)

EDIT2. I would have used some other system instead of ABC, but it is fine too, Im not complaining.

EDIT3. Why dont you use some global group here? I mean that you dont have to create a new one everytime, right?
JASS:
       set g = CreateGroup()
        call GroupEnumUnitsInRange(g, a.x, a.y, BURN_RADIUS, DamageFilt)
        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            if IsUnitEnemy(u, GetOwningPlayer(a.caster)) then
                call UnitDamageTarget(a.caster, u, BURNDAMAGE_AMOUNT(GetUnitAbilityLevel(a.caster, ID)) * 0.1, false, false, BURNATTACK, BURNDAMAGE, BURNWEAPON)
            elseif BURN_ALLY and u != a.caster then
                call UnitDamageTarget(a.caster, u, BURNDAMAGE_AMOUNT(GetUnitAbilityLevel(a.caster, ID)) * 0.1, false, false, BURNATTACK, BURNDAMAGE, BURNWEAPON)
            elseif BURN_CASTER and u == a.caster then
                call UnitDamageTarget(a.caster, u, BURNDAMAGE_AMOUNT(GetUnitAbilityLevel(a.caster, ID)) * 0.1, false, false, BURNATTACK, BURNDAMAGE, BURNWEAPON)
            endif
            call GroupRemoveUnit(g, u)
        endloop
        call DestroyGroup(g)
        set g = null


EDIT4. I have heard that dynamic triggers are bad, maybe you should consider removing them? I mean that Unit Is Issued Order -trigger. Couldnt you just replace that thing with a one trigger and use buff or some other condition to check if unit is rolling?

EDIT5. Anyways, it is a cool spell, but you need to name your test maps better. Just another warcraft III map ??? Jesus..
 

Romek

Super Moderator
Reaction score
963
I didnt read your code fully trought, but it looks good. What else you want us to say?


EDIT. Actually it reminded me that I should not forgot preloading my effects. gj :)
Comments, Criticism, Suggestions.
Thanks for looking over it.
 

Romek

Super Moderator
Reaction score
963
I added some more comments. :)
Thanks.

EDIT. Actually it reminded me that I should not forgot preloading my effects. gj
Good :p

EDIT2. I would have used some other system instead of ABC, but it is fine too, Im not complaining.
ABC is the best. And is someone with a leaking map would want to use this, it won't do any harm :)

EDIT3. Why dont you use some global group here? I mean that you dont have to create a new one everytime, right?
It's easier to create a local group. I also don't have to do anything fancy when I'm using a group-loop, as the group ends up empty by the end of the trigger.

I have heard that dynamic triggers are bad, maybe you should consider removing them?
They are bad, but the trigger-related stuff are global. Even so, the trigger isn't really necessary, I could create a no-trigger version. (The trigger stops the panda spinning around a single spot which it'll never be able to reach when it is ordered to move)
 

Viikuna

No Marlo no game.
Reaction score
265
It's easier to create a local group. I also don't have to do anything fancy when I'm using a group-loop, as the group ends up empty by the end of the trigger.

I still dont get how this differs from using only one group, expect that you need to create&destroy your groups, which is kinda useless.

I edited that post 5 times, btw. I hope that there is enought comments for you. :)
 

Flare

Stops copies me!
Reaction score
662
Why exactly do you need to oversize the TimedEffect struct? It's highly unlikely you will ever need the extra capacity and even if you do, your PC will probably have melted already from so many SFX

A multiple of 8191 is strongly suggested.
Why 8191? And if it's related to default struct instance limit, I believe the default limit is 8190 anyway :p

And you should replace that dynamic trigger (or, at the very least, get rid of the triggeraction, they can't be removed fully from what I know and, as a result, cause leaks) - you could use a single trigger, and check if the unit issued the order was in a specific global group, and if so, change it's facing

Attack type of trial
It's trail, not trial ^_^

call SetUnitVertexColor(d.caster, 255, 255, 255, ALPHA)
Configurable is win :)

Also, any particular reason why you added a constant for Crow Form? Unless people are stupid and decided to delete it, it's not really needed since it's going to be the same in every map (and, to be honest, if people are dumb enough to delete it, they deserve what they get :p)


Also, this seems very similar (judging by screenshot/description) to a spell made by Anitarf (I think, not 100% sure) :\ Not sure if his had flaming trail/turning order stuff, but it had bounce, which is more awesome anyway :D
 

Romek

Super Moderator
Reaction score
963
I still dont get how this differs from using only one group, expect that you need to create&destroy your groups, which is kinda useless.

I edited that post 5 times, btw. I hope that there is enought comments for you. :)
[del]If I was using a global group, I'd need to use GroupAddGroup to a local group anyway, then use the group-loop.[/del]
Actually, I see what you mean.
I'll change that later :)

Thanks for the feedback.

Edit:
Why exactly do you need to oversize the TimedEffect struct? It's highly unlikely you will ever need the extra capacity and even if you do, your PC will probably have melted already from so many SFX
I think it's needed. There are much, much more effects than Data structs when this spell is cast, so the MUI limit is pretty small :p

Why 8191? And if it's related to default struct instance limit, I believe the default limit is 8190 anyway :p
Forgot that 0 is null. Will fix :)

And you should replace that dynamic trigger (or, at the very least, get rid of the triggeraction, they can't be removed fully from what I know and, as a result, cause leaks) - you could use a single trigger, and check if the unit issued the order was in a specific global group, and if so, change it's facing
Good idea, thanks.

It's trail, not trial ^_^
Typo + Copy and Paste = Fail :D
Wait, I did it everywhere!
How did I manage that? :confused:

Configurable is win :)
...It's not needed there. The point is to make the original caster invisible (Yet selectable) while the dummy model and effect move around.

Also, any particular reason why you added a constant for Crow Form? Unless people are stupid and decided to delete it, it's not really needed since it's going to be the same in every map (and, to be honest, if people are dumb enough to delete it, they deserve what they get :p)
People could modify it. ;)

Also, this seems very similar (judging by screenshot/description) to a spell made by Anitarf (I think, not 100% sure) :\ Not sure if his had flaming trail/turning order stuff, but it had bounce, which is more awesome anyway :D
...Link?
 

Flare

Stops copies me!
Reaction score
662
I think it's needed. There are much, much more effects than Data structs when this spell is cast, so the MUI limit is pretty small
As I said, your PC will probably have melted by that stage anyway, so the extra space would end up unused anyway.

And, with the default values, you'd need about 70 simultaneous instances to reach the default struct size limitations, which, combined with the insane amount of SFX, would be a far more worrying situation (since 70 things moving simultaneously WILL lag, unless you have an awesome PC, which not everyone does). That, and 70 instances is fairly difficult to achieve unless the unit is a normal unit, and everyone has lots of them


Also, perhaps you could add a configurable that determines how often the effects are spawned, rather than forcing them to be spawned every timer interval. Would go a long way to avoiding any potential lag from the spell (since, obviously, 1 effect every 0.1 seconds is far less intensive than 1 effect every 0.03125 seconds)

WC3C appears to be down :( It was a long time ago when I tried it, but it definitely exists - smashing into gnolls is quite fun :D

People could modify it.
I don't think you can modify the rawcode of an existing spell (I believe you have to CnP or Create Custom Spell to get any access to rawcodes) - anyway, if someone does that, they're being an idiot, and lessons must be thought :]
 

Romek

Super Moderator
Reaction score
963
As I said, your PC will probably have melted by that stage anyway, so the extra space would end up unused anyway.

And, with the default values, you'd need about 70 simultaneous instances to reach the default struct size limitations, which, combined with the insane amount of SFX, would be a far more worrying situation (since 70 things moving simultaneously WILL lag, unless you have an awesome PC, which not everyone does). That, and 70 instances is fairly difficult to achieve unless the unit is a normal unit, and everyone has lots of them
Fine.. Removed the Constant there.
I'll upload the new version soon.

Also, perhaps you could add a configurable that determines how often the effects are spawned, rather than forcing them to be spawned every timer interval. Would go a long way to avoiding any potential lag from the spell (since, obviously, 1 effect every 0.1 seconds is far less intensive than 1 effect every 0.03125 seconds)
Maybe.

WC3C appears to be down :( It was a long time ago when I tried it, but it definitely exists - smashing into gnolls is quite fun :D
Hmm.. I think the Trail is better than Bouncing btw.
I could do bounce as well here though :p

I don't think you can modify the rawcode of an existing spell (I believe you have to CnP or Create Custom Spell to get any access to rawcodes) - anyway, if someone does that, they're being an idiot, and lessons must be thought :]
What if they made CrowForm a spell, which made every unit in a 1000 AoE invulnerable, and removing the spell bugged the effect up? :D

Edited! Posted v2.
 

Fluffball

Well-Known Member
Reaction score
35
Uhm, I know virtually nothing about vJASS, but I don't think you added a configurable damage .

Nice spell, good eye candy.

EDIT: Woops, only read the global configuration, not the function config :banghead:
 
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