• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[Trigger] Need help with an MUI issue

Status
Not open for further replies.
Level 19
Joined
Jun 16, 2007
Messages
1,574
Hello,

I've currently been tweaking with an MUI spell which was created for me by "Wizardum". The spell is based on the dragonball z move "Kamehameha".

I've just tweaked around with it, and added a few more actions so it can create more then just a kamehameha, since most of the dbz spells are basicly the same.

(Yes i've changed the triggers back to how they were before editing)

The issue is after 20 blasts the fps drops down to around 19.8fps.
The map size, and amount of doodads and units so far:
Map Size: 224x160
Doodads (So far): 1518
Units (So far): 1

And here's the trigger (Edited version):

  • Kamehameha Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Kamehameha
    • Actions
      • -------- this checks if the K_Index[1] is equal to 0 --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • K_Index[1] Equal to 0
        • Then - Actions
          • -------- if it is, it will turn on the Loop trigger --------
          • Animation - Play (Triggering unit)'s Spell Throw animation
          • Trigger - Turn on Kamehameha Loop <gen>
        • Else - Actions
      • -------- the K_Index[1] holds the number of instances currently active, so we increase it by one --------
      • Set K_Index[1] = (K_Index[1] + 1)
      • -------- the K_Index[2] is used to store the data in variables, we also increase it by one --------
      • Set K_Index[2] = (K_Index[2] + 1)
      • -------- this is the speed of the missile, it's common to all missiles so there is no need to index it --------
      • Set K_Speed = 38.00
      • -------- the distance at which the missile will collide with a unit --------
      • Set K_CollisionRadius = 100.00
      • -------- units within this distance will be damaged on the explosion --------
      • Set K_ExplosionRadius = 400.00
      • -------- this is the damage dealt to units --------
      • Set K_Damage = ((Real((Intelligence of (Triggering unit) (Exclude bonuses)))) x 2.00)
      • -------- this will be the duration of the missile, this one is indexed because it will be changed over time, and it's unique to each missile --------
      • Set K_Duration[K_Index[2]] = 1.50
      • -------- this stores the caster --------
      • Set K_Caster[K_Index[2]] = (Triggering unit)
      • -------- here we store the caster's position --------
      • Set TempPoint[0] = (Position of (Triggering unit))
      • -------- and here the target point --------
      • Set TempPoint[1] = (Target point of ability being cast)
      • -------- this is the angle at which the missile will move, it's angle between the caster's position and the target point --------
      • Set K_Direction[K_Index[2]] = (Angle from TempPoint[0] to TempPoint[1])
      • -------- here we create the missile --------
      • Unit - Create 1 Ki_Head for (Owner of (Triggering unit)) at (TempPoint[0] offset by 50.00 towards (Facing of (Triggering unit)) degrees) facing TempPoint[0]
      • -------- and store it into a variable --------
      • Set K_Missile[K_Index[2]] = (Last created unit)
      • -------- finally we remove the point memory leaks --------
      • Custom script: call RemoveLocation( udg_TempPoint[0] )
      • Custom script: call RemoveLocation( udg_TempPoint[1] )
  • Kamehameha Loop
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • -------- so basically this will run every instance, from 1 to the K_Index[2] that holds the last instance --------
      • For each (Integer K_Int) from 1 to K_Index[2], do (Actions)
        • Loop - Actions
          • -------- this checks if the duration is greater than 0, if it is it will make the missile move --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • K_Duration[K_Int] Greater than 0.00
            • Then - Actions
              • -------- here the duration is decreased --------
              • Set K_Duration[K_Int] = (K_Duration[K_Int] - 0.08)
              • -------- here we store the point of the missile --------
              • Set TempPoint[2] = (Position of K_Missile[K_Int])
              • -------- and here the new point of the missile, which is it's original point plus the speed towards the direction --------
              • Set TempPoint[3] = (TempPoint[2] offset by K_Speed towards K_Direction[K_Int] degrees)
              • -------- now we move it --------
              • Unit - Move K_Missile[K_Int] instantly to TempPoint[3]
              • Set TempLocation = (Position of K_Missile[K_Int])
              • Destructible - Pick every destructible within 200.00 of TempLocation and do (Actions)
                • Loop - Actions
                  • Destructible - Kill (Picked destructible)
              • Custom script: call RemoveLocation(udg_TempLocation)
              • -------- we create a dummy trail unit --------
              • Unit - Create 1 Ki_Trail for (Owner of K_Caster[K_Int]) at TempPoint[2] facing K_Direction[K_Int] degrees
              • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
              • -------- then we pick every unit within CollisionRadius of the position of the missile that is not a building, it's alive and if it is an enemy --------
              • Set TempGroup = (Units within K_CollisionRadius of TempPoint[3] matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of K_Caster[K_Int])) Equal to True))))
              • -------- if the number of units in the group is greater than 0, than it means that there is a unit colliding with the missile --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Number of units in TempGroup) Greater than 0
                • Then - Actions
                  • -------- so basically here we set the duration to 0, so the explosion can occur immediately --------
                  • Set K_Duration[K_Int] = 0.00
                • Else - Actions
              • -------- now we remove one of the points used --------
              • Custom script: call RemoveLocation( udg_TempPoint[2] )
              • -------- and we destroy the group since we don't need it anymore --------
              • Custom script: call DestroyGroup( udg_TempGroup )
              • -------- however we must check if the duration is lesser or equal to 0 --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • K_Duration[K_Int] Less than or equal to 0.00
                • Then - Actions
                  • -------- if it is, then we willl create the nuclear explosion special effect --------
                  • Special Effect - Create a special effect at TempPoint[3] using NuclearExplosion.mdx
                  • -------- and immediately destroy it --------
                  • Special Effect - Destroy (Last created special effect)
                  • -------- we kill the missile --------
                  • Unit - Kill K_Missile[K_Int]
                  • Set TempUnitGroup = (Units owned by (Owner of K_Caster[K_Int]) of type Ki_Trail)
                  • Unit Group - Pick every unit in TempUnitGroup and do (Actions)
                    • Loop - Actions
                      • Unit - Kill (Picked unit)
                  • Custom script: call DestroyGroup(udg_TempUnitGroup)
                  • -------- then we pick every unit within ExplosionRadius of the missile position and check if it is not a building, if it is alive and if it is an enemy --------
                  • Set TempGroup = (Units within K_ExplosionRadius of TempPoint[3] matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of K_Caster[K_Int])) Equal to True))))
                  • Unit Group - Pick every unit in TempGroup and do (Actions)
                    • Loop - Actions
                      • -------- and here we will pick every unit in the group and damage it --------
                      • Unit - Cause K_Caster[K_Int] to damage (Picked unit), dealing K_Damage damage of attack type Spells and damage type Universal
                  • -------- now we destroy the group --------
                  • Custom script: call DestroyGroup( udg_TempGroup )
                  • Animation - Reset K_Caster[K_Int]'s animation
                  • -------- this will decrease one to the K_Index[1], which is the number of running instances --------
                  • Set K_Index[1] = (K_Index[1] - 1)
                  • -------- now this checks if the number of instances is equal to 0 --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • K_Index[1] Equal to 0
                    • Then - Actions
                      • -------- if it is, we will set the K_index[2] to 0, basicaly this is a fast way of cleaning the all stored data --------
                      • Set K_Index[2] = 0
                      • -------- and then we turn off this trigger --------
                      • Trigger - Turn off (This trigger)
                    • Else - Actions
                • Else - Actions
              • -------- this point could have been used before that's why we only removing it in the end. --------
              • Custom script: call RemoveLocation( udg_TempPoint[3] )
            • Else - Actions
This MUI version is leaking and bugging somewhere because i've currently implanted Valk's kamehameha he created for us a while back, and that doesn't drop the fps at all.
 
Last edited:
Level 10
Joined
Oct 31, 2009
Messages
352
I'm at School ATM and trying (and failing) to read your code on my I-phone.

I didn't see any obvious leaks but I will take a more detailed look when I get home of your problem has not been solved by then.

One thing I CAN tell you is that if it is notably reducing lag on the 10th cast it is unlikely that your problem is just a minor point or group leak. Again I'll take a look when I get home but it could be one of the following:

1. You are leaking a substancial amount if units
2. You are removing leaks that aren't there (I've had lag problems b/c of this myself
3. Your not properly resetting a variable and by the 10th cast it is causing a problem

one minor thing I did notice, why do you set the first effect variables in the "cast trigger" and then immediately clear them? You can just use "destroy - last created special effect"
 
