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

Implosion Bomb v 1.2.0

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
This spell creates an implosion bomb. What it does first is sucks units into the middle of the caster ( not all the way unless wanted). As they get sucked in more and more they slowly shrink down to 0 then an explosion occurs and they get sent out while they start to increase in size until back to their original position.
All units in the are friendly or not will get hurt. Who ever heard of a bomb that doesn't hurt friendlies tell me lol.

This spell damages units differently than other spells. For lvl 1 i have it preset to do 300 damage. The way this is different is that the units closer get damaged more 300 being the max which means the unit is about 0.00 distance away from the caster. This damage is determined by the max range so if the range of lvl 1 is 1000 and the damage is 1000. It will do damage to units based on a 1 to 1. So unit is 100 away from caster it will damage him by 900. Unit is 900 away it will damage him by 100.

You have 7 things to change in here to ur liking. They are explained in the Implosion Bomb Config Trigger below. You also need to make a dummy unit. I made one with a scale of 2.00, the wisp model, and change the tinting colors to 0.

ALL OF MY SPELLS ARE GUI FRIENDLY

HOW TO IMPORT
I try to make my spells easy to import for both GUIers and Jassers.
Step 1) Copy the config copy trigger into your map.
Step 2) After copying that trigger u can rename it and get rid of the copy.
Step 3) Copy the cast trigger into your map.
Step 4) Go back to the config trigger and delete the variables after the line that says delete everything after this.

note: Make sure that the trigger name for the Jass is the same as the trigger name in the map.

  • Implosion Bomb Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- These are the base values that u can set. --------
      • -------- Here u can set the Aoe base radius. Its a real variable. This does not increase per lvl --------
      • Set aoeBaseImpBomb = 400.00
      • -------- --------
      • -------- This is the damage Base of the spell. --------
      • Set damBaseImpBomb = 200.00
      • -------- --------
      • -------- This is the duration Base of the spell. This is important as it sets the intervals for the spell. Put it in ticks ( 1 tick = .031250000 seconds). Keep this and the durPerLvl to an integer divisible by 4 for best results. --------
      • Set durBaseImpBomb = 200
      • -------- --------
      • -------- ---------------------------------------------------------------------------------------------------- --------
      • -------- These are the values that get added to the base per lvl that u can set. --------
      • -------- Here u can set the Aoe radius. Its a real variable. This increases per lvl So dont go to high --------
      • Set aoePerLvlImpBomb = 200.00
      • -------- --------
      • -------- This is the damage per lvl of the spell. --------
      • Set damPerLvlImpBomb = 100.00
      • -------- --------
      • -------- This is the duration of the spell. This is important as it sets the intervals for the spell. Put it in ticks ( 1 tick = .031250000 seconds). Keep this and the dur to an integer divisible by 4 for best results. --------
      • Set durPerLvlImpBomb = 100
      • -------- --------
      • -------- ---------------------------------------------------------------------------------------------------- --------
      • -------- These are the other values that u can change --------
      • -------- This is the velocity the unit moves at. Towards the Implosion --------
      • Set velocityImpBomb = 2.00
      • -------- --------
      • Set dummyUnitImpBomb = Dummy Unit
      • -------- --------
      • -------- ---------------------------------------------------------------------------------------------------- --------
      • -------- Here are the effects. These take the string values. --------
      • -------- This is the explosion effect that gets played.when units get damaged. --------
      • Set damageEffectImpBomb = Abilities\Spells\Human\MarkOfChaos\MarkOfChaosTarget.mdl
      • -------- --------
      • -------- Here is were you can set the effect that gets attached to the Dummy Unit. --------
      • Set dummyEffectImpBomb = Abilities\Spells\Orc\Voodoo\VoodooAura.mdl
      • -------- --------
      • -------- Here is were you set the attachment point for the dummy unit. --------
      • Set attachPointDummyImpBomb = origin
      • -------- --------
      • -------- Here is were you can set the effect that gets attached to the Units that get damaged. --------
      • Set unitEffectImpBomb = Abilities\Spells\Orc\Purge\PurgeBuffTarget.mdl
      • -------- --------
      • -------- Here is were you set the attachment point for the effect that gets attached to the units that get damaged. --------
      • Set attachPointUnitImpBomb = origin
      • -------- --------
      • -------- Here is where you set the attack type for the spell. --------
      • Set attackTypeImpBomb = Chaos
      • -------- --------
      • -------- Here is where you set the damage type for the spell. --------
      • Set damageTypeImpBomb = Normal
      • -------- --------
      • -------- Here is were you set the ability id --------
      • Custom script: set udg_spellIdImpBomb = 'A000'
      • -------- --------
      • -------- ---------------------------------------------------------------------------------------------------- --------
      • -------- After posting this into ur map delete the actions below here. This was just to make it easier for u to get the variables. --------
JASS:
// Implosion Bomb Spell made by deathismyfriend 
// GUI FRIENDLY version 1.2.0

function DistanceBetweenXYImpBomb takes real x1, real y1, real x2, real y2 returns real
    local real x = x2 - x1
    local real y = y2 - y1
    return SquareRoot(x*x + y*y)
endfunction

function GetAngleBetweenXYImpBomb takes real x1, real y1, real x2, real y2 returns real
    return Atan2( y1 - y2, x1 - x2)
endfunction

function PolarProjectionXImpBomb takes real x, real dist, real angle returns real // returns x
    return x + dist * Cos( angle)
endfunction

function PolarProjectionYImpBomb takes real y, real dist, real angle returns real // returns y
    return y + dist * Sin( angle)
endfunction

function ImplosionBombDeIndex takes integer L returns nothing
    local integer m = udg_maxIndexImpBomb
    set udg_durCounterImpBomb[ L] = udg_durCounterImpBomb[ m]
    call SetUnitPropWindow( udg_targetImpBomb[ L], udg_propWindowImpBomb[ L])
    set udg_propWindowImpBomb[ L] = udg_propWindowImpBomb[ m]
    set udg_casterImpBomb[ L] = udg_casterImpBomb[ m]
    set udg_casterXImpBomb[ L] = udg_casterXImpBomb[ m]
    set udg_casterYImpBomb[ L] = udg_casterYImpBomb[ m]
    set udg_targetImpBomb[ L] = udg_targetImpBomb[ m]
    set udg_targetSXImpBomb[ L] = udg_targetSXImpBomb[ m]
    set udg_targetSYImpBomb[ L] = udg_targetSYImpBomb[ m]
    set udg_targetMXImpBomb[ L] = udg_targetMXImpBomb[ m]
    set udg_targetMYImpBomb[ L] = udg_targetMYImpBomb[ m]
    set udg_distanceMXImpBomb[ L] = udg_distanceMXImpBomb[ m]
    set udg_distanceMYImpBomb[ L] = udg_distanceMYImpBomb[ m]
    set udg_durInt1ImpBomb[ L] = udg_durInt1ImpBomb[ m]
    set udg_durInt2ImpBomb[ L] = udg_durInt2ImpBomb[ m]
    set udg_scaleImpBomb[ L] = udg_scaleImpBomb[ m]
    set udg_decScaleImpBomb[ L] = udg_decScaleImpBomb[ m]
    set udg_damToDealImpBomb[ L] = udg_damToDealImpBomb[ m]
    set udg_aoeTotalImpBomb[ L] = udg_aoeTotalImpBomb[ m]
    set udg_dummyImpBomb[ L] = udg_dummyImpBomb[ m]
    call DestroyEffect( udg_effectImpBomb[ L])
    set udg_effectImpBomb[ L] = udg_effectImpBomb[ m]
    set udg_maxIndexImpBomb = udg_maxIndexImpBomb - 1
