• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] What's wrong with BJ ?

Status
Not open for further replies.
Level 5
Joined
Aug 30, 2009
Messages
114
I've been looking for some spells and I realized the most qualified makers never use BJ like

JASS:
SetUnitPositionLocFacingBJ
, they usually do this:

JASS:
SetUnitPosition
SetUnitPositionLoc

So, it drives me to one question, whats wrong with BJ ? Is there any problem using it? Once it's much easier than normal codes?

I'm having some lag stuffs into spells that use 0.05 seconds interval...

I did everything right, I cleaned all leaks, I change the time to 0.05 instead of 0.02, but yet, it does lag when it draggs much units, I wanna know if BJ codes are somehow related to it...

Can someone give me some hints about?

Here is only ONE of the spells wich lags

JASS:
function Trig_Dragula_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A0FM' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Dragula_Func003002003001 takes nothing returns boolean
    return ( IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) != true )
endfunction

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

function Trig_Dragula_Func003002003002001002 takes nothing returns boolean
    return ( IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) != true )
endfunction

function Trig_Dragula_Func003002003002001 takes nothing returns boolean
    return GetBooleanAnd( Trig_Dragula_Func003002003002001001(), Trig_Dragula_Func003002003002001002() )
endfunction

function Trig_Dragula_Func003002003002002 takes nothing returns boolean
    return ( IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(udg_Spell_Dragula_Dummy)) == true )
endfunction

function Trig_Dragula_Func003002003002 takes nothing returns boolean
    return GetBooleanAnd( Trig_Dragula_Func003002003002001(), Trig_Dragula_Func003002003002002() )
endfunction

function Trig_Dragula_Func003002003 takes nothing returns boolean
    return GetBooleanAnd( Trig_Dragula_Func003002003001(), Trig_Dragula_Func003002003002() )
endfunction

function Trig_Dragula_Func009A takes nothing returns nothing
    call KillDestructable( GetEnumDestructable() )
endfunction

function Trig_Dragula_Timer_Func001A takes nothing returns nothing
    local unit E = GetEnumUnit()
    local location L = GetUnitLoc(E)
    local location L3 = GetUnitLoc(udg_Spell_Dragula_Dummy)
    local location L2 = PolarProjectionBJ(L, 5.00, AngleBetweenPoints(L, L3))
    call SetUnitPositionLoc( E, L2 )
    call RemoveLocation(L)
    call RemoveLocation(L2)
    call RemoveLocation(L3)
    set E = null
endfunction

function DragulaPush takes nothing returns nothing
    local location L = GetUnitLoc(udg_Spell_Dragula_Dummy)
    local group G = GetUnitsInRangeOfLocMatching(875.00, L, Condition(function Trig_Dragula_Func003002003))
    call ForGroupBJ( G, function Trig_Dragula_Timer_Func001A )
    set G = null
    call DestroyGroup(G)
    call RemoveLocation(L)
endfunction

function Trig_Dragula_Actions takes nothing returns nothing
    local trigger T = CreateTrigger()
    local location L = GetSpellTargetLoc()
    call CreateNUnitsAtLoc( 1, 'u00R', GetOwningPlayer(GetTriggerUnit()), L, bj_UNIT_FACING )
    set udg_Spell_Dragula_Dummy = GetLastCreatedUnit()
    call PlaySoundOnUnitBJ( gg_snd_PossessionMissileLaunch1, 100, GetLastCreatedUnit() )
    call UnitAddAbilityBJ( 'A0FN', GetLastCreatedUnit() )
    call SetUnitAbilityLevelSwapped( 'A0FN', GetLastCreatedUnit(), GetUnitAbilityLevelSwapped('A0FM', GetTriggerUnit()) )
    call UnitApplyTimedLifeBJ( 7.00, 'BTLF', GetLastCreatedUnit() )
    call EnumDestructablesInCircleBJ( 875.00, L, function Trig_Dragula_Func009A )
    call TriggerRegisterTimerEventPeriodic( T, 0.05 )
    call TriggerAddAction( T, function DragulaPush )
    call UnitDamageTargetBJ( GetTriggerUnit(), GetTriggerUnit(), ( 100.00 + ( 100.00 * I2R(GetUnitAbilityLevelSwapped('A0FM', GetTriggerUnit())) ) ), ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC )
    call TriggerSleepAction( 6.00 )
    call DestroyTrigger(T)
    call PlaySoundOnUnitBJ( gg_snd_SoulPreservation, 100, GetLastCreatedUnit() )
    call KillSoundWhenDoneBJ( GetLastPlayedSound() )
    call RemoveLocation(L)