Level 19
Joined
Jun 16, 2007
Messages
1,574
Ok i changed

  • Else - Actions
    • -------- if it is, it will turn on the Loop trigger --------
    • Animation - Play (Triggering unit)'s Spell Throw animation
    • Special Effect - Create a special effect attached to the right hand of (Triggering unit) using Effects\SuperShinyThingy.mdx
    • Set K_Effects[K_Index[2]] = (Last created special effect)
    • Special Effect - Destroy K_Effects[K_Index[2]]
    • Trigger - Turn on Ki Blast Loop <gen>
  • Else - Actions
    • -------- if it is, it will turn on the Loop trigger --------
    • Animation - Play (Triggering unit)'s Spell Throw animation
    • Special Effect - Create a special effect attached to the right hand of (Triggering unit) using Effects\SuperShinyThingy.mdx
    • Special Effect - Destroy (Last created special effect)
    • Trigger - Turn on Ki Blast Loop <gen>
When you get back, can you point at the main causes. (Since that wont really change anything)
 
You leak 3+ unit groups every 0.05 seconds in the second trigger, meaning that you are massively leaking RAM.

  • Unit Group - Pick every unit in (Units owned by (Owner of K_Caster[K_Int]) of type Ki_Trail (Purple)) and do (Actions)
Replace that with:
  • Set Group = Units owned by (Owner of K_Caster[K_Int]) of type Ki_Trail (Purple)
  • Unit Group - Pick every unit in (Group) and do (Actions)
    • Loop - Actions
      • -------- Actions --------
  • Custom script: call DestroyGroup(udg_Group)
 
Level 19
Joined
Jun 16, 2007
Messages
1,574
If you change it to a working Jass script add a Documentry so i can follow the steps to edit the script, and add other stuff later.

Because i haven't finished adding all the different units, to detect which is which.

Give me a few seconds to get the code.

JASS:
function Trig_Ki_Blast_Cast_Func001C takes nothing returns boolean
    if ( ( GetSpellAbilityId() == 'A005' ) ) then
        return true
    endif
    if ( ( GetSpellAbilityId() == 'A006' ) ) then
        return true
    endif
    if ( ( GetSpellAbilityId() == 'A007' ) ) then
        return true
    endif
    if ( ( GetSpellAbilityId() == 'A009' ) ) then
        return true
    endif
    if ( ( GetSpellAbilityId() == 'A008' ) ) then
        return true
    endif
    if ( ( GetSpellAbilityId() == 'A004' ) ) then
        return true
    endif
    if ( ( GetUnitTypeId(GetTriggerUnit()) == 'H00I' ) ) then
        return true
    endif
    return false
endfunction