endfunction

function ImplosionBombChangeScale takes integer L returns nothing
    set udg_scaleImpBomb[ L] = udg_scaleImpBomb[ L] - udg_decScaleImpBomb[ L]
    call SetUnitScale( udg_targetImpBomb[ L], udg_scaleImpBomb[ L], udg_scaleImpBomb[ L], udg_scaleImpBomb[ L])
endfunction

function ImplosionBombMovingUnits takes integer L returns nothing
    set udg_targetMXImpBomb[ L] = udg_targetMXImpBomb[ L] - udg_distanceMXImpBomb[ L]
    set udg_targetMYImpBomb[ L] = udg_targetMYImpBomb[ L] - udg_distanceMYImpBomb[ L]
    call SetUnitX( udg_targetImpBomb[ L], udg_targetMXImpBomb[ L])
    call SetUnitY( udg_targetImpBomb[ L], udg_targetMYImpBomb[ L])
endfunction

function ImplosionBombTimerActions takes nothing returns nothing
    local integer L = 1
    local real x
    local real y
    local real d
    local real v = udg_velocityImpBomb/2
    loop
        exitwhen L > udg_maxIndexImpBomb
        
        set udg_durCounterImpBomb[ L] = udg_durCounterImpBomb[ L] + 1
        if udg_targetImpBomb[ L] == null then
            if udg_durCounterImpBomb[ L] == udg_durInt1ImpBomb[ L] - 32 then // sets the variables for second stage on. damage units here
                call DestroyEffect( AddSpecialEffectTarget( udg_damageEffectImpBomb, udg_dummyImpBomb[ L], udg_attachPointDummyImpBomb))
            elseif udg_durCounterImpBomb[ L] >= udg_durInt2ImpBomb[ L] + 1 then // de-index the caster here.
                call SetUnitPropWindow( udg_casterImpBomb[ L], GetUnitDefaultPropWindow( udg_casterImpBomb[ L]))
                call RemoveUnit( udg_dummyImpBomb[ L])
                call ImplosionBombDeIndex( L)
                set L = L - 1
            endif
        elseif udg_durCounterImpBomb[ L] < udg_durInt1ImpBomb[ L] then // first faze. pull units into implosion
            if DistanceBetweenXYImpBomb( udg_casterXImpBomb[ L], udg_casterYImpBomb[ L], udg_targetMXImpBomb[ L], udg_targetMYImpBomb[ L]) >= v then
                call ImplosionBombMovingUnits( L)
            endif
            call ImplosionBombChangeScale( L)
        elseif udg_durCounterImpBomb[ L] == udg_durInt1ImpBomb[ L] then // sets the variables for second stage on. damage units here
            set d = DistanceBetweenXYImpBomb( udg_casterXImpBomb[ L], udg_casterYImpBomb[ L], udg_targetMXImpBomb[ L], udg_targetMYImpBomb[ L])
            if d >= v then
                call ImplosionBombMovingUnits( L)
            endif
            call ImplosionBombChangeScale( L)
            set d = udg_aoeTotalImpBomb[ L] - d
            call UnitDamageTarget( udg_casterImpBomb[ L], udg_targetImpBomb[ L], ( d/udg_aoeTotalImpBomb[ L])*udg_damToDealImpBomb[ L], true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null)
            set udg_effectImpBomb[ L] = AddSpecialEffectTarget( udg_unitEffectImpBomb, udg_targetImpBomb[ L], udg_attachPointUnitImpBomb)
            //set udg_angleImpBomb[ L] = udg_angleImpBomb[ L] + 180.00
            set udg_distanceMXImpBomb[ L] = udg_distanceMXImpBomb[ L] * -2
            set udg_distanceMYImpBomb[ L] = udg_distanceMYImpBomb[ L] * -2
            set udg_decScaleImpBomb[ L] = -1.00/I2R( udg_durInt2ImpBomb[ L] - udg_durInt1ImpBomb[ L])
            if IsUnitType( udg_targetImpBomb[ L], UNIT_TYPE_DEAD) or GetUnitTypeId( udg_targetImpBomb[ L]) == 0 then
                call ImplosionBombDeIndex( L)
                set L = L - 1
            endif
            
        elseif udg_durCounterImpBomb[ L] < udg_durInt2ImpBomb[ L] then // final faze. moving units to there original position
            if DistanceBetweenXYImpBomb( udg_targetMXImpBomb[ L], udg_targetMYImpBomb[ L], udg_targetSXImpBomb[ L], udg_targetSYImpBomb[ L]) >= v then
                call ImplosionBombMovingUnits( L)
            elseif udg_targetMXImpBomb[ L] != udg_targetSXImpBomb[ L] and udg_targetMYImpBomb[ L] != udg_targetSYImpBomb[ L] then
                call SetUnitX( udg_targetImpBomb[ L], udg_targetSXImpBomb[ L])
                call SetUnitY( udg_targetImpBomb[ L], udg_targetSYImpBomb[ L])
            endif
            call ImplosionBombChangeScale( L)
            
        elseif udg_durCounterImpBomb[ L] >= udg_durInt2ImpBomb[ L] then // de-index here
            call ImplosionBombChangeScale( L)
            call ImplosionBombDeIndex( L)
            set L = L - 1
        endif
        set L = L + 1
    endloop
    if udg_maxIndexImpBomb <= 0 then
        call PauseTimer( udg_timerImpBomb)
    endif
endfunction

