[Tutorial]Efficient Jass(Intermediate)

General talk about editing, cheating, and deprotecting maps.

Moderator: Cheaters

initialD
Some Honorary Title
Posts: 1713
Joined: June 8th, 2007, 5:08 am
Title: Angry Bird

[Tutorial]Efficient Jass(Intermediate)

Post by initialD »

Content

Chapter one- A direct argument is faster than a converted function

Chapter two- BJ or not, make your choice!!

Chapter three- You don't need a saving account to save some RAM!!

Chapter four- A leaky container won't hold water!!

Credit: JASS codes written by JJ2197, Aero, Weirdones2, Fai, Dekar, SgGuy and Xantan

[line][/line]
Chapter ONE - A direct argument is faster!!!

Example 1:

Code: Select all

call TriggerRegisterPlayerUnitEvent(trigger,player,ConvertPlayerUnitEvent(273),null)
call TriggerRegisterPlayerUnitEvent(trigger,player,ConvertPlayerUnitEvent(275),null)

The 3rd argument required will be a "playerunitevent".

ConvertPlayerUnitEvent(273)=EVENT_PLAYER_UNIT_SPELL_CAST
ConvertPlayerUnitEvent(275)=EVENT_PLAYER_UNIT_SPELL_FINISH

Somehow, converting an integer to a playerunitevent is slow. Get a direct argument instead.

Code: Select all

call TriggerRegisterPlayerUnitEvent(trigger,player,EVENT_PLAYER_UNIT_SPELL_CAST,null)
call TriggerRegisterPlayerUnitEvent(trigger,player,EVENT_PLAYER_UNIT_SPELL_FINISH,null)



Example 2:

Code: Select all

local integer i=3
call AnyFunction(i+2)

Obviously AnyFunction is a function that takes an integer argument.
In the above case. Anyfunction will take argument integer 5 (3+2).
Somehow, the following code is better. Get direct arguments as often as possible.

Code: Select all

call AnyFuntion(5)

[line][/line]
Chapter TWO - BJ or not, make your choice!!

Example 1:

Code: Select all

function TriggerRegisterDialogEventBJ takes trigger trig, dialog whichDialog returns event
    return TriggerRegisterDialogEvent(trig, whichDialog)
endfunction

Well, this is one of the lame and useless BJ function ever. And there are many useless BJ functions!

As you can see, TriggerRegisterDialogEventBJ(trig, dialog) does nothing but only calling a native function, which is TriggerRegisterDialogEvent(trig, whichDialog).

Instead of wasting a few more cycles, you may just directly call the native function.
Thus

calling TriggerRegisterDialogEvent(trig, whichDialog) is always faster than calling TriggerRegisterDialogEventBJ(trig, whichDialog)

And don't forget, both of them do the same thing! You don't need the BJ here.


Example 2:

Code: Select all

call SetHeroLevel(whichHero, newLevel, showEyeCandy)
call SetHeroLevelBJ(whichHero, newLevel, showEyeCandy)

This is somehow, not like the above example. Though both of them seems alike but the BJ's function here is useful.

Notice that SetHeroLevel will only able to set a higher hero's level. Thus you can't reduce hero's level by using this native function.

Here is what you should do to make it able to reduce hero's level.

Code: Select all

function Fai_Setherolevel takes unit whichHero, integer newLevel, boolean showEyeCandy returns nothing
local boolean faib
local integer oldLevel = GetHeroLevel(whichHero)
if (newLevel > oldLevel) then
call SetHeroLevel(whichHero, newLevel, showEyeCandy)
elseif (newLevel < oldLevel) then
set faib=UnitStripHeroLevel(whichHero, oldLevel - newLevel)
endif
endfunction

Compare the above Pure_JASS function with the following function which Blizzard provided.
Not much differences, right? In this case, Blizzard has provided a function considered good enough. Use the BJ function to save some spaces.

Code: Select all

function SetHeroLevelBJ takes unit whichHero, integer newLevel, boolean showEyeCandy returns nothing
local integer oldLevel = GetHeroLevel(whichHero)
if (newLevel > oldLevel) then
call SetHeroLevel(whichHero, newLevel, showEyeCandy)
elseif (newLevel < oldLevel) then
call UnitStripHeroLevel(whichHero, oldLevel - newLevel)
else
endif
endfunction

[line][/line]
Chapter THREE - You don't need a saving account to save some RAM!!

Example 1:

Code: Select all

local integer c7=S2I(SubString(string,9,11))
local integer temp7=0
if SubString(string,0,8)=="-additem"then
set temp7=0
loop
set temp7=temp7+1
exitwhen temp7>c7
call CreateItemLoc(ChooseRandomItemExBJ(-1,ITEM_TYPE_ANY),GetUnitLoc(unit))
endloop
endif

This is what we often see while running a "loop" action. c7 is an integer in a chat string, this integer will decide how many time the function in between "loop" and "endloop" runs.

Integer temp7 is used to calculate how many times the function has already runned.

Somehow, since c7 has already an integer indicate how many times the "loop" should run. We may not need temp7! Here is what you can do to save some RAM.

Code: Select all

local integer c7=S2I(SubString(string,9,11))
if SubString(string,0,8)=="-additem"then
loop
set c7=c7-1
exitwhen c7<0
call CreateItemLoc(ChooseRandomItemExBJ(-1,ITEM_TYPE_ANY),GetUnitLoc(unit))
endloop
endif

In this case, use a same variable for different purposes! Use as less variable as possible!

Example 2:

Code: Select all

if fai=="ow."then
if z7<0 or z7>15then
call DoNothing()
else
call SetUnitOwner(u7,Player(z7),ggF)
endif
endif

Integer z7 can't be bigger than 15 or smaller than 0 or player(z7) will make the game crashes.
That's why a detector is there doing its job.

Somehow, calling DoNothing() is not really necessary. It can be simply done as following:

Code: Select all

if fai=="ow."then
if z7>-1 and z7<16then
call SetUnitOwner(u7,Player(z7),ggF)
endif
endif

Save as many lines as possible!!

[line][/line]
Chapter FOUR - A leaky container won't hold water!!

Example 1:

Code: Select all

function FastUnit2 takes nothing returns nothing
local player p2p=GetTriggerPlayer()
local integer I2I=GetTrainedUnitType()
local location j2j=GetUnitLoc(GetTriggerUnit())
call CreateUnitAtLoc(p2p,I2I,j2j,270)
set p2p=null
set j2j=null
endfunction

locations leak. Minor memory leakings are acceptable. Somehow it's fine to avoid as much memory leakings as possible

It's easy. Just save the location on a local variable and then remove it. As following:

Code: Select all

function FastUnit2 takes nothing returns nothing
local player p2p=GetTriggerPlayer()
local integer I2I=GetTrainedUnitType()
local location j2j=GetUnitLoc(GetTriggerUnit())
call CreateUnitAtLoc(p2p,I2I,j2j,270)
call RemoveLocation(j2j)
set p2p=null
set j2j=null
endfunction


Example 2:

Code: Select all

function Trig_w00t_Func001001 takes nothing returns boolean
return(IsPlayerInForce(udg_SCVirus,GetForceOfPlayer(GetTriggerPlayer())))
endfunction

Here again, GetForceOfPlayer returns force. Forces leak.

Just use an already existed force to avoid memory leaks, as following:

Code: Select all

function Trig_w00t_Func001001 takes nothing returns boolean
return(IsPlayerInForce(udg_SCVirus,bj_FORCE_PLAYER[GetPlayerId(GetTriggerPlayer)]))
endfunction