function Trig_Ki_Blast_Cast_Conditions takes nothing returns boolean
    if ( not Trig_Ki_Blast_Cast_Func001C() ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Cast_Func003Func001Func001C takes nothing returns boolean
    if ( not ( GetUnitTypeId(udg_K_Caster[udg_K_Index[2]]) == 'H00I' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Cast_Func003Func001C takes nothing returns boolean
    if ( not ( GetOwningPlayer(udg_K_Caster[udg_K_Index[2]]) == Player(11) ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Cast_Func003C takes nothing returns boolean
    if ( not ( udg_K_Index[1] == 0 ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Cast_Func029Func001Func001Func001C takes nothing returns boolean
    if ( not ( GetUnitTypeId(udg_K_Caster[udg_K_Index[2]]) == 'H00I' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Cast_Func029Func001Func001C takes nothing returns boolean
    if ( not ( GetOwningPlayer(udg_K_Caster[udg_K_Index[2]]) == Player(11) ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Cast_Func029Func001C takes nothing returns boolean
    if ( not ( GetOwningPlayer(udg_K_Caster[udg_K_Index[2]]) == Player(7) ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Cast_Func029C takes nothing returns boolean
    if ( not ( GetOwningPlayer(udg_K_Caster[udg_K_Index[2]]) == Player(1) ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Cast_Actions takes nothing returns nothing
    // this checks if the K_Index[1] is equal to 0
    if ( Trig_Ki_Blast_Cast_Func003C() ) then
        if ( Trig_Ki_Blast_Cast_Func003Func001C() ) then
            // if it is, it will turn on the Loop trigger
            call AddSpecialEffectTargetUnitBJ( "left hand", GetTriggerUnit(), "Effects\\SuperShinyThingy.mdx" )
            call DestroyEffectBJ( GetLastCreatedEffectBJ() )
            call EnableTrigger( gg_trg_Ki_Blast_Loop )
        else
            if ( Trig_Ki_Blast_Cast_Func003Func001Func001C() ) then
                // if it is, it will turn on the Loop trigger
                call SetUnitAnimation( GetTriggerUnit(), "Spell Slam" )
                call AddSpecialEffectTargetUnitBJ( "right hand", GetTriggerUnit(), "Effects\\SuperShinyThingy.mdx" )
                call DestroyEffectBJ( GetLastCreatedEffectBJ() )
                call EnableTrigger( gg_trg_Ki_Blast_Loop )
            else
                // if it is, it will turn on the Loop trigger
                call SetUnitAnimation( GetTriggerUnit(), "Spell Throw" )
                call AddSpecialEffectTargetUnitBJ( "right hand", GetTriggerUnit(), "Effects\\SuperShinyThingy.mdx" )
                call DestroyEffectBJ( GetLastCreatedEffectBJ() )
                call EnableTrigger( gg_trg_Ki_Blast_Loop )
            endif
        endif
    else
    endif
    // the K_Index[1] holds the number of instances currently active, so we increase it by one
    set udg_K_Index[1] = ( udg_K_Index[1] + 1 )
    // the K_Index[2] is used to store the data in variables, we also increase it by one
    set udg_K_Index[2] = ( udg_K_Index[2] + 1 )
    // Timer For Wait
    set udg_K_Timer[udg_K_Int] = 60
    // this is the speed of the missile, it's common to all missiles so there is no need to index it
    set udg_K_Speed = 38.00
    // the distance at which the missile will collide with a unit
    set udg_K_CollisionRadius = 100.00
    // units within this distance will be damaged on the explosion
    set udg_K_ExplosionRadius = 250.00
    // this is the damage dealt to units
    set udg_K_Damage = ( ( I2R(GetHeroStatBJ(bj_HEROSTAT_INT, GetTriggerUnit(), false)) + I2R(GetUnitAbilityLevelSwapped(GetSpellAbilityId(), GetTriggerUnit())) ) * 2.00 )
    // this will be the duration of the missile, this one is indexed because it will be changed over time, and it's unique to each missile
    set udg_K_Duration[udg_K_Index[2]] = 1.00
    // this stores the caster
    set udg_K_Caster[udg_K_Index[2]] = GetTriggerUnit()
    // here we store the caster's position
    set udg_TempPoint[0] = GetUnitLoc(GetTriggerUnit())
    // and here the target point
    set udg_TempPoint[1] = GetSpellTargetLoc()
    // this is the angle at which the missile will move, it's angle between the caster's position and the target point
    set udg_K_Direction[udg_K_Index[2]] = AngleBetweenPoints(udg_TempPoint[0], udg_TempPoint[1])
    // here we create the missile
    if ( Trig_Ki_Blast_Cast_Func029C() ) then
        call CreateNUnitsAtLocFacingLocBJ( 1, 'h00O', GetOwningPlayer(GetTriggerUnit()), PolarProjectionBJ(udg_TempPoint[0], 50.00, GetUnitFacing(GetTriggerUnit())), GetUnitLoc(GetTriggerUnit()) )
        // and store it into a variable
        set udg_K_Missile[udg_K_Index[2]] = GetLastCreatedUnit()
    else
        if ( Trig_Ki_Blast_Cast_Func029Func001C() ) then
            call CreateNUnitsAtLocFacingLocBJ( 1, 'h00M', GetOwningPlayer(GetTriggerUnit()), PolarProjectionBJ(udg_TempPoint[0], 50.00, GetUnitFacing(GetTriggerUnit())), GetUnitLoc(GetTriggerUnit()) )
            // and store it into a variable
            set udg_K_Missile[udg_K_Index[2]] = GetLastCreatedUnit()
        else
            if ( Trig_Ki_Blast_Cast_Func029Func001Func001C() ) then
                call CreateNUnitsAtLocFacingLocBJ( 1, 'h00P', GetOwningPlayer(GetTriggerUnit()), PolarProjectionBJ(udg_TempPoint[0], 50.00, GetUnitFacing(GetTriggerUnit())), GetUnitLoc(GetTriggerUnit()) )
                // and store it into a variable
                set udg_K_Missile[udg_K_Index[2]] = GetLastCreatedUnit()
            else
                if ( Trig_Ki_Blast_Cast_Func029Func001Func001Func001C() ) then
                    call CreateNUnitsAtLocFacingLocBJ( 1, 'h00R', GetOwningPlayer(GetTriggerUnit()), PolarProjectionBJ(udg_TempPoint[0], 50.00, GetUnitFacing(GetTriggerUnit())), GetUnitLoc(GetTriggerUnit()) )
                    // and store it into a variable
                    set udg_K_Missile[udg_K_Index[2]] = GetLastCreatedUnit()
                else
                    call CreateNUnitsAtLocFacingLocBJ( 1, 'h00K', GetOwningPlayer(GetTriggerUnit()), PolarProjectionBJ(udg_TempPoint[0], 50.00, GetUnitFacing(GetTriggerUnit())), GetUnitLoc(GetTriggerUnit()) )
                    // and store it into a variable
                    set udg_K_Missile[udg_K_Index[2]] = GetLastCreatedUnit()
                endif
            endif
        endif
    endif
    // finally we remove the point memory leaks
    call RemoveLocation( udg_TempPoint[0] )
    call RemoveLocation( udg_TempPoint[1] )
endfunction

//===========================================================================
function InitTrig_Ki_Blast_Cast takes nothing returns nothing
    set gg_trg_Ki_Blast_Cast = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Ki_Blast_Cast, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Ki_Blast_Cast, Condition( function Trig_Ki_Blast_Cast_Conditions ) )
    call TriggerAddAction( gg_trg_Ki_Blast_Cast, function Trig_Ki_Blast_Cast_Actions )
endfunction

JASS:
function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func009A takes nothing returns nothing
    call KillDestructable( GetEnumDestructable() )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func011Func001Func001Func001C takes nothing returns boolean
    if ( not ( GetUnitTypeId(udg_K_Caster[udg_K_Int]) == 'H00I' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func011Func001Func001C takes nothing returns boolean
    if ( not ( GetOwningPlayer(udg_K_Caster[udg_K_Int]) == Player(11) ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func011Func001C takes nothing returns boolean
    if ( not ( GetOwningPlayer(udg_K_Caster[udg_K_Int]) == Player(7) ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func011C takes nothing returns boolean
    if ( not ( GetOwningPlayer(udg_K_Caster[udg_K_Int]) == Player(1) ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func013002003001 takes nothing returns boolean
    return ( IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func013002003002001 takes nothing returns boolean
    return ( IsUnitAliveBJ(GetFilterUnit()) == true )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func013002003002002 takes nothing returns boolean
    return ( IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(udg_K_Caster[udg_K_Int])) == true )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func013002003002 takes nothing returns boolean
    return GetBooleanAnd( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func013002003002001(), Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func013002003002002() )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func013002003 takes nothing returns boolean
    return GetBooleanAnd( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func013002003001(), Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func013002003002() )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func015C takes nothing returns boolean
    if ( not ( CountUnitsInGroup(udg_TempGroup) > 0 ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func001Func002A takes nothing returns nothing
    call KillUnit( GetEnumUnit() )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func001Func004Func002A takes nothing returns nothing
    call KillUnit( GetEnumUnit() )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func001Func004Func005A takes nothing returns nothing
    call KillUnit( GetEnumUnit() )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func001Func004C takes nothing returns boolean
    if ( not ( GetUnitTypeId(udg_K_Caster[udg_K_Int]) == 'H00I' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func001C takes nothing returns boolean
    if ( not ( GetOwningPlayer(udg_K_Caster[udg_K_Int]) == Player(11) ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func003A takes nothing returns nothing
    call KillUnit( GetEnumUnit() )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002C takes nothing returns boolean
    if ( not ( GetOwningPlayer(udg_K_Caster[udg_K_Int]) == Player(7) ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func003A takes nothing returns nothing
    call KillUnit( GetEnumUnit() )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007C takes nothing returns boolean
    if ( not ( GetOwningPlayer(udg_K_Caster[udg_K_Int]) == Player(1) ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func009002003001 takes nothing returns boolean
    return ( IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func009002003002001 takes nothing returns boolean
    return ( IsUnitAliveBJ(GetFilterUnit()) == true )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func009002003002002 takes nothing returns boolean
    return ( IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(udg_K_Caster[udg_K_Int])) == true )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func009002003002 takes nothing returns boolean
    return GetBooleanAnd( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func009002003002001(), Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func009002003002002() )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func009002003 takes nothing returns boolean
    return GetBooleanAnd( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func009002003001(), Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func009002003002() )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func010A takes nothing returns nothing
    // and here we will pick every unit in the group and damage it
    call UnitDamageTargetBJ( udg_K_Caster[udg_K_Int], GetEnumUnit(), udg_K_Damage, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL )
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func017C takes nothing returns boolean
    if ( not ( udg_K_Index[1] == 0 ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021C takes nothing returns boolean
    if ( not ( udg_K_Duration[udg_K_Int] <= 0.00 ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002Func002Func002C takes nothing returns boolean
    if ( not ( udg_K_Duration[udg_K_Int] > 0.00 ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001Func002C takes nothing returns boolean
    if ( not ( udg_K_Timer[udg_K_Int] == 0 ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Func001C takes nothing returns boolean
    if ( not ( udg_K_Timer[udg_K_Int] >= 1 ) ) then
        return false
    endif
    return true
endfunction

function Trig_Ki_Blast_Loop_Actions takes nothing returns nothing
    if ( Trig_Ki_Blast_Loop_Func001C() ) then
        set udg_K_Timer[udg_K_Int] = ( udg_K_Timer[udg_K_Int] - 5 )
    else
        if ( Trig_Ki_Blast_Loop_Func001Func002C() ) then
            // so basically this will run every instance, from 1 to the K_Index[2] that holds the last instance
            set udg_K_Int = 1
            loop
                exitwhen udg_K_Int > udg_K_Index[2]
                // this checks if the duration is greater than 0, if it is it will make the missile move
                if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002C() ) then
                    // here the duration is decreased
                    set udg_K_Duration[udg_K_Int] = ( udg_K_Duration[udg_K_Int] - 0.05 )
                    // here we store the point of the missile
                    set udg_TempPoint[2] = GetUnitLoc(udg_K_Missile[udg_K_Int])
                    // and here the new point of the missile, which is it's original point plus the speed towards the direction
                    set udg_TempPoint[3] = PolarProjectionBJ(udg_TempPoint[2], udg_K_Speed, udg_K_Direction[udg_K_Int])
                    // now we move it
                    call SetUnitPositionLoc( udg_K_Missile[udg_K_Int], udg_TempPoint[3] )
                    call EnumDestructablesInCircleBJ( 200.00, GetUnitLoc(udg_K_Missile[udg_K_Int]), function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func009A )
                    // we create a dummy trail unit
                    if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func011C() ) then
                        call CreateNUnitsAtLoc( 1, 'h00L', GetOwningPlayer(udg_K_Caster[udg_K_Int]), udg_TempPoint[2], udg_K_Direction[udg_K_Int] )
                    else
                        if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func011Func001C() ) then
                            call CreateNUnitsAtLoc( 1, 'h00N', GetOwningPlayer(udg_K_Caster[udg_K_Int]), udg_TempPoint[2], udg_K_Direction[udg_K_Int] )
                        else
                            if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func011Func001Func001C() ) then
                                call CreateNUnitsAtLoc( 1, 'h00Q', GetOwningPlayer(udg_K_Caster[udg_K_Int]), udg_TempPoint[2], udg_K_Direction[udg_K_Int] )
                            else
                                if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func011Func001Func001Func001C() ) then
                                    call CreateNUnitsAtLoc( 1, 'h00S', GetOwningPlayer(udg_K_Caster[udg_K_Int]), udg_TempPoint[2], udg_K_Direction[udg_K_Int] )
                                else
                                    call CreateNUnitsAtLoc( 1, 'h00J', GetOwningPlayer(udg_K_Caster[udg_K_Int]), udg_TempPoint[2], udg_K_Direction[udg_K_Int] )
                                endif
                            endif
                        endif
                    endif
                    // then we pick every unit within CollisionRadius of the position of the missile that is not a building, it's alive and if it is an enemy
                    set udg_TempGroup = GetUnitsInRangeOfLocMatching(udg_K_CollisionRadius, udg_TempPoint[3], Condition(function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func013002003))
                    // if the number of units in the group is greater than 0, than it means that there is a unit colliding with the missile
                    if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func015C() ) then
                        // so basically here we set the duration to 0, so the explosion can occur immediately
                        set udg_K_Duration[udg_K_Int] = 0.00
                    else
                    endif
                    // now we remove one of the points used
                    call RemoveLocation( udg_TempPoint[2] )
                    // and we destroy the group since we don't need it anymore
                    call DestroyGroup( udg_TempGroup )
                    // however we must check if the duration is lesser or equal to 0
                    if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021C() ) then
                        // if it is, then we willl create the nuclear explosion special effect
                        call AddSpecialEffectLocBJ( udg_TempPoint[3], "Effects\\NewDirtEXNofire.mdx" )
                        // and immediately destroy it
                        call DestroyEffectBJ( GetLastCreatedEffectBJ() )
                        // we kill the missile
                        call KillUnit( udg_K_Missile[udg_K_Int] )
                        if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007C() ) then
                            set udg_MyUnitGroup = GetUnitsOfPlayerAndTypeId(GetOwningPlayer(udg_K_Caster[udg_K_Int]), 'h00L')
                            call ForGroupBJ( udg_MyUnitGroup, function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func003A )
                            call DestroyGroup(udg_MyUnitGroup)
                        else
                            if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002C() ) then
                                set udg_MyUnitGroup = GetUnitsOfPlayerAndTypeId(GetOwningPlayer(udg_K_Caster[udg_K_Int]), 'h00N')
                                call ForGroupBJ( udg_MyUnitGroup, function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func003A )
                                call DestroyGroup(udg_MyUnitGroup)
                            else
                                if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func001C() ) then
                                    set udg_MyUnitGroup = GetUnitsOfPlayerAndTypeId(GetOwningPlayer(udg_K_Caster[udg_K_Int]), 'h00Q')
                                    call ForGroupBJ( udg_MyUnitGroup, function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func001Func002A )
                                    call DestroyGroup(udg_MyUnitGroup)
                                else
                                    if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func001Func004C() ) then
                                        set udg_MyUnitGroup = GetUnitsOfPlayerAndTypeId(GetOwningPlayer(udg_K_Caster[udg_K_Int]), 'h00S')
                                        call ForGroupBJ( udg_MyUnitGroup, function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func001Func004Func002A )
                                        call DestroyGroup(udg_MyUnitGroup)
                                    else
                                        set udg_MyUnitGroup = GetUnitsOfPlayerAndTypeId(GetOwningPlayer(udg_K_Caster[udg_K_Int]), 'h00J')
                                        call ForGroupBJ( udg_MyUnitGroup, function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func007Func002Func001Func004Func005A )
                                        call DestroyGroup(udg_MyUnitGroup)
                                    endif
                                endif
                            endif
                        endif
                        // then we pick every unit within ExplosionRadius of the missile position and check if it is not a building, if it is alive and if it is an enemy
                        set udg_TempGroup = GetUnitsInRangeOfLocMatching(udg_K_ExplosionRadius, udg_TempPoint[3], Condition(function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func009002003))
                        call ForGroupBJ( udg_TempGroup, function Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func010A )
                        // now we destroy the group
                        call DestroyGroup( udg_TempGroup )
                        call ResetUnitAnimation( udg_K_Caster[udg_K_Int] )
                        // this will decrease one to the K_Index[1], which is the number of running instances
                        set udg_K_Index[1] = ( udg_K_Index[1] - 1 )
                        // now this checks if the number of instances is equal to 0
                        if ( Trig_Ki_Blast_Loop_Func001Func002Func002Func002Func021Func017C() ) then
                            // if it is, we will set the K_index[2] to 0, basicaly this is a fast way of cleaning the all stored data
                            set udg_K_Index[2] = 0
                            // and then we turn off this trigger
                            call DisableTrigger( GetTriggeringTrigger() )
                        else
                        endif
                    else
                    endif
                    // this point could have been used before that's why we only removing it in the end.
                    call RemoveLocation( udg_TempPoint[3] )
                else
                endif
                set udg_K_Int = udg_K_Int + 1
            endloop
        else
        endif
    endif
endfunction

//===========================================================================
function InitTrig_Ki_Blast_Loop takes nothing returns nothing
    set gg_trg_Ki_Blast_Loop = CreateTrigger(  )
    call DisableTrigger( gg_trg_Ki_Blast_Loop )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Ki_Blast_Loop, 0.05 )
    call TriggerAddAction( gg_trg_Ki_Blast_Loop, function Trig_Ki_Blast_Loop_Actions )
endfunction
 
Last edited:
Level 19
Joined
Jun 16, 2007
Messages
1,574
First of all nice catch

second of all, WHAT?

it is true that GUI does require more processor time but how would that translate into this notable of a problem and why would it not occur on every cast? This has nothing to do with the format it's in

I know the first MUI version never caused FPS drop, but that was in a 64x64 map with only 30units, and 100doodads.

But sadly, even if i use just that version with no tweaks, and adjustments the FPS still drops dramaticly, within my map.
 
This will syntax correctly and has absolutely zero leaks. If the problem persists, it is likely a glitch with your custom model files.

JASS:
function Trig_Ki_Blast_Cast_Actions takes unit u,integer id,player p,integer i,string attach returns nothing
    local real angle = GetUnitFacing(u) // this is the angle at which the missile will move: the angle between the caster and the target
    local real x = GetUnitX(u) + 50.*Cos(angle * bj_DEGTORAD)
    local real y = GetUnitY(u) + 50.*Sin(angle * bj_DEGTORAD)
    if ( udg_K_Index[1] == 0 ) then
        if ( GetOwningPlayer(udg_K_Caster[i - 1]) == Player(11) ) then
            set attach = "left hand"
        elseif ( GetUnitTypeId(udg_K_Caster[i - 1]) == 'H00I' ) then
            call SetUnitAnimation( u, "Spell Slam" )
            set attach = "right hand"
        else
            call SetUnitAnimation( u, "Spell Throw" )
            set attach = "right hand"
        endif
        call DestroyEffect( AddSpecialEffectTarget( "Effects\\SuperShinyThingy.mdx",u,attach ) )
        call EnableTrigger( gg_trg_Ki_Blast_Loop )
    endif
 
    set udg_K_Index[1] = ( udg_K_Index[1] + 1 ) // the K_Index[1] holds the number of instances currently active, so we increase it by one
    set udg_K_Index[2] = i // the K_Index[2] is used to store the data in variables, we also increase it by one
    set udg_K_Timer[udg_K_Int] = 60 // Timer For Wait
    set udg_K_Speed = 38. // this is the speed of the missile, it's common to all missiles so there is no need to index it
    set udg_K_CollisionRadius = 100. // the distance at which the missile will collide with a unit
    set udg_K_ExplosionRadius = 250. // units within this distance will be damaged on the explosion
    set udg_K_Damage = GetHeroInt(u,false) + GetUnitAbilityLevel(u,id)*2. // this is the damage dealt to units:
    set udg_K_Duration[i] = 1. // this will be the duration of the missile, this one is indexed because it will be changed over time, and it's unique to each missile
    set udg_K_Caster[i] = u // this stores the caster
    set udg_K_Direction[i] = angle
 
    if ( p == Player(1) ) then
        set udg_K_Missile[i] = CreateUnit(p, 'h00O', x,y, angle )
    elseif ( p == Player(7) ) then
        set udg_K_Missile[i] = CreateUnit(p, 'h00M', x,y, angle )
    elseif ( p == Player(11) ) then
        set udg_K_Missile[i] = CreateUnit(p, 'h00P', x,y, angle )
    elseif ( GetUnitTypeId(u) == 'H00I' ) then
        set udg_K_Missile[i] = CreateUnit(p, 'h00R', x,y, angle )
    else
        set udg_K_Missile[i] = CreateUnit(p, 'h00K', x,y, angle )
    endif
 
endfunction
 
function Trig_Ki_Blast_Cast_Conditions takes nothing returns boolean
    local integer id = GetSpellAbilityId()
    if (id == 'A004' or id == 'A005' or id == 'A006' or id == 'A007' or id == 'A008' or id == 'A009' or GetUnitTypeId(GetTriggerUnit()) == 'H00I') then
        call Trig_Ki_Blast_Cast_Actions(GetTriggerUnit(),id,GetTriggerPlayer(),udg_K_Index[2] + 1,"")
    endif
    return false
endfunction
 
//===========================================================================
function InitTrig_Ki_Blast_Cast takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t,Condition(function Trig_Ki_Blast_Cast_Conditions))
endfunction

JASS:
function Trig_Ki_Blast_Kill_Destructables takes nothing returns boolean
    local destructable d = GetFilterDestructable()
    local real x = GetDestructableX(d) - bj_meleeNearestMineDist
    local real y = GetDestructableY(d) - bj_randomSubGroupChance
    if(SquareRoot(x*x + y*y) <= bj_enumDestructableRadius)then
        call KillDestructable(d)
    endif
    set d = null
    return false
endfunction
 
function Trig_Ki_Blast_KD_Setup takes real x,real y,real radius,rect r returns nothing
    set bj_meleeNearestMineDist = x
    set bj_randomSubGroupChance = y
    set bj_enumDestructableRadius = radius
    call SetRect(r,x - radius,y - radius,x + radius,y + radius)
    call EnumDestructablesInRect(r,Filter(function Trig_Ki_Blast_Kill_Destructables),null)
endfunction
 
function KiDummyExpireAll takes nothing returns boolean
    if(GetUnitTypeId(GetEnumUnit()) == bj_groupEnumTypeId)then
        call KillUnit(GetEnumUnit())
    endif
    return false
endfunction
 
function GetIdByKiFilter takes integer id,integer casterId returns integer
    if id == 1 then
        return 'h00L'
    elseif id == 7 then
        return 'h00N'
    elseif id == 11 then
        return 'h00Q'
    elseif casterId == 'H00I' then
        return 'h00S'
    endif
    return 'h00J'
endfunction
 
function KiTriFoldFiltUtil takes unit u returns boolean
    if GetWidgetLife(u) > 0. and IsUnitEnemy(u,bj_groupEnumOwningPlayer) and not IsUnitType(u,UNIT_TYPE_STRUCTURE) then
        if bj_wantDestroyGroup then
            call UnitDamageTarget(bj_groupRandomCurrentPick,u,udg_K_Damage,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_UNIVERSAL,WEAPON_TYPE_WHOKNOWS)
        else
            return true
        endif
    endif
    return false
endfunction
 
function KiTriFoldFilt takes nothing returns boolean
    return KiTriFoldFiltUtil(GetFilterUnit())
endfunction
 
function DoKiBlast takes integer i,rect r,unit u returns nothing
    local player  p = GetOwningPlayer(u)
    local real    x = GetUnitX(u)
    local real    y = GetUnitY(u)
 
    // Create a dummy trail unit
    call CreateUnit(p,GetIdByKiFilter(GetPlayerId(p),GetUnitTypeId(u)),x,y,udg_K_Direction[i])
 
    //get polar projection (point from point offset by angle)
    set x = x + udg_K_Speed*Cos(udg_K_Direction[i]*bj_DEGTORAD)
    set y = y + udg_K_Speed*Sin(udg_K_Direction[i]*bj_DEGTORAD)
 
    //move missile
    call SetUnitX(udg_K_Missile[i],x)
    call SetUnitY(udg_K_Missile[i],y)
 
    //kill trees
    call Trig_Ki_Blast_KD_Setup(x,y,200.,r)
 
    // if there is a (matching) unit within CollisionRadius, it collides with the missile and immediately detonates it.
    set bj_groupEnumOwningPlayer = p
    set bj_wantDestroyGroup = false
    call GroupEnumUnitsInRange(bj_lastCreatedGroup,x,y,udg_K_CollisionRadius,Filter(function KiTriFoldFilt))
    if FirstOfGroup(bj_lastCreatedGroup) != null then
        call GroupClear(bj_lastCreatedGroup)
        set udg_K_Duration[i] = 0.
    endif
 
    ///////////////////////////////////////////////////////////////////////////////////
    //The next part of the loop (explosion) occurs if the duration has reached zero: //
    ///////////////////////////////////////////////////////////////////////////////////
 
    if ( udg_K_Duration[i] <= 0. ) then
        call DestroyEffect(AddSpecialEffect("Effects\\NewDirtEXNofire.mdx",x,y))
        call KillUnit(udg_K_Missile[i])
 
        //kill dummies
        set bj_groupEnumTypeId = GetIdByKiFilter(GetPlayerId(p),GetUnitTypeId(u))
        call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup,p,Filter(function KiDummyExpireAll))
 
        //kill trees
        call Trig_Ki_Blast_KD_Setup(x,y,udg_K_ExplosionRadius,r)
 
        //kill units
        set bj_groupRandomCurrentPick = u
        set bj_wantDestroyGroup = true
        call GroupEnumUnitsInRange(bj_lastCreatedGroup,x,y,udg_K_ExplosionRadius,Filter(function KiTriFoldFilt))
        call SetUnitAnimation(u,"stand")
        set udg_K_Index[1] = udg_K_Index[1] - 1 // Decrease number of running instances
        if ( udg_K_Index[1] == 0 ) then // if no more instances...
            set udg_K_Index[2] = 0
            call DisableTrigger( gg_trg_Ki_Blast_Loop )
        endif
    endif
endfunction
 
function Trig_Ki_Blast_Loop takes rect r returns integer
    local integer i = 0
    local boolean b = bj_wantDestroyGroup
    loop
        exitwhen i >= udg_K_Index[2]
        set i = i + 1
        if ( udg_K_Duration[i] > 0. ) then
            set udg_K_Duration[i] = udg_K_Duration[i] - 0.05 // decrease duration
            call DoKiBlast(i,r,udg_K_Caster[i])
        endif
    endloop
    call RemoveRect(r)
    set bj_wantDestroyGroup = b
    return i
endfunction
 
function Trig_Ki_Blast_Setup takes nothing returns boolean
    if ( udg_K_Timer[udg_K_Int] <= 0 ) then
        set udg_K_Timer[udg_K_Int] = udg_K_Timer[udg_K_Int] - 5
    else
        set udg_K_Int = Trig_Ki_Blast_Loop(Rect(0.,0.,0.,0.))
    endif
    return false
endfunction
 
//===========================================================================
function InitTrig_Ki_Blast_Loop takes nothing returns nothing
    local trigger t = CreateTrigger()
    call DisableTrigger(t)
    call TriggerRegisterTimerEventPeriodic(t,0.05)
    call TriggerAddCondition(t,Condition(function Trig_Ki_Blast_Setup))
    set gg_trg_Ki_Blast_Loop = t
endfunction
 
Last edited:
Level 19
Joined
Jun 16, 2007
Messages
1,574
Can you tell me how to fix these Location and Group leaks by GUI, so i can fix it for future triggers.

I've just imported the Jass format you have posted, and the trigger has stopped working completely.

This is what it currently does now, charges the spell, creates the special effects, and creates the Ki_Blast Head, and then stops.

Its not detecting the second trigger.
 
Last edited:
It's impossible for me to test it as I don't know what the heck your variables are supposed to do. JASS, like any programming language, is not intuitive and needs debugging. I could only check that it compiled correctly.

It's hard for me to read GUI, but I can tell you that every "unit -create" in the first trigger leaks (facing position).

Leak:
  • Unit - Create 1 Ki_Head (Purple) for (Owner of (Triggering unit)) at (TempPoint[0] offset by 50.00 towards (Facing of (Triggering unit)) degrees) facing (Position of (Triggering unit))
You can try replacing my JASS code for the first trigger with this, but no promises:

JASS:
function Trig_Ki_Blast_Cast_Actions takes unit u,integer id,player p,string attach returns nothing
    local real angle = GetUnitFacing(u) // this is the angle at which the missile will move: the angle between the caster and the target
    local real x = GetUnitX(u) + 50.*Cos(angle * bj_DEGTORAD)
    local real y = GetUnitY(u) + 50.*Sin(angle * bj_DEGTORAD)
    local boolean b = GetUnitTypeId(u) == 'H00I'
    local integer i = udg_K_Index[1]
 
    if ( i == 0 ) then
        if GetOwningPlayer(u) == Player(11) then
            set attach = "left hand"
        elseif b then
            call SetUnitAnimation( u, "Spell Slam" )
            set attach = "right hand"
        else
            call SetUnitAnimation(u,"Spell Throw")
            set attach = "right hand"
        endif
        call DestroyEffect(AddSpecialEffectTarget("Effects\\SuperShinyThingy.mdx",u,attach))
        call EnableTrigger(gg_trg_Ki_Blast_Loop)
    endif
 
    set udg_K_Index[1] = udg_K_Index[1] + 1 // the K_Index[1] holds the number of instances currently active, so we increase it by one
    set udg_K_Index[2] = udg_K_Index[2] + 1 // the K_Index[2] is used to store the data in variables, we also increase it by one
    set udg_K_Timer[udg_K_Int] = 60         // Timer For Wait
    set udg_K_Speed = 38.                   // this is the speed of the missile, it's common to all missiles so there is no need to index it
    set udg_K_CollisionRadius = 100.        // the distance at which the missile will collide with a unit
    set udg_K_ExplosionRadius = 250.        // units within this distance will be damaged on the explosion
    set udg_K_Damage = GetHeroInt(u,false) + GetUnitAbilityLevel(u,id)*2. // this is the damage dealt to units:
    set udg_K_Duration[i] = 1.              // this will be the duration of the missile, this one is indexed because it will be changed over time, and it's unique to each missile
    set udg_K_Caster[i] = u                 // this stores the caster

    set udg_K_Direction[i] = angle
 
    if p == Player(1) then
        set udg_K_Missile[i] = CreateUnit(p,'h00O',x,y,angle)
    elseif p == Player(7) then
        set udg_K_Missile[i] = CreateUnit(p,'h00M',x,y,angle)
    elseif p == Player(11) then
        set udg_K_Missile[i] = CreateUnit(p,'h00P',x,y,angle)
    elseif b then
        set udg_K_Missile[i] = CreateUnit(p,'h00R',x,y,angle)
    else
        set udg_K_Missile[i] = CreateUnit(p,'h00K',x,y,angle)
    endif
 
endfunction
 
function Trig_Ki_Blast_Cast_Conditions takes nothing returns boolean
    local integer id = GetSpellAbilityId()
    if id == 'A004' or id == 'A005' or id == 'A006' or id == 'A007' or id == 'A008' or id == 'A009' or b then
        call Trig_Ki_Blast_Cast_Actions(GetTriggerUnit(),id,GetTriggerPlayer(),"")
    endif
    return false
endfunction
 
//===========================================================================
function InitTrig_Ki_Blast_Cast takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t,Condition(function Trig_Ki_Blast_Cast_Conditions))
endfunction
 
Last edited:
Level 19
Joined
Jun 16, 2007
Messages
1,574
Ok, well i'll change the GUI part for facing to this:
  • Unit - Create 1 Ki_Head (Purple) for (Owner of (Triggering unit)) at (TempPoint[0] offset by 50.00 towards (Facing of (Triggering unit)) degrees) facing (Position of K_Caster[K_Index[2]])
And see how it does,

Also going to CnP that updated version of the jass.

Edit: Ok well its still not running the next part of the trigger.

But first to make sure is it alright if i paste these into two different triggers ? or does it have to be in 1.
 
They have to be the two original triggers.

Here is the loop trigger with some added debug messages to help you find out which components are working:

JASS:
function Trig_Ki_Blast_Kill_Destructables takes nothing returns boolean
    local destructable d = GetFilterDestructable()
    local real x = GetDestructableX(d) - bj_meleeNearestMineDist
    local real y = GetDestructableY(d) - bj_randomSubGroupChance
    if(SquareRoot(x*x + y*y) <= bj_enumDestructableRadius)then
        call KillDestructable(d)
    endif
    set d = null
    return false
endfunction
 
function Trig_Ki_Blast_KD_Setup takes real x,real y,real radius,rect r returns nothing
    set bj_meleeNearestMineDist = x
    set bj_randomSubGroupChance = y
    set bj_enumDestructableRadius = radius
    call SetRect(r,x - radius,y - radius,x + radius,y + radius)
    call EnumDestructablesInRect(r,Filter(function Trig_Ki_Blast_Kill_Destructables),null)
endfunction
 
function KiDummyExpireAll takes nothing returns boolean
    if(GetUnitTypeId(GetEnumUnit()) == bj_groupEnumTypeId)then
        call KillUnit(GetEnumUnit())
    endif
    return false
endfunction
 
function GetIdByKiFilter takes integer id,integer casterId returns integer
    if id == 1 then
        return 'h00L'
    elseif id == 7 then
        return 'h00N'
    elseif id == 11 then
        return 'h00Q'
    elseif casterId == 'H00I' then
        return 'h00S'
    endif
    return 'h00J'
endfunction
 
function KiTriFoldFiltUtil takes unit u returns boolean
    if GetWidgetLife(u) > 0. and IsUnitEnemy(u,bj_groupEnumOwningPlayer) and not IsUnitType(u,UNIT_TYPE_STRUCTURE) then
        if bj_wantDestroyGroup then
            call UnitDamageTarget(bj_groupRandomCurrentPick,u,udg_K_Damage,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_UNIVERSAL,WEAPON_TYPE_WHOKNOWS)
        else
            return true
        endif
    endif
    return false
endfunction
 
function KiTriFoldFilt takes nothing returns boolean
    return KiTriFoldFiltUtil(GetFilterUnit())
endfunction
 
function DoKiBlast takes integer i,rect r,unit u returns nothing
    local player  p = GetOwningPlayer(u)
    local real    x = GetUnitX(u)
    local real    y = GetUnitY(u)
 
    // Create a dummy trail unit
    call CreateUnit(p,GetIdByKiFilter(GetPlayerId(p),GetUnitTypeId(u)),x,y,udg_K_Direction[i])
 
    //get polar projection (point from point offset by angle)
    set x = x + udg_K_Speed*Cos(udg_K_Direction[i]*bj_DEGTORAD)
    set y = y + udg_K_Speed*Sin(udg_K_Direction[i]*bj_DEGTORAD)
 
    //move missile
    call SetUnitX(udg_K_Missile[i],x)
    call SetUnitY(udg_K_Missile[i],y)
 
    //kill trees
    call Trig_Ki_Blast_KD_Setup(x,y,200.,r)
 
    // if there is a (matching) unit within CollisionRadius, it collides with the missile and immediately detonates it.
    set bj_groupEnumOwningPlayer = p
    set bj_wantDestroyGroup = false
    call GroupEnumUnitsInRange(bj_lastCreatedGroup,x,y,udg_K_CollisionRadius,Filter(function KiTriFoldFilt))
    if FirstOfGroup(bj_lastCreatedGroup) != null then
        call GroupClear(bj_lastCreatedGroup)
        set udg_K_Duration[i] = 0.
    endif
 
    ///////////////////////////////////////////////////////////////////////////////////
    //The next part of the loop (explosion) occurs if the duration has reached zero: //
    ///////////////////////////////////////////////////////////////////////////////////
 
    if ( udg_K_Duration[i] <= 0. ) then
        call DestroyEffect(AddSpecialEffect("Effects\\NewDirtEXNofire.mdx",x,y))
        call KillUnit(udg_K_Missile[i])
 
        //kill dummies
        set bj_groupEnumTypeId = GetIdByKiFilter(GetPlayerId(p),GetUnitTypeId(u))
        call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup,p,Filter(function KiDummyExpireAll))
 
        //kill trees
        call Trig_Ki_Blast_KD_Setup(x,y,udg_K_ExplosionRadius,r)
 
        //kill units
        set bj_groupRandomCurrentPick = u
        set bj_wantDestroyGroup = true
        call GroupEnumUnitsInRange(bj_lastCreatedGroup,x,y,udg_K_ExplosionRadius,Filter(function KiTriFoldFilt))
        call SetUnitAnimation(u,"stand")
        set udg_K_Index[1] = udg_K_Index[1] - 1 // Decrease number of running instances
        if ( udg_K_Index[1] == 0 ) then // if no more instances...
            set udg_K_Index[2] = 0
            call DisableTrigger( gg_trg_Ki_Blast_Loop )
        endif
    endif
endfunction
 
function Trig_Ki_Blast_Loop takes rect r returns integer
    local integer i = 0
    local boolean b = bj_wantDestroyGroup
    loop
        if ( udg_K_Duration[i] > 0. ) then
            set udg_K_Duration[i] = udg_K_Duration[i] - 0.05 // decrease duration
            call DoKiBlast(i,r,udg_K_Caster[i])
        endif
        exitwhen i == udg_K_Index[2]
        set i = i + 1
    endloop
    call RemoveRect(r)
    set bj_wantDestroyGroup = b
    return i
endfunction
 
function Trig_Ki_Blast_Setup takes nothing returns boolean
    //If you see this message, delete this line:
    call BJDebugMsg("Debug MSG: Loop Trigger is evaluating")
    if ( udg_K_Timer[udg_K_Int] <= 0 ) then
        set udg_K_Timer[udg_K_Int] = udg_K_Timer[udg_K_Int] - 5
    else
        //If you see this message, delete this line:
        call BJDebugMsg("Debug MSG: Loop Trigger has entered phase 2")
    
    set udg_K_Int = Trig_Ki_Blast_Loop(Rect(0.,0.,0.,0.))
    endif
    return false
endfunction
 
//===========================================================================
function InitTrig_Ki_Blast_Loop takes nothing returns nothing
    local trigger t = CreateTrigger()
    
    //If you see this message, delete this line:
    call BJDebugMsg("Debug MSG: Loop Trigger has initialized properly")
    
    call DisableTrigger(t)
    call TriggerRegisterTimerEventPeriodic(t,0.05)
    call TriggerAddCondition(t,Condition(function Trig_Ki_Blast_Setup))
    set gg_trg_Ki_Blast_Loop = t
endfunction
 
The only other thing I can think of now is to change the caster trigger to this:

JASS:
function Trig_Ki_Blast_Cast_Actions takes unit u,integer id,player p,string attach returns nothing
    local real angle = GetUnitFacing(u) // this is the angle at which the missile will move: the angle between the caster and the target
    local real x = GetUnitX(u) + 50.*Cos(angle * bj_DEGTORAD)
    local real y = GetUnitY(u) + 50.*Sin(angle * bj_DEGTORAD)
    local boolean b = GetUnitTypeId(u) == 'H00I'
    local integer i
 
    if udg_K_Index[1] == 0 then
        if GetOwningPlayer(u) == Player(11) then
            set attach = "left hand"
        elseif b then
            call SetUnitAnimation( u, "Spell Slam" )
            set attach = "right hand"
        else
            call SetUnitAnimation(u,"Spell Throw")
            set attach = "right hand"
        endif
        call DestroyEffect(AddSpecialEffectTarget("Effects\\SuperShinyThingy.mdx",u,attach))
        call EnableTrigger(gg_trg_Ki_Blast_Loop)
        set udg_K_Index[1] = udg_K_Index[1] - 1
        set udg_K_Index[2] = udg_K_Index[2] - 1
    endif
 
    set udg_K_Index[1] = i + 1              // the K_Index[1] holds the number of instances currently active, so we increase it by one
    set i = udg_K_Index[2] + 1
    set udg_K_Index[2] = i                  // the K_Index[2] is used to store the data in variables, we also increase it by one
    set udg_K_Timer[udg_K_Int] = 60         // Timer For Wait
    set udg_K_Speed = 38.                   // this is the speed of the missile, it's common to all missiles so there is no need to index it
    set udg_K_CollisionRadius = 100.        // the distance at which the missile will collide with a unit
    set udg_K_ExplosionRadius = 250.        // units within this distance will be damaged on the explosion
    set udg_K_Damage = GetHeroInt(u,false) + GetUnitAbilityLevel(u,id)*2. // this is the damage dealt to units:
    set udg_K_Duration[i] = 1.              // this will be the duration of the missile, this one is indexed because it will be changed over time, and it's unique to each missile
    set udg_K_Caster[i] = u                 // this stores the caster
    set udg_K_Direction[i] = angle
 
    if p == Player(1) then
        set udg_K_Missile[i] = CreateUnit(p,'h00O',x,y,angle)
    elseif p == Player(7) then
        set udg_K_Missile[i] = CreateUnit(p,'h00M',x,y,angle)
    elseif p == Player(11) then
        set udg_K_Missile[i] = CreateUnit(p,'h00P',x,y,angle)
    elseif b then
        set udg_K_Missile[i] = CreateUnit(p,'h00R',x,y,angle)
    else
        set udg_K_Missile[i] = CreateUnit(p,'h00K',x,y,angle)
    endif
 
endfunction
 
function Trig_Ki_Blast_Cast_Conditions takes nothing returns boolean
    local integer id = GetSpellAbilityId()
    if id == 'A004' or id == 'A005' or id == 'A006' or id == 'A007' or id == 'A008' or id == 'A009' or b then
        call Trig_Ki_Blast_Cast_Actions(GetTriggerUnit(),id,GetTriggerPlayer(),"")
    endif
    return false
endfunction
 
//===========================================================================
function InitTrig_Ki_Blast_Cast takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t,Condition(function Trig_Ki_Blast_Cast_Conditions))
endfunction
 
Level 19
Joined
Jun 16, 2007
Messages
1,574
Nope not working at all now, and Newgen doesn't like:

JASS:
    if id == 'A004' or id == 'A005' or id == 'A006' or id == 'A007' or id == 'A008' or id == 'A009' or b then

so i keep changing it to;

JASS:
    if id == 'A004' or id == 'A005' or id == 'A006' or id == 'A007' or id == 'A008' or id == 'A009' then
 
You can put this in any trigger. It does not need to be split or anything like that.

JASS:
scope KiBlast
 
    private function DummyAllExpire takes nothing returns boolean
        if(GetUnitTypeId(GetEnumUnit()) == bj_groupEnumTypeId)then
            call KillUnit(GetEnumUnit())
        endif
        return false
    endfunction
 
    private function KiTriFoldFiltUtil takes unit f returns boolean
        if GetWidgetLife(f) > 0. and IsUnitEnemy(f,bj_groupEnumOwningPlayer) and not IsUnitType(f,UNIT_TYPE_STRUCTURE) then
            if bj_wantDestroyGroup then
                call UnitDamageTarget(bj_groupRandomCurrentPick,f,bj_meleeNearestMineDist,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_UNIVERSAL,WEAPON_TYPE_WHOKNOWS)
            else
                return true
            endif
        endif
        return false
    endfunction
    private function KiTriFoldFilt takes nothing returns boolean
        return KiTriFoldFiltUtil(GetFilterUnit())
    endfunction
 
    private function KillDestUtil takes destructable d returns boolean
        local real x = GetWidgetX(d) - bj_meleeNearestMineDist
        local real y = GetWidgetY(d) - bj_randomSubGroupChance
        if(SquareRoot(x*x + y*y) <= bj_enumDestructableRadius)then
            call KillDestructable(d)
        endif
        return false
    endfunction
    private function KillDest takes nothing returns boolean
        return KillDestUtil(GetFilterDestructable())
    endfunction
 
private struct S
 
    static rect RCT
    static timer TIM = CreateTimer()
    static integer TOT = -1
    static thistype array DEX
 
    unit caster
    unit missile
    player owner
    real incX
    real incY
    real vX
    real vY
    real damage
    real angle
    real duration = 1.
    integer dumId
    integer delay = 60
 
    method DestSetup takes real radius returns nothing
        set bj_meleeNearestMineDist = .vX
        set bj_randomSubGroupChance = .vY
        set bj_enumDestructableRadius = radius
        call SetRect(.RCT,.vX - radius,.vY - radius,.vX + radius,.vY + radius)
        call EnumDestructablesInRect(.RCT,Filter(function KillDest),null)
    endmethod
 
    static method onLoop takes nothing returns nothing
        local boolean b = bj_wantDestroyGroup
        local thistype this
        local integer i = 0
        loop
            set this = .DEX[i]
            if .delay <= 0 then
            // Create a dummy trail unit
                call CreateUnit(.owner,.dumId,.vX,.vY,.angle)
            //get polar projection (point from point offset by angle)
                set .vX = .vX + 38.*.incX
                set .vY = .vY + 38.*.incY
            //move missile
                call SetUnitX(.missile,.vX)
                call SetUnitY(.missile,.vY)
            //kill trees
                call .DestSetup(200.)
            // if there is a (matching) unit within CollisionRadius, it collides with the missile and immediately detonates it.
                set bj_groupEnumOwningPlayer = .owner
                set bj_wantDestroyGroup = false
                call GroupEnumUnitsInRange(bj_lastCreatedGroup,.vX,.vY,100.,Filter(function KiTriFoldFilt))
                if FirstOfGroup(bj_lastCreatedGroup) != null then
                    call GroupClear(bj_lastCreatedGroup)
                    set .duration = 0.
                else
                    set .duration = .duration - 0.05
                endif
            ////////////////////////////////////////////////////////////////////////
            // The next part of the loop occurs if the duration has reached zero: //
            ////////////////////////////////////////////////////////////////////////
                if ( .duration <= 0. ) then
                    call DestroyEffect(AddSpecialEffect("Effects\\NewDirtEXNofire.mdx",.vX,.vY))
                //kill dummies
                    set bj_groupEnumTypeId = .dumId
                    call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup,.owner,Filter(function DummyAllExpire))
                //kill trees
                    call .DestSetup(250.)
                //kill units
                    set bj_groupRandomCurrentPick = .caster
                    set bj_meleeNearestMineDist = .damage
                    set bj_wantDestroyGroup = true
                    call GroupEnumUnitsInRange(bj_lastCreatedGroup,.vX,.vY,250.,Filter(function KiTriFoldFilt))
                //reset the spell
                    call SetUnitAnimation(.caster,"stand")
                    if i < .TOT then
                        set .DEX[i] = .DEX[.TOT]
                        set i = i - 1
                    endif
                    call .destroy()
                    set .TOT = .TOT - 1
                endif
            else
                set .delay = .delay - 5
            endif
            exitwhen i >= .TOT
            set i = i + 1
        endloop
        if .TOT < 0 then
            call PauseTimer(.TIM)
        endif
        set bj_wantDestroyGroup = b
    endmethod
 
    method GetIdByKiFilter takes nothing returns integer
        local integer id = GetPlayerId(.owner)
        if id == 1 then
            return 'h00L'
        elseif id == 7 then
            return 'h00N'
        elseif id == 11 then
            return 'h00Q'
        elseif GetUnitTypeId(.caster) == 'H00I' then
            return 'h00S'
        endif
        return 'h00J'
    endmethod
 
    static method Actions takes integer id returns nothing
        local string attach
        local thistype this = thistype.create()
        set .TOT = .TOT + 1
        set .DEX[.TOT] = this
        set .owner = GetTriggerPlayer()
        set .caster = GetTriggerUnit()
        set .damage = GetHeroInt(.caster,false) + GetUnitAbilityLevel(.caster,id)*2.
        set .angle = GetUnitFacing(.caster)
        set .incX = Cos(.angle*bj_DEGTORAD)
        set .incY = Sin(.angle*bj_DEGTORAD)
        set .vX = GetUnitX(.caster) + 50.*.incX
        set .vY = GetUnitY(.caster) + 50.*.incY
        set .dumId = .GetIdByKiFilter()
        set .missile = CreateUnit(.owner,.dumId,.vX,.vY,.angle)
        if .owner == Player(11) then
            set attach = "left hand"
        else
            set attach = "right hand"
            if GetUnitTypeId(.caster) == 'H00I' then
                call SetUnitAnimation(.caster,"Spell Slam")
            else
                call SetUnitAnimation(.caster,"Spell Throw")
            endif
        endif
        call DestroyEffect(AddSpecialEffectTarget("Effects\\SuperShinyThingy.mdx",.caster,attach))
        if .TOT == 0 then
            call TimerStart(.TIM,0.05,true,function S.onLoop)
        endif
    endmethod
 
    static method Conditions takes nothing returns boolean
        local integer id = GetSpellAbilityId()
        if id == 'A004' or id == 'A005' or id == 'A006' or id == 'A007' or id == 'A008' or id == 'A009' or GetUnitTypeId(GetTriggerUnit()) == 'H00I' then
            call .Actions(id)
        endif
        return false
    endmethod
 
    static method onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t,Condition(function S.Conditions))
        set .RCT = Rect(0.,0.,0.,0.)
    endmethod
 
endstruct
 
endscope
 
Last edited:
My JassHelper parses that just fine. Do you have WC3 patched and JassHelper updated? I'll inline that function anyway, but I don't think that will change anything. It will take me a minute to inline it.

Edit: inlined:

JASS:
scope KiBlast
 
    private function DummyAllExpire takes nothing returns boolean
        if(GetUnitTypeId(GetEnumUnit()) == bj_groupEnumTypeId)then
            call KillUnit(GetEnumUnit())
        endif
        return false
    endfunction
 
    private function KiTriFoldFiltUtil takes unit f returns boolean
        if GetWidgetLife(f) > 0. and IsUnitEnemy(f,bj_groupEnumOwningPlayer) and not IsUnitType(f,UNIT_TYPE_STRUCTURE) then
            if bj_wantDestroyGroup then
                call UnitDamageTarget(bj_groupRandomCurrentPick,f,bj_meleeNearestMineDist,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_UNIVERSAL,WEAPON_TYPE_WHOKNOWS)
            else
                return true
            endif
        endif
        return false
    endfunction
    private function KiTriFoldFilt takes nothing returns boolean
        return KiTriFoldFiltUtil(GetFilterUnit())
    endfunction
 
    private function KillDestUtil takes destructable d returns boolean
        local real x = GetWidgetX(d) - bj_meleeNearestMineDist
        local real y = GetWidgetY(d) - bj_randomSubGroupChance
        if(SquareRoot(x*x + y*y) <= bj_enumDestructableRadius)then
            call KillDestructable(d)
        endif
        return false
    endfunction
    private function KillDest takes nothing returns boolean
        return KillDestUtil(GetFilterDestructable())
    endfunction
 
private struct S
 
    static rect RCT
    static timer TIM = CreateTimer()
    static integer TOT = -1
    static thistype array DEX
 
    unit caster
    unit missile
    player owner
    real incX
    real incY
    real vX
    real vY
    real damage
    real angle
    real duration = 1.
    integer dumId
    integer delay = 60
 
    method DestSetup takes real radius returns nothing
        set bj_meleeNearestMineDist = .vX
        set bj_randomSubGroupChance = .vY
        set bj_enumDestructableRadius = radius
        call SetRect(.RCT,.vX - radius,.vY - radius,.vX + radius,.vY + radius)
        call EnumDestructablesInRect(.RCT,Filter(function KillDest),null)
    endmethod
 
    static method onLoop takes nothing returns nothing
        local boolean b = bj_wantDestroyGroup
        local thistype this
        local integer i = 0
        loop
            set this = .DEX[i]
            if .delay <= 0 then
            // Create a dummy trail unit
                call CreateUnit(.owner,.dumId,.vX,.vY,.angle)
            //get polar projection (point from point offset by angle)
                set .vX = .vX + 38.*.incX
                set .vY = .vY + 38.*.incY
            //move missile
                call SetUnitX(.missile,.vX)
                call SetUnitY(.missile,.vY)
            //kill trees
                call .DestSetup(200.)
            // if there is a (matching) unit within CollisionRadius, it collides with the missile and immediately detonates it.
                set bj_groupEnumOwningPlayer = .owner
                set bj_wantDestroyGroup = false
                call GroupEnumUnitsInRange(bj_lastCreatedGroup,.vX,.vY,100.,Filter(function KiTriFoldFilt))
                if FirstOfGroup(bj_lastCreatedGroup) != null then
                    call GroupClear(bj_lastCreatedGroup)
                    set .duration = 0.
                else
                    set .duration = .duration - 0.05
                endif
            ////////////////////////////////////////////////////////////////////////
            // The next part of the loop occurs if the duration has reached zero: //
            ////////////////////////////////////////////////////////////////////////
                if ( .duration <= 0. ) then
                    call DestroyEffect(AddSpecialEffect("Effects\\NewDirtEXNofire.mdx",.vX,.vY))
                //kill dummies
                    set bj_groupEnumTypeId = .dumId
                    call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup,.owner,Filter(function DummyAllExpire))
                //kill trees
                    call .DestSetup(250.)
                //kill units
                    set bj_groupRandomCurrentPick = .caster
                    set bj_meleeNearestMineDist = .damage
                    set bj_wantDestroyGroup = true
                    call GroupEnumUnitsInRange(bj_lastCreatedGroup,.vX,.vY,250.,Filter(function KiTriFoldFilt))
                //reset the spell
                    call SetUnitAnimation(.caster,"stand")
                    if i < .TOT then
                        set .DEX[i] = .DEX[.TOT]
                        set i = i - 1
                    endif
                    call .destroy()
                    set .TOT = .TOT - 1
                endif
            else
                set .delay = .delay - 5
            endif
            exitwhen i >= .TOT
            set i = i + 1
        endloop
        if .TOT < 0 then
            call PauseTimer(.TIM)
        endif
        set bj_wantDestroyGroup = b
    endmethod
 
    static method Actions takes integer id returns nothing
        local string attach
        local thistype this = thistype.create()
        local integer pid
        set .TOT = .TOT + 1
        set .DEX[.TOT] = this
        set .owner = GetTriggerPlayer()
        set .caster = GetTriggerUnit()
        set .damage = GetHeroInt(.caster,false) + GetUnitAbilityLevel(.caster,id)*2.
        set .angle = GetUnitFacing(.caster)
        set .incX = Cos(.angle*bj_DEGTORAD)
        set .incY = Sin(.angle*bj_DEGTORAD)
        set .vX = GetUnitX(.caster) + 50.*.incX
        set .vY = GetUnitY(.caster) + 50.*.incY
        set pid = GetPlayerId(.owner)
        if pid == 1 then
            set .dumId = 'h00L'
        elseif pid == 7 then
            set .dumId = 'h00N'
        elseif pid == 11 then
            set .dumId = 'h00Q'
        elseif GetUnitTypeId(.caster) == 'H00I' then
            set .dumId = 'h00S'
        else
            set .dumId = 'h00J'
        endif
        set .missile = CreateUnit(.owner,.dumId,.vX,.vY,.angle)
        if pid == 11 then
            set attach = "left hand"
        else
            set attach = "right hand"
            if GetUnitTypeId(.caster) == 'H00I' then
                call SetUnitAnimation(.caster,"Spell Slam")
            else
                call SetUnitAnimation(.caster,"Spell Throw")
            endif
        endif
        call DestroyEffect(AddSpecialEffectTarget("Effects\\SuperShinyThingy.mdx",.caster,attach))
        if .TOT == 0 then
            call TimerStart(.TIM,0.05,true,function S.onLoop)
        endif
    endmethod
 
    static method Conditions takes nothing returns boolean
        local integer id = GetSpellAbilityId()
        if id == 'A004' or id == 'A005' or id == 'A006' or id == 'A007' or id == 'A008' or id == 'A009' or GetUnitTypeId(GetTriggerUnit()) == 'H00I' then
            call .Actions(id)
        endif
        return false
    endmethod
 
    static method onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t,Condition(function S.Conditions))
        set .RCT = Rect(0.,0.,0.,0.)
    endmethod
 
endstruct
 
endscope
 
Level 19
Joined
Jun 16, 2007
Messages
1,574
You come here to ask for help but you show no desire to learn how to solve your problems in the future. Please do yourself a favor and start learning what needs to be learned, because if you don't have time to figure your shit out, why should we?

I wish to learn how to solve my issues, in the format i'm currently working with.
But not by completely learning a new coding language, and making even more issues.
 
Level 19
Joined
Jun 16, 2007
Messages
1,574
Well by the looks of it, you've been stuck in gooey since at least June 2007, and JASS is not going to be a demon at that point because you're so well acquainted with the mechanics.

Only issues, i used to have are mainly about Game Caches, and i disbanned that project and moved to something else, after 2008, everything was working fine, just up to recently after i've switched from Non-MUI to MUI everything has gone pear shaped.
 
Level 8
Joined
Apr 30, 2009
Messages
338
I never used game caches, I am pretty sure that hashtables have replaced game caches in every way (it looks to me like game cache is just like hash table but with just 1 key instead of 2)

Seriously I was basically 100% lost even with GUI when doing triggered abilities until I learned hashtables. It makes the biggest difference in letting you do complex and leakless MUI spells and hashtables do the indexing for you
 
Level 19
Joined
Jun 16, 2007
Messages
1,574
I never used game caches, I am pretty sure that hashtables have replaced game caches in every way (it looks to me like game cache is just like hash table but with just 1 key instead of 2)

Seriously I was basically 100% lost even with GUI when doing triggered abilities until I learned hashtables. It makes the biggest difference in letting you do complex and leakless MUI spells and hashtables do the indexing for you

I've already messed around with Hashtables, and never goes right. So thats why i've stayed with GUI, and i'll probably learn HashTables when i have the time to do so. But to be frank the where things are going i wont have time to. Thats why i'm currently only trying to fix it only in GUI.
 
Status
Not open for further replies.
Top