[Log in / Register]
| News | Chat | Pastebin | Donations | Tutorials | Rules | Forums | Starcraft II |
| Maps | Skins | Icons | Models | Spells | Tools | Jass | Packs |
(Keeps Hive Alive)
Go Back   The Hive Workshop > Warcraft III Modding > Triggers & Scripts

Triggers & Scripts Discussions regarding GUI triggers & JASS/AI scripts may be found here. Please review the » JASS Tutorials » Trigger Tutorials

Closed Thread
 
LinkBack Thread Tools
Old 02-08-2010, 01:05 PM   #1 (permalink)
Registered User Justify
User
 
Justify's Avatar
 
Join Date: Mar 2008
Posts: 863
Justify is a jewel in the rough (205)Justify is a jewel in the rough (205)
Spell causing a huge lag

I've recreated a spell of mine and it is completly finished, but when casting it on units it creates a huge lag. It's supposed to create two missles, each flying on it's own path and damaging units once. If a unit gets struck by both, a special effect should happen, but that's not inserted fully at the moment.

However, if I cast it on three creeps the game lags like hell for this moment:
code
Jass:
scope ChillingStreams initializer InitStreams

    private keyword Streams

    globals
        private constant    integer SPELL_ID        = 'A000'
        private constant    integer STUN_ID         = 'A001'
        private constant    integer BUFF_ID         = 'B000'
        
        private constant    real    PERIOD          = 0.04
        
        private constant    string  SFX_PATH        = "Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl"
        private constant    string  SFX_ATTACH      = "chest"
        
        private constant    real    SPEED           = 400.
        
        private constant    real    SIDEDIST        = 100.
        private constant    real    COLLISION       = 100.
        
        private constant    integer MISSLE_COUNT    = 2
        
        private constant    real    STEP            = SPEED*PERIOD
        
        private             Streams TempStream
        private             integer Current
        
        private integer test = 0
    endglobals
    
    
    private constant function GetMaxDist takes integer lvl returns real
        return 500.+lvl*200.
    endfunction
    
    private constant function GetDamage takes integer lvl returns real
        return lvl*70.
    endfunction
    

    private struct Streams
        private unit            caster
        private player          owner
        
        private unit    array   missle[MISSLE_COUNT]
        private effect  array   sfx[MISSLE_COUNT]
        private real    array   vecx[MISSLE_COUNT]
        private real    array   vecy[MISSLE_COUNT]
        
        private group   array   hit[MISSLE_COUNT]
        
        private real            dist
        private real            maxdist
        
        private real            damage
        
        private timer           movetim
        
        
        method onDestroy takes nothing returns nothing
            local integer i = 0
            
            set .caster = null
            loop
                exitwhen i >= MISSLE_COUNT
                call ReleaseDummy(.missle[i])
                call DestroyEffect(.sfx[i])
                set .sfx[i] = null
                call ReleaseGroup(.hit[i])
                set .hit[i] = null
                set i = i+1
            endloop
            call ReleaseTimer(movetim)
        endmethod
        
        static method collisionCheck takes nothing returns boolean
            local thistype this = TempStream
            local unit u = GetFilterUnit()
            local unit dummy
            local boolean second = false
            
            local integer i = 0
            
            loop
                exitwhen i >= MISSLE_COUNT
                
                if IsUnitInGroup(u, .hit[i]) then
                    if i != Current then
                        set second = true
                    else
                        return false
                    endif
                else
                    set i = i+1
                endif
            endloop
            
            set test = test+1
            call BJDebugMsg(I2S(test))
            call BJDebugMsg(GetPlayerName(.owner))
            
            if GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, .owner) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
                call UnitDamageTarget(.caster, u, .damage, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                call GroupAddUnit(.hit[Current], u)
                call BJDebugMsg("Damage")
                if second then
                    set dummy = NewDummy(GetUnitX(u), GetUnitY(u), 0.)
                    call UnitAddAbility(dummy, STUN_ID)
                    call IssueTargetOrder(dummy, "thunderbolt", u)
                    call ReleaseDummy(dummy)
                endif
            endif
            
            return false
        endmethod 
        
        static method movement takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            
            local real x
            local real y
            
            local integer i = 0
            
            set TempStream = this
            
            loop
                exitwhen i >= MISSLE_COUNT
                
                set x = GetUnitX(.missle[i])+.vecx[i]
                set y = GetUnitY(.missle[i])+.vecy[i]
                
                call SetUnitX(.missle[i], x)
                call SetUnitY(.missle[i], y)
                
                set Current = i                
                call GroupEnumUnitsInArea(ENUM_GROUP, x, y, COLLISION, Condition(function thistype.collisionCheck))
                
                set i = i+1
            endloop
            
            set .dist = .dist+STEP
            if .dist >= .maxdist then
                call .destroy()
            endif
        endmethod
        
        static method createStreams takes nothing returns nothing
            local thistype this = thistype.allocate()
            
            local real spellx = GetSpellTargetX() 
            local real spelly = GetSpellTargetY()
            local real x
            local real y
            local real casterx
            local real castery
            local real angle
            local real facing
            
            local integer i = 0
            
            set .caster = GetTriggerUnit()
            set casterx = GetUnitX(.caster)
            set castery = GetUnitY(.caster)
            set facing  = Atan2(spelly-castery, spellx-casterx)
            set .owner  = GetOwningPlayer(.caster)
            
            loop
                exitwhen i >= MISSLE_COUNT
                
                set facing = facing+bj_PI*(i+1)/2
                set x = PolarX(casterx, facing, SIDEDIST)
                set y = PolarY(castery, facing, SIDEDIST)
                set angle = Atan2(spelly-y, spellx-x)
                
                set .missle[i] = NewDummy(x, y, angle)
                call AddSpecialEffectTarget(SFX_PATH, .missle[i], SFX_ATTACH)
                set .vecx[i] = PolarX(0, angle, STEP)
                set .vecy[i] = PolarY(0, angle, STEP)
                
                set .hit[i] = NewGroup()
                
                set i = i+1
            endloop
                
            set .dist = 0.
            set .maxdist = GetMaxDist(GetUnitAbilityLevel(.caster, SPELL_ID))
            
            set .damage = GetDamage(GetUnitAbilityLevel(.caster, SPELL_ID))
            
            set .movetim = NewTimer()
            call SetTimerData(.movetim, this)
            call TimerStart(.movetim, PERIOD, true, function thistype.movement)
        endmethod
    endstruct

    private function InitStreams takes nothing returns nothing
        call RegisterSpellAction(SPELL_ID, Streams.createStreams)
    endfunction
endscope

For debugging, "test" counts the picked units. After 5 spells this value is around 800, seems to be ok for 0.04 evaluations per second and picks each time. The owner is also correct, but damage is displayed only once for three creeps. I also used the blizzard pick-natives, same result.

Greets, Justify
__________________
My Spells
My Models
Survival Spellpack Simple Axe

Last edited by Justify; 02-08-2010 at 03:53 PM.
Justify is offline  
Old 02-08-2010, 11:09 PM   #2 (permalink)
Forum Moderator PurgeandFire111
User Title
 
PurgeandFire111's Avatar
Tutorial Moderator
 
Join Date: Nov 2006
Posts: 1,812
PurgeandFire111 is a glorious beacon of light (451)PurgeandFire111 is a glorious beacon of light (451)PurgeandFire111 is a glorious beacon of light (451)
At first glance I'd think it to be just in general due to loops within timers and the collision check, but I don't know if that is necessarily it. From what I can tell, you don't have any leaks other than maybe nulling your unit vars in collisionCheck, and as far as I know boolexprs don't need to be/shouldn't be destroyed.

I'd suggest attaching a test map, but otherwise you can try // commenting out the debug messages and special effects and see if that has an impact on it. This way you can tell whether it is your computer or the actual code itself.
__________________
Vote For The Hive Workshop!
PurgeandFire111 is offline  
Old 02-09-2010, 10:14 AM   #3 (permalink)
Registered User Justify
User
 
Justify's Avatar
 
Join Date: Mar 2008
Posts: 863
Justify is a jewel in the rough (205)Justify is a jewel in the rough (205)
The loop was the problem, but not just because it's a loop.
In case that the unit was hit once, the second hit was an endless loop.
I didn't think of this possibility because my computer normaly completly laggs and you can end warcraft because nothing works in such situations.
However, the code isn't lagging anymore, but units can be struck twice (they get stunned) but they take damage even more often. Why?
The current instance is safed in "current" and if the unit is already in the "current" group the emthod should return false and end.

code
Jass:
scope ChillingStreams initializer InitStreams

    private keyword Streams

    globals
        private constant    integer SPELL_ID        = 'A000'
        private constant    integer STUN_ID         = 'A001'
        private constant    integer BUFF_ID         = 'B000'
        
        private constant    real    PERIOD          = 0.04
        
        private constant    string  SFX_PATH        = "Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl"
        private constant    string  SFX_ATTACH      = "chest"
        
        private constant    real    SPEED           = 400.
        
        private constant    real    SIDEDIST        = 100.
        private constant    real    COLLISION       = 100.
        
        private constant    integer MISSLE_COUNT    = 2
        
        private constant    real    STEP            = SPEED*PERIOD
        
        private             Streams TempStream
        private             integer Current
        
        private integer test = 0
    endglobals
    
    
    private constant function GetMaxDist takes integer lvl returns real
        return 500.+lvl*200.
    endfunction
    
    private constant function GetDamage takes integer lvl returns real
        return lvl*70.
    endfunction
    

    private struct Streams
        private unit            caster
        private player          owner
        
        private unit    array   missle[MISSLE_COUNT]
        private effect  array   sfx[MISSLE_COUNT]
        private real    array   vecx[MISSLE_COUNT]
        private real    array   vecy[MISSLE_COUNT]
        
        private group   array   hit[MISSLE_COUNT]
        
        private real            dist
        private real            maxdist
        
        private real            damage
        
        private timer           movetim
        
        
        method onDestroy takes nothing returns nothing
            local integer i = 0
            
            set .caster = null
            loop
                exitwhen i >= MISSLE_COUNT
                call ReleaseDummy(.missle[i])
                call DestroyEffect(.sfx[i])
                set .sfx[i] = null
                call ReleaseGroup(.hit[i])
                set .hit[i] = null
                set i = i+1
            endloop
            call ReleaseTimer(movetim)
        endmethod
        
        static method collisionCheck takes nothing returns boolean
            local thistype this = TempStream
            local unit u = GetFilterUnit()
            local unit dummy
            local boolean second = false
            
            local integer i = 0
            
            loop
                exitwhen i >= MISSLE_COUNT
                
                if IsUnitInGroup(u, .hit[i]) then
                    if i != Current then
                        set second = true
                        set i = MISSLE_COUNT
                    else
                        return false
                    endif
                else
                    set i = i+1
                endif
            endloop
            
            set test = test+1
            
            if GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, .owner) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
                call UnitDamageTarget(.caster, u, .damage, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                call GroupAddUnit(.hit[Current], u)
                if second then
                    set dummy = NewDummy(GetUnitX(u), GetUnitY(u), 0.)
                    call UnitAddAbility(dummy, STUN_ID)
                    call IssueTargetOrder(dummy, "thunderbolt", u)
                    call ReleaseDummy(dummy)
                endif
            endif
            
            set u = null
            
            return false
        endmethod 
        
        static method movement takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            
            local real x
            local real y
            
            local integer i = 0
            
            set TempStream = this
            
            loop
                exitwhen i >= MISSLE_COUNT
                
                set x = GetUnitX(.missle[i])+.vecx[i]
                set y = GetUnitY(.missle[i])+.vecy[i]
                
                call SetUnitX(.missle[i], x)
                call SetUnitY(.missle[i], y)
                
                set Current = i                
                call GroupEnumUnitsInArea(ENUM_GROUP, x, y, COLLISION, Condition(function thistype.collisionCheck))
                
                set i = i+1
            endloop
            
            set .dist = .dist+STEP
            if .dist >= .maxdist then
                call .destroy()
            endif
        endmethod
        
        static method createStreams takes nothing returns nothing
            local thistype this = thistype.allocate()
            
            local real spellx = GetSpellTargetX() 
            local real spelly = GetSpellTargetY()
            local real x
            local real y
            local real casterx
            local real castery
            local real angle
            local real facing
            
            local integer i = 0
            
            set .caster = GetTriggerUnit()
            set casterx = GetUnitX(.caster)
            set castery = GetUnitY(.caster)
            set facing  = Atan2(spelly-castery, spellx-casterx)
            set .owner  = GetOwningPlayer(.caster)
            
            loop
                exitwhen i >= MISSLE_COUNT
                
                set facing = facing+bj_PI*(i+1)/2
                set x = PolarX(casterx, facing, SIDEDIST)
                set y = PolarY(castery, facing, SIDEDIST)
                set angle = Atan2(spelly-y, spellx-x)
                
                set .missle[i] = NewDummy(x, y, angle)
                call AddSpecialEffectTarget(SFX_PATH, .missle[i], SFX_ATTACH)
                set .vecx[i] = PolarX(0, angle, STEP)
                set .vecy[i] = PolarY(0, angle, STEP)
                
                set .hit[i] = NewGroup()
                
                set i = i+1
            endloop
                
            set .dist = 0.
            set .maxdist = GetMaxDist(GetUnitAbilityLevel(.caster, SPELL_ID))
            
            set .damage = GetDamage(GetUnitAbilityLevel(.caster, SPELL_ID))
            
            set .movetim = NewTimer()
            call SetTimerData(.movetim, this)
            call TimerStart(.movetim, PERIOD, true, function thistype.movement)
        endmethod
    endstruct

    private function InitStreams takes nothing returns nothing
        call RegisterSpellAction(SPELL_ID, Streams.createStreams)
    endfunction
endscope
__________________
My Spells
My Models
Survival Spellpack Simple Axe
Justify is offline  
Old 02-10-2010, 07:08 AM   #4 (permalink)
Registered User scorpion182
comatose
 
scorpion182's Avatar
 
Join Date: Jun 2008
Posts: 557
scorpion182 has a spectacular aura about (147)scorpion182 has a spectacular aura about (147)scorpion182 has a spectacular aura about (147)scorpion182 has a spectacular aura about (147)
Jass:
if GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, .owner) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then