function ImplosionBombSetup takes nothing returns nothing
    local unit c = GetTriggerUnit()
    local unit u
    local integer abiLvl = GetUnitAbilityLevel( c, udg_spellIdImpBomb)
    local real r = udg_aoeBaseImpBomb + ( udg_aoePerLvlImpBomb*I2R( abiLvl))
    local real x = GetUnitX( c)
    local real y = GetUnitY( c)
    local integer i = ( udg_durBaseImpBomb + ( udg_durPerLvlImpBomb*abiLvl))
    local integer i2 = R2I( I2R( i)*0.75)
    local real dam = udg_damBaseImpBomb + ( udg_damPerLvlImpBomb*abiLvl)
    local unit dum
    local integer m = udg_maxIndexImpBomb
    local real angle
    local real v = udg_velocityImpBomb/2
    set m = m + 1
    set udg_casterImpBomb[ m] = c
    set udg_casterXImpBomb[ m] = x
    set udg_casterYImpBomb[ m] = y
    set udg_targetImpBomb[ m] = null
    set udg_durCounterImpBomb[ m] = 0
    set udg_durInt1ImpBomb[ m] = i2 // first effect stage
    set udg_durInt2ImpBomb[ m] = i // second effect stage
    set udg_damToDealImpBomb[ m] = dam
    set udg_aoeTotalImpBomb[ m] = r
    set udg_propWindowImpBomb[ m] = GetUnitPropWindow( c)
    set udg_dummyImpBomb[ m] = CreateUnit( GetOwningPlayer( c), udg_dummyUnitImpBomb, x, y, 0)
    set dum = udg_dummyImpBomb[ m]
    call SetUnitPropWindow( dum, 0.00)
    call SetUnitX( udg_dummyImpBomb[ m], x)
    call SetUnitY( udg_dummyImpBomb[ m], y)
    set udg_effectImpBomb[ m] = AddSpecialEffectTarget( udg_dummyEffectImpBomb, udg_dummyImpBomb[ m], udg_attachPointDummyImpBomb)
    if m == 1 then
        call TimerStart( udg_timerImpBomb, 0.031250000, true, function ImplosionBombTimerActions)
    endif
    
    call GroupEnumUnitsInRange( udg_groupImpBomb, x, y, r, null)
    
    loop
        set u = FirstOfGroup( udg_groupImpBomb)
        exitwhen u == null
        if u != c and u != UNIT_TYPE_STRUCTURE and not IsUnitType( u, UNIT_TYPE_DEAD) and u != dum then
            set m = m + 1
            set udg_casterImpBomb[ m] = c
            set udg_casterXImpBomb[ m] = x
            set udg_casterYImpBomb[ m] = y
            set udg_targetImpBomb[ m] = u
            set udg_targetSXImpBomb[ m] = GetUnitX( udg_targetImpBomb[ m])
            set udg_targetSYImpBomb[ m] = GetUnitY( udg_targetImpBomb[ m])
            set udg_targetMXImpBomb[ m] = udg_targetSXImpBomb[ m]
            set udg_targetMYImpBomb[ m] = udg_targetSYImpBomb[ m]
            set udg_durInt1ImpBomb[ m] = i2 // first effect stage
            set udg_durInt2ImpBomb[ m] = i // second effect stage
            set udg_durCounterImpBomb[ m] = 0
            set udg_scaleImpBomb[ m] = 1.00
            set udg_decScaleImpBomb[ m] = 1.00/i2
            set udg_damToDealImpBomb[ m] = dam
            set udg_aoeTotalImpBomb[ m] = r
            set udg_propWindowImpBomb[ m] = GetUnitPropWindow( u)
            call SetUnitPropWindow( u, 0.00)
            set angle = GetAngleBetweenXYImpBomb( x, y, udg_targetSXImpBomb[ m], udg_targetSYImpBomb[ m])
            set udg_distanceMXImpBomb[ m] = udg_targetSXImpBomb[ m] - PolarProjectionXImpBomb( udg_targetMXImpBomb[ m], v, angle)
            set udg_distanceMYImpBomb[ m] = udg_targetSYImpBomb[ m] - PolarProjectionYImpBomb( udg_targetMYImpBomb[ m], udg_velocityImpBomb/2, angle)
        endif
        call GroupRemoveUnit( udg_groupImpBomb, u)
    endloop
    
    set udg_maxIndexImpBomb = m
    set c = null
    set dum = null
endfunction

function ImplosionBombCastConditions takes nothing returns boolean
    if GetSpellAbilityId() == udg_spellIdImpBomb then
        call ImplosionBombSetup()
    endif
    return false
endfunction

//===========================================================================
function InitTrig_Implosion_Bomb_Cast takes nothing returns nothing
    local trigger t = CreateTrigger()
    set udg_timerImpBomb = CreateTimer()
    set udg_groupImpBomb = CreateGroup()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition( t, Condition( function ImplosionBombCastConditions))
    set t = null
endfunction

JASS:
library ImpBomb

// Implosion Bomb Spell made by deathismyfriend 
// Alloc by Nestharus can be found here. http://www.hiveworkshop.com/forums/jass-resources-412/snippet-alloc-alternative-221493/
// vJass version 1.2.0

globals
    // These are the base values that u can set.
    // Here u can set the Aoe base radius. Its a real variable. This does not increase per lvl
    private constant real AOE_BASE = 400.00                                                                   
    // This is the damage Base of the spell.
    private constant real DAM_BASE = 200.00                                                              
    // This is the duration Base of the spell. This is important as it sets the intervals for the spell. Put it in seconds.
    private constant integer DUR_BASE = 200
    // These are the values that get added to the base per lvl that u can set.
    // Here u can set the Aoe radius. Its a real variable. This increases per lvl So dont go to high
    private constant real AOE_PER_LVL = 200.00                                                                    
    // This is the damage of the spell.
    private constant real DAM_PER_LVL = 100.00                                                                    
    // This is the duration of the spell. This is important as it sets the intervals for the spell. Put it in seconds.
    private constant integer DUR_PER_LVL = 100
    // These are the other values that u can change
    // This is the VELOCITY the unit moves at. Towards the Implosion
    private constant real VELOCITY = 2.00                                                              
    // Set the dummy unit type here.
    private constant integer DUMMY_UNIT = 'h000'
    // This is the explosion effect that gets played.when units get damaged.
    private constant string DAMAGE_EFF = "Abilities\\Spells\\Human\\MarkOfChaos\\MarkOfChaosTarget.mdl"
    // Here is were you can set the effect that gets attached to the Dummy Unit.
    private constant string DUMMY_EFF = "Abilities\\Spells\\Orc\\Voodoo\\VoodooAura.mdl" //caster
    // Here is were you set the attachment point for the dummy unit.
    private constant string ATTACH_POINT_DUMMY = "origin"
    // Here is were you can set the effect that gets attached to the Units that get damaged.
    private constant string UNIT_EFF = "Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl"
    // Here is were you set the attachment point for the effect that gets attached to the units that get damaged.
    private constant string ATTACH_POINT_UNIT = "origin"
    // Here is the ability id
    private constant integer SPELL_ID = 'A000' 
    // Here is the attack type
    private constant attacktype ATTACK_TYPE = ATTACK_TYPE_CHAOS
    // Here is the damage type
    private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
    // dont change anything below here.
    
    private integer array structIndex
    private timer tmr
    private integer maxIndex = 0
    private group grp
endglobals

