• 🏆 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]Giga Drain

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
Was playing Pokemon Black2 last 2 weeks, and some of the special effects/particle effects of the moves there are awesome, specially the Giga Drain. So I created one of my own :D

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/
*   */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, 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 target unit
        */
        private constant string ON_CAST_TARGET_EFFECT = ""
        private constant string ON_CAST_TARGET_ATTACH = ""
        /*
        *   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
        /*
        *   Particles per delay
        */
        private constant integer PARTICLES_PER_DELAY = 4
        /*
        *   Total number of particles released
        */
        private constant integer PARTICLE_COUNT = 32
        /*
        *   Model of particles
        */
        private constant string PARTICLE_MODEL = "Abilities\\Spells\\Undead\\Possession\\PossessionTarget.mdl"
        /*
        *   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
        /*
        *   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
        // the particle
        private unit u
        // it's target and collision size of the target
        private unit target
        private real csize
        // the speed and direction
        private real speed
        private real face
        private real face3d
        // the appearance duration
        private real cdur
        // the amount of heal
        private real amount
      
        private effect mdl
      
        //start scale and argb
        private real ss
        private integer sa
        private integer sr
        private integer sg
        private integer sb
        //end scale and argb
        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 ptz
            local real pz
            local real dx
            local real dy
            local real dtz
            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 ptz = GetSurfaceZ(px, py)
                    set pz = GetUnitFlyHeight(u) + ptz
                    set dx = GetUnitX(target)
                    set dy = GetUnitY(target)
                    set dtz = GetSurfaceZ(dx, dy)
                    set dz = GetUnitFlyHeight(target) + dtz + 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 SetUnitFlyHeight(u, nz - GetSurfaceZ(nx, ny), 0)
                        /*
                        *   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]
            local integer i = 0
            loop
                exitwhen 0 == this
                /*
                *   Check if the count has not yet reached the max count an
                *   if both the source and the target is still alive
                */
                if count < PARTICLE_COUNT and UnitAlive(target) and UnitAlive(source) then
                    /*
                    *   Check if spawn delay has finished
                    */
                    if spawnDelay > 0 then
                        set spawnDelay = spawnDelay - TIMEOUT
                    else
                        /*
                        *   if true, release the particles
                        */
                        loop
                            set i = i + 1
                            set count = count + 1
                            call Particles.create(source, target, level)
                            exitwhen i == PARTICLES_PER_DELAY or count >= PARTICLE_COUNT
                        endloop
                        set i = 0
                        /*
                        *   reset the spawn delay timer
                        */
                        set spawnDelay = PARTICLE_DELAY
                        call DestroyEffect(AddSpecialEffectTarget(ON_DAMAGE_EFFECT, target, ON_DAMAGE_ATTACH))
                    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
          
            call DestroyEffect(AddSpecialEffectTarget(ON_CAST_TARGET_EFFECT, tg, ON_CAST_TARGET_ATTACH))
            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

take note that the particles may orbit the caster forever :D

How to import:
There are priorities here:
1) First, import the MissileRecycler and the ZLibrary, because both of which needs to generate their objects. Save, close map then open again.
2) Import the libraries.
3) Copy the ability to your map (edit the data if you want)
4) Copy the code :D

Keywords:
Giga Drain, Grass, Life Drain, Spell Vamp
Contents

Just another Warcraft III map (Map)

Reviews
Reviewer:KILLCIDE Time:13:53 Date:30 May 2016 Review:Link Status:Awaiting Update

Wrda

Spell Reviewer
Level 25
Joined
Nov 18, 2012
Messages
1,864
Just the amount of library requirements make me want to throw up...:goblin_jawdrop:

JASS:
        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

This will make no one try to review your code since it is confusing :D
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
:)) Why did you use missile GUI

Missile GUI?

also, updated.
I removed the UnitIndexerGUI because i forgot lol. The old code was that it requires UnitIndexer, tho the new code doesn't even use it.

I also added some minor comment blocks in the code.

I also changed the model of the particles to match the the particles of the real Giga Drain :D
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
I just played around ingame a bit without reading your code.
Very cool and fun :).

I think the requirements are totally fine.
Most them are widely used in our databank.

Off:

Missile GUI is still pending and I'm planning to make some changes,
because I discovered a better algorithm for projectile motion.

Thanks :D


also, i think im going to update this tomorrow, it is still dropping the fps when casting the spell multiple times at a short time.

DOg should update his ZLibrary :/
 
Level 14
Joined
Jul 1, 2008
Messages
1,314
I think, that this spell looks pretty good and is a lot of fun! :)

you can confuse the particle movement much by running around though. After running around for too long, it is pretty hard to gather them.. On the one hand, I like it that way, but on the other hand you might add a customizable distance factor, when the healing spots are considered to have hit the caster?
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
I think, that this spell looks pretty good and is a lot of fun! :)

you can confuse the particle movement much by running around though. After running around for too long, it is pretty hard to gather them.. On the one hand, I like it that way, but on the other hand you might add a customizable distance factor, when the healing spots are considered to have hit the caster?

I can add that configuration if you want :D