endfunction

//===========================================================================
function InitTrig_Dragula takes nothing returns nothing
    set gg_trg_Dragula = CreateTrigger(  )
    call DisableTrigger( gg_trg_Dragula )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Dragula, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Dragula, Condition( function Trig_Dragula_Conditions ) )
    call TriggerAddAction( gg_trg_Dragula, function Trig_Dragula_Actions )
endfunction

OBS: The Dummy unit used in this spell is just an effect and has nothing to do with it. Before you say something, I have another trigger that runs a few seconds after the map initializing wich I made the preload of the Dummy spell, the Hero Spell and the Dummy ability (just another visual effect).
I don't know if it's nescessary to make a preload of the sounds.

Thank you, for your time.
 
Level 2
Joined
Feb 8, 2011
Messages
31
BJ functions are non-native functions that are usually used to perform other actions inside of them (the only exception I can think of is DoNothing, which does nothing). Native functions are also faster than BJ functions. Keep in mind that any function you make is technically a BJ function when based on my above statement, but BJ actually stands for Blizzard Jass. All BJ functions are also stored in a jass file called blizzard.j.

I guess the best answer to your question is that most BJ functions use extra function calls to make coding simpler for users. Since function calls in JASS are rather slow, it's better to use native functions. Using many BJ functions per second can cause a significant drop for your FPS depending on which ones you're using.

Edit:

On a side note, I've read somewhere that SetUnitPosition (or SetUnitPositionLoc) causes a drop in FPS because of spammed stop orders (it might also be because pathing is considered). I've never tested that, but you should be using SetUnitX/SetUnitY anyway. Moving many units at one time will generally cause an FPS drop anyway, so try to keep the amount of moving units small when using SetUnitX/SetUnitY or SetUnitPosition.
 
Level 8
Joined
Jun 28, 2008
Messages
356
BJ is actually Blizzard Junction, not Blizzard JASS. And there is no problem with using BJ functions in triggers that you call once or twice throughout the whole game. The problems come when you use them in big loops or timers with 0.03 timeout or something. It could drag down your performance a lot then. But if you are not gonna post your code on hive, don't worry about BJs, cause the onliest real reason to remove them is to not get scolded by the elite users eheheh
 

Cokemonkey11

Spell Reviewer
Level 29
Joined
May 9, 2006
Messages
3,534
Only a few BJs are considered okay to use in today's jass standards.

JASS:
TriggerRegisterAnyUnitEventBJ()
is a common one.

Edit: To answer the original question (although it's been answered already), BJ functions are frowned upon because the vast majority of them don't do anything more than call 1 native.

So you can either use a BJ which calls a native which does some cpp in the backend

Or you can use a native which does some cpp in the backend.

Each function call takes processing power - that's why we try to stick to natives.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
your spell spammed the GetLastCreatedUnit() a lot...In JASS, even in GUI, if you use your reference a lot, you should store it to a variable for better performance...

In JASS however we use locals, like this...

JASS:
 local unit u = GetTriggerUnit()
 local unit dummy
 local real x = GetSpellTargetX()
 local real y = GetSpellTargetY()
 set dummy = CreateUnit(GetOwningPlayer(u), 'u00R', x, y, 0)

Making the variable editor 95% useless and completely useless in vJASS...
 
Status
Not open for further replies.
Top