private struct impBombSpell extends array
    implement Alloc
    
    private real aoeTotal
    private unit caster
    private real casterX
    private real casterY
    private real decScale
    private real damToDeal
    private unit dummy
    private integer durCounter
    private integer durInt1
    private integer durInt2
    private effect eff
    private real propWindow
    private real scale
    private unit target
    private real distanceMX
    private real distanceMY
    private real targetMX
    private real targetMY
    private real targetSX
    private real targetSY
    
    static method distBetweenXY takes real x1, real y1, real x2, real y2 returns real
        local real x = x2 - x1
        local real y = y2 - y1
        return SquareRoot(x*x + y*y)
    endmethod

    private static method getAngleBetweenXY takes real x1, real y1, real x2, real y2 returns real
        return Atan2( y1 - y2, x1 - x2)
    endmethod 

    private static method polarProjectionX takes real x, real dist, real angle returns real // returns x
        return x + dist * Cos( angle)
    endmethod

    private static method polarProjectionY takes real y, real dist, real angle returns real // returns y
        return y + dist * Sin( angle)
    endmethod
    
    private method changeScale takes nothing returns nothing
        set this.scale = this.scale - this.decScale
        call SetUnitScale( this.target, this.scale, this.scale, this.scale)
    endmethod

    private method movingUnits takes real vel returns nothing
        set this.targetMX = this.targetMX - this.distanceMX
        set this.targetMY = this.targetMY - this.distanceMY
        call SetUnitX( this.target, this.targetMX)
        call SetUnitY( this.target, this.targetMY)
    endmethod
    
    private method destroy takes nothing returns nothing // de-index
        call SetUnitPropWindow( this.target, this.propWindow)
        set this.caster = null
        set this.target = null
        set this.dummy = null
        call DestroyEffect( this.eff)
        set this.eff = null
        set maxIndex = maxIndex - 1
        call this.deallocate()
    endmethod

    private static method timerActions takes nothing returns nothing
        local thistype this
        local integer L = 1
        local real x
        local real y
        local real d
        local real v = VELOCITY/2
        loop
            exitwhen L > maxIndex
            set this = structIndex[ L]
            set this.durCounter = this.durCounter + 1
            if this.target == null then
                if this.durCounter == this.durInt1 - 32 then // sets the variables for second stage on. damage units here
                    call DestroyEffect( AddSpecialEffectTarget( DAMAGE_EFF, this.dummy,  ATTACH_POINT_DUMMY))
                elseif this.durCounter >= this.durInt2 + 1 then // de-index the caster here.
                    call SetUnitPropWindow( this.caster,this.propWindow)
                    call RemoveUnit( this.dummy)
                    set structIndex[ L] = structIndex[ maxIndex]
                    call this.destroy()
                    set L = L - 1
                endif
            elseif this.durCounter < this.durInt1 then // first faze. pull units into implosion
                if distBetweenXY( this.casterX, this.casterY, this.targetMX, this.targetMY) >= v then
                    call this.movingUnits( v)
                endif
                call this.changeScale()
            elseif this.durCounter == this.durInt1 then // sets the variables for second stage on. damage units here
                set d = distBetweenXY( this.casterX, this.casterY, this.targetMX, this.targetMY)
                if d >= v then
                    call this.movingUnits( v)
                endif
                call this.changeScale()
                set d = this.aoeTotal - d
                call UnitDamageTarget( this.caster, this.target, ( d/this.aoeTotal)*this.damToDeal, false, false, ATTACK_TYPE, DAMAGE_TYPE, null)
                set this.eff = AddSpecialEffectTarget( UNIT_EFF, this.target, ATTACH_POINT_UNIT)
                set this.distanceMX = this.distanceMX * -2
                set this.distanceMY = this.distanceMY * -2
                set this.decScale = -1.00/I2R( this.durInt2 - this.durInt1)
                if IsUnitType( this.target, UNIT_TYPE_DEAD) or GetUnitTypeId( this.target) == 0 then
                    set structIndex[ L] = structIndex[ maxIndex]
                    call this.destroy()
                    set L = L - 1
                endif
                
            elseif this.durCounter < this.durInt2 then // final faze. moving units to there original position
                if distBetweenXY( this.targetMX, this.targetMY, this.targetSX, this.targetSY) >= v then
                    call this.movingUnits( VELOCITY)
                elseif this.targetMX != this.targetSX and this.targetMY != this.targetSY then
                    call SetUnitX( this.target, this.targetSX)
                    call SetUnitY( this.target, this.targetSY)
                endif
                call this.changeScale()
                
            elseif this.durCounter >= this.durInt2 then // de-index here
                call this.changeScale()
                set structIndex[ L] = structIndex[ maxIndex]
                call this.destroy()
                set L = L - 1
            endif
            set L = L + 1
        endloop
        if maxIndex <= 0 then
            call PauseTimer( tmr)
        endif
    endmethod

    private static method create takes unit c, real x, real y, integer i, integer i2, real dam, real r returns thistype
        local thistype this = thistype.allocate()
        set this.caster = c
        set this.casterX = x
        set this.casterY = y
        set this.durCounter = 0
        set this.durInt1 = i2 // first effect stage
        set this.durInt2 = i // second effect stage
        set this.damToDeal = dam
        set this.aoeTotal = r
        set maxIndex = maxIndex + 1
        return this
    endmethod
    
    private static method setup takes nothing returns nothing
        local thistype this
        local thistype data
        local unit c = GetTriggerUnit()
        local unit u
        local unit dum
        local integer abiLvl = GetUnitAbilityLevel( c, SPELL_ID)
        local real r = AOE_BASE + ( AOE_PER_LVL*I2R( abiLvl))
        local real x = GetUnitX( c)
        local real y = GetUnitY( c)
        local integer i = ( DUR_BASE + ( DUR_PER_LVL*abiLvl))
        local integer i2 = R2I( I2R( i)*0.75)
        local real dam = DAM_BASE + ( DAM_PER_LVL*abiLvl)
        local real angle
        local real v = VELOCITY/2
        set this = thistype.create( c, x, y, i, i2, dam, r)
        set this.target = null
        set this.propWindow = GetUnitPropWindow( this.caster)
        set this.dummy = CreateUnit( GetOwningPlayer( c), DUMMY_UNIT, x, y, 0)
        call SetUnitPropWindow( this.dummy, 0.00)
        call SetUnitX( this.dummy, x)
        call SetUnitY( this.dummy, y)
        set this.eff = AddSpecialEffectTarget( DUMMY_EFF, this.dummy, ATTACH_POINT_DUMMY)
        set dum = this.dummy
        set structIndex[ maxIndex] = this
        if maxIndex == 1 then
            call TimerStart( tmr, 0.031250000, true, function thistype.timerActions)
        endif
        
        call GroupEnumUnitsInRange( grp, x, y, r, null)
        
        loop
            set u = FirstOfGroup( grp)
            exitwhen u == null
            if u != c and u != UNIT_TYPE_STRUCTURE and not IsUnitType( u, UNIT_TYPE_DEAD) and u != dum then
                set this = thistype.create( c, x, y, i, i2, dam, r)
                set this.target = u
                set this.targetSX = GetUnitX( this.target)
                set this.targetSY = GetUnitY( this.target)
                set this.targetMX = this.targetSX
                set this.targetMY = this.targetSY
                set this.propWindow = GetUnitPropWindow( this.target)
                call SetUnitPropWindow( this.target, 0.00)
                set this.scale = 1.00
                set this.decScale = 1.00/i2
                set angle = getAngleBetweenXY( x, y, this.targetSX, this.targetSY)
                set this.distanceMX = this.targetSX - polarProjectionX( this.targetMX, v, angle)
                set this.distanceMY = this.targetSY - polarProjectionY( this.targetMY, v, angle)
                set structIndex[ maxIndex] = this
            endif
            call GroupRemoveUnit( grp, u)
        endloop
        
        set c = null
        set dum = null
    endmethod

    private static method conditions takes nothing returns boolean
        if GetSpellAbilityId() == SPELL_ID then
            call setup()
        endif
        return false
    endmethod

    //===========================================================================
    private static method onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        set tmr = CreateTimer()
        set grp = CreateGroup()
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition( t, Condition( function thistype.conditions))
        set t = null
    endmethod
    