should be

Jass:
if not IsUnitInGroup(u, .hit[i]) and GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, .owner) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
scorpion182 is offline  
Old 02-10-2010, 07:31 AM   #5 (permalink)
Registered User Adiktuz
-MapMaker-JASS/GUI-
 
Adiktuz's Avatar
 
Join Date: Oct 2008
Posts: 1,442
Adiktuz is a jewel in the rough (162)
Quote:
Originally Posted by scorpion182 View Post
Jass:
if GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, .owner) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then

should be

Jass:
if not IsUnitInGroup(u, .hit[i]) and GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, .owner) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
based on other threads: you should use parentheses after not because it overwrites any other checker.... your trigger would work something like this one...

Jass:
if not (IsUnitInGroup(u, .hit[i]) and GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, .owner) and not IsUnitType(u, UNIT_TYPE_STRUCTURE)) then

it should be

Jass:
if (not IsUnitInGroup(u, .hit[i])) and GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, .owner) and (not IsUnitType(u, UNIT_TYPE_STRUCTURE)) then
Adiktuz is offline  
Closed Thread

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Math operations causing lag? Cyclotrutan Triggers & Scripts 12 01-06-2010 06:03 PM
[Trigger] Help My spell is causing lag neku99 Triggers & Scripts 9 09-11-2009 10:45 AM
[Unsolved] Gold specs on ground causing lag hoihoi8 World Editor Help Zone 2 02-01-2009 08:22 PM
[Trigger] What is causing lag every x seconds? Eccho Triggers & Scripts 5 04-05-2008 08:17 PM
Am I the only one with huge WE lag? Furkentine Warcraft Editing Tools 1 12-21-2004 04:06 AM

All times are GMT. The time now is 09:22 PM.





Powered by vBulletin®
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.1
Copyright©Ralle