• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Laggy spell...

Status
Not open for further replies.
Level 11
Joined
Feb 22, 2006
Messages
752
So basically, whenever I cast this spell in my map, it starts lagging REALLY badly. The fps drops to like one frame every 5 seconds. It does not crash the game, it just lags it to hell.

The spell is supposed to create an explosion that knocks enemy units into the air and sends them flying backwards from the target location of the spell, if that matters at all.

The script is in two parts; the first is the actual trigger, the second are the structs and timer callback that actually do all the work. This is because I have multiple spells in my map that require "jump" effects and it seemed a waste to me to declare one struct type and timer for every one of them instead of just making one "master" timer using a single struct type. It also clears up my code a lot.

First part (actual trigger)

JASS:
function InitTrig_Enflame takes nothing returns nothing
    call OnAbilityEffect('A00Z',"Enflame_Actions")
endfunction

//===========================================================================

function Enflame_Actions takes nothing returns nothing
    local jumpdata temp
    local group g = CreateGroup()
    local unit caster = GetTriggerUnit()
    local unit u
    local location targetloc = GetSpellTargetLoc()
    local player p = GetOwningPlayer( caster )
    local real x1 = GetLocationX( targetloc )
    local real y1 = GetLocationY( targetloc )
    local integer level = GetUnitAbilityLevel( caster, 'A00Z' )
    call DestroyEffect( AddSpecialEffect( "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl", x1, y1 ) )
    call GroupEnumUnitsInRange( g, x1, y1, 300.00, null )
    loop
        set u = FirstOfGroup( g )
        exitwhen ( u == null )
        if ( IsUnitEnemy( u, p ) and IsUnitType( u, UNIT_TYPE_STRUCTURE ) == false and IsUnitType( u, UNIT_TYPE_FLYING ) == false and GetWidgetLife( u ) >= 0.405 ) then
            set temp = jumpdata.create()
            call UnitDamageTarget( caster, u, 200 + 100 * level, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_FIRE, WEAPON_TYPE_WHOKNOWS )
            set temp.target = u
            set temp.x1 = x1
            set temp.y1 = y1
            set temp.distance = 10.00
            set temp.flyheight = 200.00
            set temp.flyup = 0.30
            set temp.flydown = 0.20
            if ( jumptotal == 0 ) then
                call TimerStart( jumptimer, 0.04, true, function Jump_Event )
            endif
            set jumparray[jumptotal] = temp
            set jumptotal = jumptotal + 1
        endif
        call GroupRemoveUnit( g, u )
    endloop
    call DestroyGroup( g )
    call RemoveLocation( targetloc )
    set g = null
    set caster = null
    set targetloc = null
    set p = null
endfunction


Second part of script ("master" struct and timer callback as well as the global declarations)

JASS:
struct jumpdata
    unit target
    real x1
    real y1
    real distance
    real flyheight
    real flyup
    real flydown
    integer counter = 0
    boolean flyuptime = true
    boolean destroyplease = false
endstruct

globals
    timer jumptimer = CreateTimer()
    jumpdata array jumparray
    integer jumptotal = 0
endglobals

function Jump_Event takes nothing returns nothing
    local jumpdata temp
    local real targetx
    local real targety
    local real angle
    local real duration
    local integer i = 0
    loop
        set temp = jumparray[i]
        if ( temp.destroyplease ) then
            set jumparray[i] = jumparray[jumptotal - 1]
            set jumptotal = jumptotal - 1
            call temp.destroy()
            set i = i - 1
        else
            set duration = temp.flyup + temp.flydown
            if ( temp.counter >= duration / 0.04 ) then
                call UnitRemoveAbility( temp.target, 'Arav' )
                call PauseUnit( temp.target, false )
                set temp.destroyplease = true
            else
                if ( temp.counter == 0 ) then
                    call PauseUnit( temp.target, true )
                    call UnitAddAbility( temp.target, 'Arav' )
                    call SetUnitFlyHeight( temp.target, temp.flyheight, temp.flyheight / temp.flyup )
                endif
                if ( temp.counter >= temp.flyup / 0.04 and temp.flyuptime ) then
                    call SetUnitFlyHeight( temp.target, 0.00, temp.flyheight / temp.flydown )
                    set temp.flyuptime = false
                endif
                set targetx = GetUnitX( temp.target )
                set targety = GetUnitY( temp.target )
                set angle = GetAngleBetweenPoints( temp.x1, temp.y1, targetx, targety )
                call SetUnitPosition( temp.target, PolarProjectionX( targetx, temp.distance, angle ), PolarProjectionY( targety, temp.distance, angle ) )
                set temp.counter = temp.counter + 1
            endif
        endif
        set i = i + 1
    endloop
    if ( jumptotal == 0 ) then
        call PauseTimer( jumptimer )
    endif
endfunction

I can't find any problems with the script, so I'm turning it over to you guys to see if being the retard I am, I missed something that you can catch.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Thus it loops till the oplimate is reached so wastes CPU power.

Also raise timer times to 0.05 and base it around that, as that is about the peak time that it appears near constant and does not run as much to cause noticable lag. Only if the spell is cast multiple times at the same time as other as demanding spells is this a worry and should happen.
 
Status
Not open for further replies.
Top