endstruct

endlibrary


version 1.2.0
Fixed some of the code.​
version 1.1.8
Removed unneeded GetUnitTypeId().​
version 1.1.7
Fixed a bug and some other small things.​
version 1.1.6
Fixed a small mistake.​
version 1.1.5
Updated with the fixes suggested.​
version 1.1.2
made changes Maker suggested.​
version 1.1.1
got rid of the BJDEGTORAD things
fixed button positions ( pointless)
changed follow through time to 0.00​
version 1.1.0
changed the jass spell a little.
easier to read.​
version 1.0.6
changed the jass spell a little.
easier to read.​
version 1.0.5
fixed bug with the effects not showing​
version 1.0.4
fixed some things in the spell​
version 1.0.3
changed vJass version a bit
added ability to change effects easier​
version 1.0.2
added vJass version​
version 1.0.1
fixed bug​
version 1.0.0
first upload​


Comments are appreciated. Finally created my first spell lol. Thanks to anyone that posts.

Keywords:
GUI, GUI freindly, friendly, jass, deathismyfriend, implosion, bomb, implosion bomb, wc3, spell, vJass
Contents

Template Map (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. BPower 14.1.2014 Aslong as you upload a vJass and a GUI-friendly JASS version, we have to take both into consideration. For this review the focus lies on the second one...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.

BPower 14.1.2014
Aslong as you upload a vJass and a GUI-friendly JASS version, we have to take both into consideration.
For this review the focus lies on the second one.

http://www.hiveworkshop.com/forums/spells-569/implosion-bomb-v-1-2-0-a-235096/index3.html#post2466790

In addition I like to refer to Makers post #37.


Implosion Bomb v 1.1.0 | Reviewed by Maker | 4th Jun 2013
NEEDS FIX


126248-albums6177-picture66522.png


  • Trying to reset the caster's prop window with GetUnitDefaultPropWindow
    results in giving the unit a wrong prop window value
  • The follow through time is way too long and the caster keeps channeling
    even when the spell is over
  • Get rid of the unneeded degtorad and radtodeg conversions
126248-albums6177-picture66523.png


  • Improve the tooltips, look at default Blizzard abilities for reference
  • Adjust command card positions
  • Add importing intructions into the map file
  • I recommend adding locust to the dummy in object editor
    and removing upgrades used and unneeded abilities from it
[tr]




Implosion Bomb v1.0.0.6 | Reviewed by Maker | 1st Jun 2013
NEEDS FIX


126248-albums6177-picture66522.png


  • The dummy uses food and upgrades, has build ability, gives vision
126248-albums6177-picture66523.png


  • Learn icon is missing
  • There is no attention to command card positions
  • The tooltips are lacking
  • You could make the ability true channeling ability that
    the caster can break out from
  • You are calling the polar projection functions too often.
    As the angle won't change, the sin/cos*angle*bj_RADTODEG is always the same
    Why is the angle converted away from radians in the first place?
[tr]

 
Level 33
Joined
Apr 24, 2012
Messages
5,113
YAY! First spell from DIMF :D

Review:
For the vJASS:
1) I see you use a lot of array variables.Best suggestion? Structs.
2)
JASS:
       else
            if durCounter[ L] < durInt1[ L] then
You know what's the problem here right? ehem..... elseif.

3) The space in arrays makes the code ugly :(. [ L] vs [L]
4) Combine setup with condition. As what Bribe always say: "Keep it simple".
5)
JASS:
private function GroupCondition takes nothing returns boolean
    return GetFilterUnit() != caster[ maxIndex] and GetFilterUnit() != UNIT_TYPE_STRUCTURE and /*
    */ GetUnitState( GetFilterUnit(), UNIT_STATE_LIFE) > 0.405 and GetFilterUnit() != dummy[ maxIndex]
endfunction
Cache filter unit into a global(because local leaks).
6)you don't need to null unit u. Booleans are already nulling them(im referring the FirstOfGroup loop)
7)Do the condition(optional) in the FirstOfGroup loop than in GroupEnumUnits blah blah.

8)Make "origin" configurable.
9)Make those special effects models configurable err i mean in the globals.

This is all of what i got. Later the GUI.

Btw, the funniest thing I saw here is the Idle Worker Icon spawning while channeling the spell XD
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
YAY! First spell from DIMF :D

Review:
For the vJASS:
1) I see you use a lot of array variables.Best suggestion? Structs.
2)
JASS:
       else
            if durCounter[ L] < durInt1[ L] then
You know what's the problem here right? ehem..... elseif.

3) The space in arrays makes the code ugly :(. [ L] vs [L]
4) Combine setup with condition. As what Bribe always say: "Keep it simple".
5)
JASS:
private function GroupCondition takes nothing returns boolean
    return GetFilterUnit() != caster[ maxIndex] and GetFilterUnit() != UNIT_TYPE_STRUCTURE and /*
    */ GetUnitState( GetFilterUnit(), UNIT_STATE_LIFE) > 0.405 and GetFilterUnit() != dummy[ maxIndex]
endfunction
Cache filter unit into a global(because local leaks).
6)you don't need to null unit u. Booleans are already nulling them(im referring the FirstOfGroup loop)
7)Do the condition(optional) in the FirstOfGroup loop than in GroupEnumUnits blah blah.

8)Make "origin" configurable.
9)Make those special effects models configurable err i mean in the globals.

This is all of what i got. Later the GUI.

Btw, the funniest thing I saw here is the Idle Worker Icon spawning while channeling the spell XD

1) ya i should convert to structs id still use the same variables tho lol.

2) not sure how i did that one.

3) i like it that way its easier to read / write / correct anything.

4) i could do that only reason i do it with the condition function is so it doesnt create the locals. i dont think ill change that.

5) i was told that the local doesnt leak. are u sure it does leak ? my handle counter didnt go up at all.

6) i null the unit u in case the group doesnt run. that way i know its still nulled.

7) umm not sure what u mean lol

8) that makes sense i will do that

9) good point
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
I was wrong. Only Handle Locals XD

As i told you, booleans automatically nulls the handle. exitwhen u == null does the job.

About 7,do the filtering in the loop,not in GroupEnum action,but that is optional.

ok lol ill change the null thing lol. i didnt even think about that lol.

about 7 i guess i could do it in the group loop it would get rid of a function. and the less efficient GetFilterUnit calls.

edit: updated a lot of the code. especially the vJass. now it uses a struct.
 
