• 🏆 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!

[vJASS] Massive FPS Drop

Status
Not open for further replies.
I created this spell:
JASS:
library GigaDrain/* 1.0 by Almia
*************************************************************************************
*
*   Giga Drain
*
*       Deals 100/200/300 damage to the target unit, per 0.125 seconds. The caster 
*       then absorbs the damage dealt, healing for 50/60/70 % of the damage dealt.
*       The healing/damage is divided to the number of particles released.
*
*
*************************************************************************************
*
*   */ requires /*
*
*   */MissileRecycler /* hiveworkshop.com/forums/jass-resources-412/system-missilerecycler-206086/
*   */UnitIndexerGUI /* hiveworkshop.com/forums/spells-569/gui-unit-indexer-1-2-0-2-a-197329/
*   */Projection /* hiveworkshop.com/forums/2038279-post655.html
*   */GetUnitCollision /* github.com/nestharus/JASS/blob/master/jass/Systems/GetUnitCollision/script.j
*   */MapBounds /* hiveworkshop.com/forums/jass-resources-412/snippet-mapbounds-222870/
*   */ZLibrary /* hiveworkshop.com/forums/jass-resources-412/snippet-zlibrary-237821/
*   */SpellEffectEvent /* hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193/
*
*************************************************************************************
*
*   Credits
*
*       Nestharus - GUC
*       Bribe - MissileRecycler, UnitIndexer, SpellEffectEvent
*       D.O.G. - ZLibrary
*       Adiktuz - MapBounds
*
*************************************************************************************/

    globals
        /*
        *   ability code
        */
        private constant integer ABIL = 'giga'
        /*
        *   Timeout iteration
        */
        private constant real TIMEOUT = 0.03125
        /*
        *   Damage values
        */
        private constant real DAMAGE_BASE = 0
        private constant real DAMAGE_PER_LEVEL = 100
        /*
        *   attack type and damage type for damage
        */
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_CHAOS
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_UNIVERSAL
        /*
        *   Heal potency (heal = damage*potency)
        */
        private constant real HEAL_POTENCY_BASE = 0.4
        private constant real HEAL_POTENCY_PER_LEVEL = 0.1
        /*
        *   SFX applied to the unit when healed.
        */
        private constant string ON_HEAL_EFFECT = ""
        private constant string ON_HEAL_ATTACH = ""
        /*
        *   SFX applied to the target when damaged.
        */
        private constant string ON_DAMAGE_EFFECT = ""
        private constant string ON_DAMAGE_ATTACH = ""
        /*
        *   Release delay of particles
        */
        private constant real PARTICLE_DELAY = 0.125
        /*
        *   Model of particles
        */
        private constant string PARTICLE_MODEL = "Abilities\\Spells\\Undead\\Possession\\PossessionTarget.mdl"
        /*
        *   Total number of particles released
        */
        private constant real PARTICLE_COUNT = 16
        /*
        *   Bonus z applied to the unit(approximate height of the "chest"
        */
        private constant real UNIT_Z_BONUS = 64
        /*
        *   Time it takes for each particle to transform their appearances
        */
        private constant real APPEARANCE_DURATION = 3.0
        /*
        *   Particle sizes (newSize = random(start - variation, start + variation)
        */
        private constant real START_SIZE = 1.5
        private constant real START_SIZE_VARIATION = 0.5
        private constant real END_SIZE = 0.25
        private constant real END_SIZE_VARIATION = 0.125
        
        private constant integer START_ALPHA = 255
        private constant integer START_ALPHA_VARIATION = 0
        private constant integer END_ALPHA = 255
        private constant integer END_ALPHA_VARIATION = 0
        
        private constant integer START_RED = 0
        private constant integer START_RED_VARIATION = 0
        private constant integer END_RED = 0
        private constant integer END_RED_VARIATION = 0
        
        private constant integer START_GREEN = 255
        private constant integer START_GREEN_VARIATION = 0
        private constant integer END_GREEN = 255
        private constant integer END_GREEN_VARIATION = 0
        
        private constant integer START_BLUE = 0
        private constant integer START_BLUE_VARIATION = 0
        private constant integer END_BLUE = 0
        private constant integer END_BLUE_VARIATION = 0
        /*
        *   Gravitational speed applied to each particles
        *   towards their target
        */
        private constant real GRAVITY = 0.6129375//9.807//4.9035
        /*
        *   Angles of particles when released.
        */
        private constant real ANGLE_START = bj_PI/2
        private constant real ANGLE_VARIATION = bj_PI
        private constant real ANGLE_Z_START = bj_PI/2
        private constant real ANGLE_Z_VARIATION = bj_PI
        /*
        *   How fast the particles travel(also influenced by gravity)
        */
        private constant real OUTWARD_SPEED = 250
        private constant real OUTWARD_SPEED_VARIATION = 125
    endglobals
    
    private function GetDamage takes integer lvl returns real
        return DAMAGE_BASE + DAMAGE_PER_LEVEL*lvl
    endfunction
    
    private function GetParticleDamage takes integer lvl returns real
        return GetDamage(lvl)/PARTICLE_COUNT
    endfunction
    
    private function GetHealPotency takes integer lvl returns real
        return HEAL_POTENCY_BASE + HEAL_POTENCY_PER_LEVEL*lvl
    endfunction
    
    private function GetParticleHeal takes real damage, integer lvl returns real
        return (damage*GetHealPotency(lvl))/PARTICLE_COUNT
    endfunction
    
    private function GetVarianceReal takes real base, real variation returns real
        if variation == 0 then
            return base
        endif
        return GetRandomReal(base - variation, base + variation)
    endfunction
    
    private function GetVarianceInt takes integer base, integer variation returns integer
        if variation == 0 then
            return base
        endif
        return GetRandomInt(base - variation, base + variation)
    endfunction
    
    private function DamageTarget takes unit s, unit t, real amount returns nothing
        call UnitDamageTarget(s, t, amount, false, false, ATTACK_TYPE, DAMAGE_TYPE, null)
    endfunction
    
    private function HealTarget takes unit s, real amount returns nothing
        call SetWidgetLife(s, GetWidgetLife(s) + amount)
    endfunction

    private function SetPitch takes unit u, real pitch returns nothing
        local integer i = R2I(pitch * 57.2957795 + 90.5)
        if (179 < i) then
            set i = 179
        elseif (0 > i) then
            set i = 0
        endif
        call SetUnitAnimationByIndex(u, i)
    endfunction
    
    private function Linear takes real a, real b, real t returns real
        return a + (b - a)*t
    endfunction
    
    private function LinearI takes integer a, integer b, real t returns integer
        return R2I(Linear(I2R(a), I2R(b), t))
    endfunction
    
    private struct Particles
        private unit u
        
        private unit target
        private real csize
        
        private real speed
        private real face
        private real face3d
        
        private real cdur
        
        private real amount
        
        private effect mdl
        
        private real ss
        private integer sa
        private integer sr
        private integer sg
        private integer sb
        
        private real es
        private integer ea
        private integer er
        private integer eg
        private integer eb
        
        private static thistype array p
        private static thistype array n
        
        private static constant timer t = CreateTimer()
        
        method destroy takes nothing returns nothing
            call deallocate()
            set n[p[this]] = n[this]
            set p[n[this]] = p[this]
            if n[0] == 0 then
                call PauseTimer(t)
            endif
            
            call RecycleMissile(u)
            call DestroyEffect(mdl)
            
            set u = null
            set target = null
            set csize = 0
            set speed = 0
            set face = 0
            set face3d = 0
            set cdur = 0
            set amount = 0
            set mdl = null
            set ss = 0
            set sa = 0
            set sr = 0
            set sg = 0
            set sb = 0
            set es = 0
            set ea = 0
            set er = 0
            set eg = 0
            set eb = 0
        endmethod
        
        private static method pr takes nothing returns nothing
            local thistype this = n[0]
            local real angle2
            local real angle3
            local real px
            local real py
            local real pz
            local real dx
            local real dy
            local real dz
            local real nx
            local real ny
            local real nz
            local real dist2d
            local real dist3d
            local real pct
            loop
                exitwhen 0 == this
                /*
                *   Check if target is alive
                */
                if UnitAlive(target) then
                    /*
                    *   if true, initialize coordinates for both the target and the particle
                    */
                    set px = GetUnitX(u)
                    set py = GetUnitY(u)
                    set pz = GetUnitZ(u)
                    set dx = GetUnitX(target)
                    set dy = GetUnitY(target)
                    set dz = GetUnitZ(target) + UNIT_Z_BONUS
                    /*
                    *   Get the 2d and 3d distances
                    */
                    set dist2d = GetMagnitude2D(dx - px, dy - py)
                    set dist3d = GetMagnitude3D(dx - px, dy - py, dz - pz)
                    /*
                    *   Check if particle is within the spherical collision
                    */
                    if dist3d <= csize then
                        /*
                        *   If true, heal the target then destroy the particle
                        */
                        call HealTarget(target, amount)
                        call DestroyEffect(AddSpecialEffectTarget(ON_HEAL_EFFECT, target, ON_HEAL_ATTACH))
                        call destroy()
                    else
                        /*
                        *   if not, get the angle towards the target
                        */
                        set angle2 = GetAngle2D(dx - px, dy - py)
                        set angle3 = GetAngle3D(dist2d, dz - pz)
                        /*
                        *   Get the next coordinates for the unit(w/o gravity)
                        */
                        set nx = px + speed*Cos(face)*Cos(face3d)
                        set ny = py + speed*Sin(face)*Cos(face3d)
                        set nz = pz + speed*Sin(face3d)
                        /*
                        *   Apply gravity for the new coordinates
                        */
                        set nx = nx + GRAVITY*Cos(angle2)*Cos(angle3)
                        set ny = ny + GRAVITY*Sin(angle2)*Cos(angle3)
                        set nz = nz + GRAVITY*Sin(angle3)
                        /*
                        *   Apply new facing
                        */
                        set face = GetAngle2D(nx - px, ny - py)
                        set face3d = GetAngle3D(GetMagnitude2D(nx - px, ny - py), nz - pz)
                        /*
                        *   Move the particle to the coordinates, bounded.
                        */
                        call SetUnitX(u, GetBoundedX(nx))
                        call SetUnitY(u, GetBoundedY(ny))
                        call SetUnitZ(u, nz)
                        /*
                        *   Apply pitch and facing
                        */
                        call SetUnitFacing(u, face*bj_RADTODEG)
                        call SetPitch(u, face3d)
                        /*
                        *   Check if the appearance timer has not yet ended.
                        */
                        if cdur < APPEARANCE_DURATION then
                            /*
                            *   If true, get the percentage of the progress
                            */
                            set cdur = cdur + TIMEOUT
                            set pct = cdur/APPEARANCE_DURATION
                            /*
                            *   Apply linear calculation to get the new appearance values
                            */
                            call SetUnitScale(u, Linear(ss, es, pct), 0, 0)
                            call SetUnitVertexColor(u, LinearI(sr, er, pct), LinearI(sg, eg, pct), LinearI(sb, eb, pct), LinearI(sa, ea, pct))
                        endif
                    endif
                else
                    /*
                    *   Destroy the particle
                    */
                    call destroy()
                endif
                set this = n[this]
            endloop
        endmethod
        
        static method create takes unit source, unit victim, integer level returns thistype
            local thistype this = allocate()
            /*
            *   Get the coordinates of the victim
            */
            local real x = GetUnitX(victim)
            local real y = GetUnitY(victim)
            local real z = GetUnitZ(victim)
            /*
            *   Get the damage
            */
            local real damage = GetParticleDamage(level)
            /*
            *   get the facing
            */
            set face = GetVarianceReal(ANGLE_START, ANGLE_VARIATION)
            set face3d = GetVarianceReal(ANGLE_Z_START, ANGLE_Z_VARIATION)
            /*
            *   create the particles
            */
            set u = GetRecycledMissile(x, y, z, face*bj_RADTODEG)
            call SetPitch(u, face3d)
            /*
            *   Add the model to it.
            */
            set mdl = AddSpecialEffectTarget(PARTICLE_MODEL, u, "origin")
            /*
            *   get the appearance values
            */
            //! textmacro GD_APPEAR takes att, ATT
            set s$att$ = GetVarianceInt(START_$ATT$, START_$ATT$_VARIATION)
            set e$att$ = GetVarianceInt(END_$ATT$, END_$ATT$_VARIATION)
            //! endtextmacro
            //! runtextmacro GD_APPEAR("a", "ALPHA")
            //! runtextmacro GD_APPEAR("r", "RED")
            //! runtextmacro GD_APPEAR("g", "GREEN")
            //! runtextmacro GD_APPEAR("b", "BLUE")
            set ss = GetVarianceReal(START_SIZE, START_SIZE_VARIATION)
            set es = GetVarianceReal(END_SIZE, END_SIZE_VARIATION)
            /*
            *   Apply the appearances
            */
            call SetUnitScale(u, ss, 0, 0)
            call SetUnitVertexColor(u, sr, sg, sb, sa)
            /*
            *   Get the speed of the particle
            */
            set speed = GetVarianceReal(OUTWARD_SPEED, OUTWARD_SPEED_VARIATION)*TIMEOUT
            /*
            *   Damage the target
            */
            call DamageTarget(source, victim, damage)
            /*
            *   Get the heal amount
            */
            set amount = GetParticleHeal(damage, level)
            /*
            *   get the target's collision size
            */
            set target = source
            set csize = GetUnitCollision(target)
            
            set n[this] = 0
            set p[this] = p[0]
            set n[p[0]] = this
            set p[0] = this
            if p[this] == 0 then
                call TimerStart(t, TIMEOUT, true, function thistype.pr)
            endif
            
            return this
        endmethod
    endstruct
    
    private struct GigaDrain
        private integer count
        private real spawnDelay
        
        private unit target
        private unit source
        
        private integer level
        
        private static thistype array p
        private static thistype array n
        
        private static constant timer t = CreateTimer()
        
        private method destroy takes nothing returns nothing
            call deallocate()
            set n[p[this]] = n[this]
            set p[n[this]] = p[this]
            if n[0] == 0 then
                call PauseTimer(t)
            endif
            
            set spawnDelay = 0
            set count = 0
            set level = 0
            set source = null
            set target = null
        endmethod
        
        private static method pr takes nothing returns nothing
            local thistype this = n[0]
            loop
                exitwhen 0 == this
                if count < PARTICLE_COUNT and UnitAlive(target) and UnitAlive(source) then
                    if spawnDelay > 0 then
                        set spawnDelay = spawnDelay - TIMEOUT
                    else
                        set count = count + 1
                        set spawnDelay = PARTICLE_DELAY
                        call Particles.create(source, target, level)
                    endif
                else
                    call destroy()
                endif
                set this = n[this]
            endloop
        endmethod
        
        private static method onCast takes nothing returns boolean
            local thistype this
            local integer i = 0
            local unit s = GetTriggerUnit()
            local unit tg = GetSpellTargetUnit()
            local integer lvl = GetUnitAbilityLevel(s, ABIL)
            if PARTICLE_DELAY < TIMEOUT then
                loop
                    set i = i + 1
                    call Particles.create(s, tg, lvl)
                    exitwhen i == PARTICLE_COUNT
                endloop
            else
                set this = allocate()
                set spawnDelay = PARTICLE_DELAY
                set source = s
                set target = tg
                set level = lvl
                set count = 0
                set n[this] = 0
                set p[this] = p[0]
                set n[p[0]] = this
                set p[0] = this
                if p[this] == 0 then
                    call TimerStart(t, TIMEOUT, true, function thistype.pr)
                endif
            endif
            set s = null
            set tg = null
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(ABIL, function thistype.onCast)
        endmethod
    endstruct
endlibrary

and whenever i cast it, my fps drops so bad :(

curiously tho, this thing(i think it's a barracks model) always show whenever the fps drop:
attachment.php


My guess is that ZLibrary has something to do with it
 

Attachments

  • wut.png
    wut.png
    1,011.2 KB · Views: 178
  • Giga Drain.w3x
    67.1 KB · Views: 41
Status
Not open for further replies.
Top