I'll add it to the update
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
The spell effects were well chosen and look really cool, making it aesthetically pleasing to spam! However, there are some issues I would like for you to fix and some questions I have:
  • Why is the spell in a library?
  • I think it would be better in the long run to keep the configurables that have linear scaling in private functions so that they can have full control of how it scales. You also save yourself a couple of globals per configurable :D
  • Could you add some explanation to what the value for "GRAVITY" means? Personally, 0.6129375 looks arbitary, so some explanation to why you chose that number would be useful
  • Why did you make a seperate function for DamageTarget and HealTarget? You're just creating another useless function call
  • Why 57.2957795 over bj_RADTODEG?
  • It seems kind of useless to use structs if you're just going to make all its data type global. It seems better for each element to have its own next/prev
  • Can you please consider naming your locals to something that can easily make sense ;_; (ex: local unit s)
  • Add a configurable for where PARTICLE_MODEL attaches
  • I personally think textmacros are pretty ugly and only save you a few lines of code. I'm not experienced with them, so do you mind explaining what some of your textmacros do?
  • It seems all the angles you calculate can be cached on index instead of having to always recalculate it every loop iteration
  • No point in setting the value 0 to the primitive data types in your destroy methods
  • While I was testing the spell, I may have encountered a bug. Check the GIF below. The effects circled around me for a good minute until I just decided to close the game. Can you adress if this is a bug or not?

For now, I will set the spell's status to Awaiting Update. Also, can you add a version number in the next update?
 

Attachments

  • GigaDrain Bug.gif
    GigaDrain Bug.gif
    1.6 MB · Views: 196
Level 33
Joined
Apr 24, 2012
Messages
5,113
at last, after two months of rotting
(sorry i'm in mobile)
- making a spell that is written in a library in my opinion, because you can handle the requirements muh better
- why that value instrad of bj_RADTODEG? idk, that's how missile systems wrote it(in their pitch formulas)
- attachment for PARTICLE_MODEL is a no.
- that is no bug. I already explained that on the description(keywords:eek:rbit, forever)

on the other comments, okay will do it.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
at last, after two months of rotting
Mmm more like a little over a month :D still safe enough to eat.

attachment for PARTICLE_MODEL is a no
Why so? Some effects look awkward when applied to their origin. I've had this issue before and had to attach it to the dummy's chest. I also don't understand why a no? It just requires one extra global.


that is no bug. I already explained that on the description(keywords:eek:rbit, forever)
Could you point to me where exactly that is said? I don't see you specifying that in both the description or the keywords. Hmm regardless, a little odd to have the orbs "orbit forever." It doesn't sound like a mechanic most people would enjoy, unless of course the original Giga Drain is that way?
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
take note that the particles may orbit the caster forever :D

That was intentional, btw, I could have used the "turning rate" instead of "gravity" if i wanted to, but I like it much better. Users can just adjust the gravitational force to prevent that from orbiting. Ofc, I am just trying to mimic the original Giga Drain effect.

Why so? Some effects look awkward when applied to their origin. I've had this issue before and had to attach it to the dummy's chest. I also don't understand why a no? It just requires one extra global.
Didn't some models don't work on chest? I encountered that problem years ago that's why I always use origin. if it works, I need to test it.

[edit]
Quoting other stuff:
Why did you make a seperate function for DamageTarget and HealTarget? You're just creating another useless function call
ugghhhh, if that's what you want, ok. err uhh no. I use that because I am lazy to write UnitDamageTarget. They are functional wrappers for me.

I personally think textmacros are pretty ugly and only save you a few lines of code. I'm not experienced with them, so do you mind explaining what some of your textmacros do?
I am a lazy coder. I used that to calculate the unit appearance.

It seems all the angles you calculate can be cached on index instead of having to always recalculate it every loop iteration
I have to recalculate it, because of the gravity. (no jokes intended)
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Didn't some models don't work on chest? I encountered that problem years ago that's why I always use origin. if it works, I need to test it.
Hmm not sure what you mean by this? If you're using dummy.mdx, then origin, chest, and overhead should all work.

ugghhhh, if that's what you want, ok. err uhh no. I use that because I am lazy to write UnitDamageTarget. They are functional wrappers for me.
Not enough for me to reject it, but it's extremely pointless. I'd say it's almost like comparing "true == true"

I have to recalculate it, because of the gravity. (no jokes intended)
Ah right. I forgot the caster can still move around. My mistake.
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,516
Why is the spell in a library?

library and scope are functionally equivalent, except that scope cannot be imported. The only reason you might require a scope over a library is that you could argue that scopes don't pollute the global namespace. But this is a vJass-only feature - other languages don't have some equivalent.

I disagree that this is an issue. I think it should be up to the developer.

I think it would be better in the long run to keep the configurables that have linear scaling in private functions so that they can have full control of how it scales. You also save yourself a couple of globals per configurable

I don't think this is necessary. For purely affine transformations, having the constant function adds more lines and more whitespace without clarifying much developer intent.

In some contexts I agree it's better. But not necessary.

Why did you make a seperate function for DamageTarget and HealTarget? You're just creating another useless function call

It shouldn't be the developers problem if JH doesn't inline the function. This should only matter if the script actually has a performance issue AND these functions are hot spots (which is not the case)

It seems kind of useless to use structs if you're just going to make all its data type global. It seems better for each element to have its own next/prev

It sounds like you dislike that the script bothers with structs since it's using a linear array (rather than a linked list).

In this case struct is the best option. I would also argue that the linear array is better practice than a linked list.

No point in setting the value 0 to the primitive data types in your destroy methods

Zeroing data helps with maintenance. This is actually why separate calloc exists.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
I disagree that this is an issue. I think it should be up to the developer.
I wasn't making it out to be an issue. I was actually interested as to why he did it. It was one of my very early reviews as a Spell Reviewer, so I wanted to know.

Zeroing data helps with maintenance. This is actually why separate
calloc exists.
I'll look into it. I haven't heard about calloc.
 

Deleted member 219079

D

Deleted member 219079

not peta drain, 0/5, disappointed in son you son smh
 
Top