Last edited:
Level 7
Joined
Jan 22, 2013
Messages
293
JASS:
function InitTrig_Implosion_Bomb_Cast takes nothing returns nothing
    local trigger t = CreateTrigger()
    set udg_timerImpBomb = CreateTimer()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST)
    call TriggerAddCondition( t, Condition( function ImplosionBombCastConditions))
    set t = null
endfunction

You should know better then to use that TriggerREgisterAnyUnitEventBJ, I have replaced it with the proper way.

Also you should try not making the spell depend on the cast, it should depend on the effect stage.

Here:
JASS:
function InitTrig_Implosion_Bomb_Cast takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer index
    set udg_timerImpBomb = CreateTimer()
    set index = 0
    loop
        call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_SPELL_CAST, null)
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddCondition( t, Condition( function ImplosionBombCastConditions))
    set t = null
endfunction

Also I do believe you should be able to remove that entire Trigger Conditon line by adding it to the null location on the new event.

as this:
JASS:
call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, Filter(function ImplosionBombCastConditions))
//which will allow you to delete this:
call TriggerAddCondition( t, Condition( function ImprosionBombCastConditions))

JASS:
function ImplosionBombGroupCondition takes nothing returns boolean
    return GetFilterUnit() != udg_casterImpBomb[ udg_maxIndexImpBomb] and GetFilterUnit() != UNIT_TYPE_STRUCTURE and GetUnitState( GetFilterUnit(), UNIT_STATE_LIFE) > 0.405 and GetFilterUnit() != udg_dummyImpBomb[ udg_maxIndexImpBomb]
endfunction
//I do not see you detecting if the victims are going to be Hostile to the caster or not to toss it.

Overall, the trigger is not neat in any way, you are also using very ugly and long variable names. As long as you make a Key Table for the Short Names for people to copy paste and look at when they are editing the spell, you should be allowed to dramaticaly shorten it so it is way easier to read.
You also don't tell some people where the cords are ended up at.


I have several issues with the spell (Preformance wise)

1. You have no way to stop the spell after its cast, Every spell should stop when the caster stops since it is a channeling spell.
2. the spell doesn't check to see if some units are stunned, sleeping or have a way to get removed from the spells effects if they change forces.
3. The spell is ideal to conflict with many other spells.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
that BJ function is perfectly fine to use. i dont like putting the condition in the event. Its ugly to me.
The units dont get tossed. Also as i stated this spell is a bomb and there are no friendly free bombs, so thats how i made it.

The long variable names can be shortened by the user in the variable editor. It changes the jass script when changing them. They are long so they dont conflict with any other spells. its GUI cant do much about that lol. if u want short names go to vJass.

1) this spell isnt channeling. The caster gets stuck in the implosion also.
2) as i said its a bomb. Every unit gets hit.
3) how is that ?
 
Level 7
Joined
Jan 22, 2013
Messages
293
that BJ function is perfectly fine to use. i dont like putting the condition in the event. Its ugly to me.
The units dont get tossed. Also as i stated this spell is a bomb and there are no friendly free bombs, so thats how i made it.

The long variable names can be shortened by the user in the variable editor. It changes the jass script when changing them. They are long so they dont conflict with any other spells. its GUI cant do much about that lol. if u want short names go to vJass.

1) this spell isnt channeling. The caster gets stuck in the implosion also.
2) as i said its a bomb. Every unit gets hit.
3) how is that ?

1) I disapprove lol, the spell is set up like a channel spell since he is standing still, also if you don't want it to be a channel spell then allow it to be a cast at a target area with range, like an instant walk away. It would make more sense. Plus if you did that, it would be nice to have something in the center grow then explode lol.
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
The Spell is a Channeling spell.

Review:
  • Structs shouldn't have any constants inside it. Move all of the constants in the globals block.
  • You should now learn how to create your own alloc bro :D
  • Move the timer to the global.
  • I think linked list is good than your indexing. But that is optional
  • Make struct private.
  • You don't need this.
    JASS:
        private static method polarProjectionX takes real x, real dist, real angle returns real // returns x
            return x + dist * Cos( angle*bj_DEGTORAD)
        endmethod
    
        private static method polarProjectionYtakes real y, real dist, real angle returns real // returns y
            return y + dist * Sin( angle*bj_DEGTORAD)
        endmethod
  • Instead of a method,make this a function:
    JASS:
        private static method distBetweenXY takes real x1, real y1, real x2, real y2 returns real
            local real x = x2 - x1
            local real y = y2 - y1
            return SquareRoot(x*x + y*y)
        endmethod
    
        private static method getAngleBetweenXY takes real x1, real y1, real x2, real y2 returns real
            return bj_RADTODEG * Atan2( y1 - y2, x1 - x2)
        endmethod
  • if GetUnitState( this.target, UNIT_STATE_LIFE) < 0.405 then
    Use GetWidgetLife.
  • Attack Types and Damage Types should be at least constants.
  • The booleans in UnitDamageTarget should be false.
  • JASS:
    globals
        private integer array structIndex
    endglobals
    You don't need this,make this a struct global
  • I suggest that you use SpellEffectEvent by Bribe.
  • Y u remove this?
    if u != c and u != UNIT_TYPE_STRUCTURE and GetUnitState( u, UNIT_STATE_LIFE) > 0.405 and u != dum then
  • CTL? no,its an option.
  • local integer abiLvl = GetUnitAbilityLevel( c, GetSpellAbilityId())
    Replace GetSpellAbilityId() with the ability constant you use.

That's all i can see.

@Orthane
RegisterAnyUnitEventBJ is fine. In fact,it is the most useful BJ.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
The Spell is a Channeling spell.

Review:
[*]Structs shouldn't have any constants inside it. Move all of the constants in the globals block.
[*]You should now learn how to create your own alloc bro :D
[*]Move the timer to the global.
[*]I think linked list is good than your indexing. But that is optional
[*]Make struct private.

changed the constants.
I like how the module is already set up. so y index structs by myself when im gonna do it the exact same way ? lol
moved the timer.
i dont think ill use linked list.
struct is now private. wonder how i missed that haha

[*]You don't need this.
JASS:
    private static method polarProjectionX takes real x, real dist, real angle returns real // returns x
        return x + dist * Cos( angle*bj_DEGTORAD)
    endmethod

    private static method polarProjectionYtakes real y, real dist, real angle returns real // returns y
        return y + dist * Sin( angle*bj_DEGTORAD)
    endmethod

i do need that lol look at the move method

[*] Instead of a method,make this a function:
JASS:
    private static method distBetweenXY takes real x1, real y1, real x2, real y2 returns real
        local real x = x2 - x1
        local real y = y2 - y1
        return SquareRoot(x*x + y*y)
    endmethod

    private static method getAngleBetweenXY takes real x1, real y1, real x2, real y2 returns real
        return bj_RADTODEG * Atan2( y1 - y2, x1 - x2)
    endmethod

i rather that be a method.

[*] if GetUnitState( this.target, UNIT_STATE_LIFE) < 0.405 then
Use GetWidgetLife.
[*]Attack Types and Damage Types should be at least constants.
[*]The booleans in UnitDamageTarget should be false.

lol i honestly couldnt remember the getwidget life name haha.
changed them to false

[*]
JASS:
globals
    private integer array structIndex
endglobals
You don't need this,make this a struct global
[*]I suggest that you use SpellEffectEvent by Bribe.
[*]Y u remove this?
if u != c and u != UNIT_TYPE_STRUCTURE and GetUnitState( u, UNIT_STATE_LIFE) > 0.405 and u != dum then
[*]CTL? no,its an option.
[*] local integer abiLvl = GetUnitAbilityLevel( c, GetSpellAbilityId())
Replace GetSpellAbilityId() with the ability constant you use.

i do need that for looping purposes.
id rather not use that system as i dont believe this needs it.
i didnt remove that i just moved it into the group loop like previously stated lol.
CTL ? not sure what u mean
changed that to a constant.

Edit: updated the triggers and the test map

Edit2: fixed bug with effects for the jass / gui triggers.
 
Last edited:
Level 29
Joined
Oct 24, 2012
Messages
6,543
The dummy uses food and upgrades, has build ability, gives vision
....umm not sure y this matters ? i said to make ur own dummy unit.
Learn icon is missing
....not sure y this matters either ? its a spell. the icon doesnt matter they can make it what they want.
There is no attention to command card positions
....not sure what u mean ?
The tooltips are lacking
....again not sure why this matters ?
You could make the ability true channeling ability that the caster can break out from
....i dont want the ability true channeling. Its a bomb, not a channel ability.
You are calling the polar projectuion functions too often.
As the angle won't change, the sin/cos*angle*bj_RADTODEG is always the same
....this i will change as that makes sense.
Why is the angle converted away from radians in the first place?
....is there a better way to do it ?
 
Last edited:
Level 37
Joined
Mar 6, 2006
Messages
9,240
The dummy uses food and upgrades, has build ability, gives vision
....umm not sure y this matters ? i said to make ur own dummy unit.
Not everyone knows how to make a proper dummy unit. In fact the vast majority don't know that. If a spell uses a dummy unit, it must provide a proper dummy unit for that reason. Spells should be useable and glitchelss without the user having to edit it.

Learn icon is missing
....not sure y this matters either ? its a spell. the icon doesnt matter they can make it what they want.
The tooltips are lacking
....again not sure why this matters ?
Spells are not just triggering/coding. Tooltips and icons are a part of the complete package. Sure people can change them to their liking, but you should still provide a complete spell.

There is no attention to command card positions
....not sure what u mean ?
The learn icon position doesn't match the position of the learned ability. Additionally, the learned icon shows up where no abilities show up for units. By default, the bottom row is used for learned ability icons.

You could make the ability true channeling ability that the caster can break out from
....i dont want the ability true channeling. Its a bomb, not a channel ability.
Then why do you have such long follow through time? The caster keeps the order way too long after casting the ability.

Why is the angle converted away from radians in the first place?
....is there a better way to do it ?
You only need degrees for facings of unit, but you are not setting any facing in that spell. Therefore you should only use radians. In getAngleBetweenXY you convert radians to degrees only to convert the same angle from degrees back to radians in polarProjectionX/Y. You are no using the degree value anywhere.
 
Last edited:
Level 29
Joined
Oct 24, 2012
Messages
6,543
Not everyone knows how to make a proper dummy unit. In fact the vast majority don't know that. If a spell uses a dummy unit, it must provide a proper dummy unit for that reason. Spells should be useable and glitchelss without the user having to edit it.

ok i already fixed this.

Spells are not just triggering/coding. Tooltips and icons are a part of the complete package. Sure people can change them to their liking, but you should still provide a complete spell.

i fixed this in the update also

The learn icon position doesn't match the position of the learned ability. Additionally, the learned icon shows up where no abilities show up for units. By default, the boom row is used for learned ability icons.

umm not sure y that matters ? or how to change it.

Then why do you have such long follow through time? The caster keeps the order way too long after casting the ability.

i have the follow through time high because i always set it like that. it could be shortened it really doesnt matter either way IMO.

You only need degrees for facings of unit, but you are not setting any facing in that spell. Therefore you should only use radians. In getAngleBetweenXY you convert radians to degrees only to convert the same angle from degrees back to radians in polarProjectionX/Y. You are no using the degree value anywhere.

u said that already but how do i change that ? what are the formulas that u would use so it didnt do that ? thats the way ive always seen angles and polar projections done.
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
1) Art - Button positions
2) Follow through time matter. It sounds to me you don't know what it does. It is the time that the unit keeps looping the cast animation and keeps the ability order. The unit won't auto-attack enemies for example during follow thorugh time, so it does matter a lot.
3) Remove all degtorad/radtodeg conversions.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
1) Art - Button positions
2) Follow through time matter. It sounds to me you don't know what it does. It is the time that the unit keeps looping the cast animation and keeps the ability order. The unit won't auto-attack enemies for example during follow thorugh time, so it does matter a lot.
3) Remove all degtorad/radtodeg conversions.

1) ok will fix it.
2) ik what follow through time does. i will change it to the length of the spells.
3) again what are the other formulas without them ????? u keep telling me to remove them. im asking for the formulas
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
So what becomes of these when you remove degtorad and radtodeg conversions?
JASS:
    private static method getAngleBetweenXY takes real x1, real y1, real x2, real y2 returns real
        return bj_RADTODEG * Atan2( y1 - y2, x1 - x2)
    endmethod

    private static method polarProjectionX takes real x, real dist, real angle returns real // returns x
        return x + dist * Cos( angle*bj_DEGTORAD)
    endmethod

    private static method polarProjectionY takes real y, real dist, real angle returns real // returns y
        return y + dist * Sin( angle*bj_DEGTORAD)
    endmethod


JASS:
    private static method getAngleBetweenXY takes real x1, real y1, real x2, real y2 returns real
        return Atan2( y1 - y2, x1 - x2)
    endmethod

    private static method polarProjectionX takes real x, real dist, real angle returns real // returns x
        return x + dist * Cos( angle)
    endmethod

    private static method polarProjectionY takes real y, real dist, real angle returns real // returns y
        return y + dist * Sin( angle)
    endmethod
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
So what becomes of these when you remove degtorad and radtodeg conversions?
JASS:
    private static method getAngleBetweenXY takes real x1, real y1, real x2, real y2 returns real
        return bj_RADTODEG * Atan2( y1 - y2, x1 - x2)
    endmethod

    private static method polarProjectionX takes real x, real dist, real angle returns real // returns x
        return x + dist * Cos( angle*bj_DEGTORAD)
    endmethod

    private static method polarProjectionY takes real y, real dist, real angle returns real // returns y
        return y + dist * Sin( angle*bj_DEGTORAD)
    endmethod


JASS:
    private static method getAngleBetweenXY takes real x1, real y1, real x2, real y2 returns real
        return Atan2( y1 - y2, x1 - x2)
    endmethod

    private static method polarProjectionX takes real x, real dist, real angle returns real // returns x
        return x + dist * Cos( angle)
    endmethod

    private static method polarProjectionY takes real y, real dist, real angle returns real // returns y
        return y + dist * Sin( angle)
    endmethod

Ahaha
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
EVENT_PLAYER_UNIT_SPELL_CAST - no
0.00 follow through time - no
GetWidgetLife - no
call SetUnitPropWindow( this.caster, GetUnitDefaultPropWindow( this.caster)) - no

Are damage- and attack types configrable? - no
Is there a hotkey listed? - no

Needs fix

1) ok ill change that
2) y not ? its not a channeling spell.
3) forgot to remove that
4) forgot to change that
5) ok i will make that configurable.
6) y does a hotkey matter ? they can put there own if they want.
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
Oh I just saw it you're double privating !
JASS:
private struct impBombSpell extends array
    implement Alloc
    
    private real aoeTotal
    private unit caster
    private real casterX
    private real casterY
    private real decScale
    private real damToDeal
    private unit dummy
    private integer durCounter
    private integer durInt1
    private integer durInt2
    private effect eff
    private real propWindow
    private real scale
    private unit target
    private real distanceMX
    private real distanceMY
    private real targetMX
    private real targetMY
    private real targetSX
    private real targetSY

Even the methods ^^
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
Oh I just saw it you're double privating !
JASS:
private struct impBombSpell extends array
    implement Alloc
    
    private real aoeTotal
    private unit caster
    private real casterX
    private real casterY
    private real decScale
    private real damToDeal
    private unit dummy
    private integer durCounter
    private integer durInt1
    private integer durInt2
    private effect eff
    private real propWindow
    private real scale
    private unit target
    private real distanceMX
    private real distanceMY
    private real targetMX
    private real targetMY
    private real targetSX
    private real targetSY

Even the methods ^^

Lol thanks for that. I made this a long time ago i didn't even think to check for that stuff.
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
Oh there is no problem with the longer name with double privating :O ?
I wanna see this too xD
*Going back to test*

EDIT : Actually you're right.
But how amazing this can be.
When parsing private members get nothing more in their names.
That means that private struct against regular struct with everything private is slower :O
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
-No follow through time
-Lackluster tooltip
-No learn hotkey
-If a unit is close to the caster while the spell is on and I order the caster to move, the caster is moved away from where the spell was cast
-I would make the spell channeled. Now the unit just casts it and it goes on an on and the caster can not move but it can do anyting else
-getAngleBetweenXY should be yx not xy, since you return the angle from y to x
-You could do like this: call SetUnitScale( this.target, this.scale, 0, 0)
The y and z won't make a difference
-Instead of SquareRoot(x*x + y*y) > VELOCITY/2, you could do (x*x + y*y) > VELOCITY*VELOCITY/2. The vel*vel could be precalculated. Just an optimization to avoid sqrt calls
-The dummy should have Locust in object editor, and it does have it. So no need to add it with triggers
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
-No follow through time
-Lackluster tooltip
-No learn hotkey
-If a unit is close to the caster while the spell is on and I order the caster to move, the caster is moved away from where the spell was cast
-I would make the spell channeled. Now the unit just casts it and it goes on an on and the caster can not move but it can do anyting else
-getAngleBetweenXY should be yx not xy, since you return the angle from y to x
-You could do like this: call SetUnitScale( this.target, this.scale, 0, 0)
The y and z won't make a difference
-Instead of SquareRoot(x*x + y*y) > VELOCITY/2, you could do (x*x + y*y) > VELOCITY*VELOCITY/2. The vel*vel could be precalculated. Just an optimization to avoid sqrt calls
-The dummy should have Locust in object editor, and it does have it. So no need to add it with triggers

As i said above this is a bomb. It will never be channeling. That is entirely my choice.
I don't care about hotkeys click the button.
I'll change the spell so the caster can move after it casts. That makes more sense than a channeled bomb.
I always label it XY. I don't see a reason to change it.
If y and z don't do anything then there is no reason to change it.
As long as it works the same I will change the velocity code. // This adjustment seems to screw up a lot of the calculations so i am leaving the old square root calculations.
I must've forgot to remove from code after i added it in OE.

Will edit soon.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
As i said above this is a bomb. It will never be channeling. That is entirely my choice.
Follow through time is required to display the animation used for the spell, for instance "attack" or "spell". If you set it to 0 the spell will go off, but the casters animation will immediately end on spell cast. It's just a matter of eyecandy.
I always label it XY. I don't see a reason to change it.
To improve read-ability and because it is logical. You could also name your variables and functions aa, ab, ac, ad, ... with the argument most people use a map optimizer in the end anyways.

Edit: I don't see a reason for the last these lines. I can't imagine a case, where a dummy tries to flee ^^. Use dum if you initialize that local unit.
JASS:
    set udg_dummyImpBomb[ m] = CreateUnit( GetOwningPlayer( c), udg_dummyUnitImpBomb, x, y, 0)
    set dum = udg_dummyImpBomb[ m]
    call SetUnitPropWindow( dum, 0.00)
    call SetUnitX( udg_dummyImpBomb[ m], x)
    call SetUnitY( udg_dummyImpBomb[ m], y)
- call SetUnitScale( udg_targetImpBomb[ L], udg_scaleImpBomb[ L], udg_scaleImpBomb[ L], udg_scaleImpBomb[ L]) --> units can only be scaled in x-axis. You could simple pass in 1 for y and z.
It doesn't change anything, but reading 1 should be faster than reading the array.
- call DestroyEffect( udg_effectImpBomb[ L]) null that and also this one call RemoveUnit( udg_dummyImpBomb[ L])
- call SetUnitPropWindow( udg_casterImpBomb[ L], GetUnitDefaultPropWindow( udg_casterImpBomb[ L])) This will not reset the PropWindow properly, also the casters prop window is never changed in the first place.
- The tooltips could be improved.

I like the effects of the spell aswell as the concept itself. The caster could perform the full cast animtion and once the bomb is set new units can run through it without getting involved :/.
 
Last edited:
Level 10
Joined
Aug 21, 2010
Messages
316
This is totally unnecessary and can be optimized with four simple lines
JASS:
function DistanceBetweenXYImpBomb takes real x1, real y1, real x2, real y2 returns real
    local real x = x2 - x1
    local real y = y2 - y1
    return SquareRoot(x*x + y*y)
endfunction

function GetAngleBetweenXYImpBomb takes real x1, real y1, real x2, real y2 returns real
    return Atan2( y1 - y2, x1 - x2)
endfunction

function PolarProjectionXImpBomb takes real x, real dist, real angle returns real // returns x
    return x + dist * Cos( angle)
endfunction

function PolarProjectionYImpBomb takes real y, real dist, real angle returns real // returns y
    return y + dist * Sin( angle)
endfunction

But that does not mean it is wrong!

If you already use vJass,then do not use this
JASS:
TriggerRegisterAnyUnitEventBJ
Again I say, it is not wrong but it looks ugly.
 
Top