How to make simple Spells/functions using locals

Level 3
Joined
Jun 19, 2010
Messages
9
How to make a simple Stat-based spell

The Planning

Okay, firstly, you may want to think how much planning you want to put in this spell. Too much damage and it will be too easy, too little damage and it will be too hard. Stat spells are extremely hard to get right so experiment!

WHAT YOU WILL NEED:
Warcraft III (Working copy)
A IQ of at least 80.
A mouse
A keyboard

The Locals

Okay, firstly, set up the locals. Locals are Variables that can only be used in that function (Unless you set them up as globals, which are normal vars).

Start by typing this:
JASS:
local unit a

This creates a local unit. These cannot be destroyed without destroying the unit, but CAN be nullified. Don't do this and say hello to memory leaks. Now, type this:

JASS:
local unit b

This creates...another local. Remember, THEY CAN ONLY BE USED INSIDE THE FUNCTION YOU CREATE THEM IN!!! Now, create 2 Reals, these work like Integers, by the way.

JASS:
local real s
local real p

Now you setup the locals, time to go into....

Setting The Locals

Setting Locals has to be the most complicated part, forgetting to use them right can have severe punishments. Okay, let's start by setting up our units:

JASS:
    set a = GetSpellAbilityUnit()
set b = GetSpellTargetUnit()

The first one get's the casting unit, the second one get's the target of the spell. Remember to nullify these always, In particular, spells and other commonly used triggers..

JASS:
set s = GetUnitAbilityLevelSwapped('A007', GetSpellAbilityUnit())
set p = GetHeroStatBJ(bj_HEROSTAT_STR, GetSpellAbilityUnit(), true)

This sets the reals. The first one sets the local to the units ability level of our spell, set the spell ID to whatever you want, the second one sets 'p' to the strength of the hero. This is as simple as it gets, so dont go complaining to me that you spend 200 hours on a jump spell and you get 567,356,238 errors.

Leak Fixing

JASS:
    call UnitDamageTargetBJ( a, b, ( s * ( p * 2.00 ) ),  ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )

This, my good sir, is the main part of the function. Causes the caster to damage the target for ABILITY LEVEL x STRENGTH x 2 damage. You can use the locals however you like, they are indeed flexible and the most useful thing you can get in JASS. They are a life-saver with spells. Now it's time to fix our spell so we dont get those dreaded leaks:

JASS:
set a = null
set b = null

This sets the units to null. Nothing. Reals do not leak, i think, correct me if i am wrong.

Some Samples

  • Crab
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Dying unit)) Equal to Omnipotent Crab
    • Actions
      • Custom script: local unit u
      • Custom script: local location r
      • Custom script: set u = GetDyingUnit()
      • Custom script: set r = GetUnitLoc(GetDyingUnit())
      • Wait 40.00 seconds
      • Custom script: call ReviveHeroLoc( u, r, true )
      • Custom script: call RemoveLocation ( r )
      • Custom script: set u = null
      • Custom script: set r = null
- A revival spell for heroes, i found it mandatory to put in JASS.

JASS:
function Trig_H1_Conditions takes nothing returns boolean
    if ( not ( IsUnitType(GetSoldUnit(), UNIT_TYPE_HERO) == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_H1_Actions takes nothing returns nothing
    local location a
    local player b
    local unit c
    set b = GetOwningPlayer(GetSellingUnit())
    set a = GetRandomLocInRect(gg_rct_Region_000)
    set c = GetSoldUnit()
    call RemoveUnit( udg_Player[GetConvertedPlayerId(b)] )
    set udg_Player[GetConvertedPlayerId(b)] = null
    call SetUnitPositionLoc( GetSoldUnit(), a )
    set udg_Player[GetConvertedPlayerId(b)] = c
    call RemoveLocation( a )
    set c = null
endfunction

function InitTrig_H1 takes nothing returns nothing
    set gg_trg_H1 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_H1, EVENT_PLAYER_UNIT_SELL )
    call TriggerAddCondition( gg_trg_H1, Condition( function Trig_H1_Conditions ) )
    call TriggerAddAction( gg_trg_H1, function Trig_H1_Actions )
endfunction

- A hero selection script, removes leaks.

More samples coming soon!

FAQ


Q: What are locals ACTUALLY for?
A: Well, you can create more than 1 local, which means that it is not shared like normal variables, this is good for common spells or else they will just mess up if 2 people use it at the same time.

Q: Do handles leak?
A: Yes.

Q: What do leaks do
A: 1. Lag out your map
2. Attract flying pigs that EAT YOUR SOUL
3. It is inedible, Mr. Anderson.
 
Last edited:
  • Like
Reactions: TKF
Level 17
Joined
Jun 17, 2007
Messages
1,433
You should really stop pseudo-jassing. Here is a better version of the script you posted:
JASS:
function Trig_H1_Conditions takes nothing returns boolean
    return IsUnitType(GetSoldUnit(), UNIT_TYPE_HERO) == true
endfunction

function Trig_H1_Actions takes nothing returns nothing
    local integer i = GetPlayerId(GetTriggerPlayer())
    local unit u = GetSoldUnit()
    call RemoveUnit(udg_Player[i])
    call SetUnitX(u, GetRandomReal(GetRectMinX(gg_rct_Region_000), GetRectMaxX(gg_rct_Region_000)))
    call SetUnitY(u, GetRandomReal(GetRectMinY(gg_rct_Region_000), GetRectMaxY(gg_rct_Region_000)))
    set udg_Player[i] = c
    set u = null
endfunction

function InitTrig_H1 takes nothing returns nothing
    set gg_trg_H1 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_H1, EVENT_PLAYER_UNIT_SELL )
    call TriggerAddCondition( gg_trg_H1, Condition( function Trig_H1_Conditions ) )
    call TriggerAddAction( gg_trg_H1, function Trig_H1_Actions )
endfunction
 
Level 21
Joined
Mar 19, 2009
Messages
444
You should really stop pseudo-jassing. Here is a better version of the script you posted:
JASS:
function Trig_H1_Conditions takes nothing returns boolean
    return IsUnitType(GetSoldUnit(), UNIT_TYPE_HERO) == true
endfunction

function Trig_H1_Actions takes nothing returns nothing
    local integer i = GetPlayerId(GetTriggerPlayer())
    local unit u = GetSoldUnit()
    call RemoveUnit(udg_Player[i])
    call SetUnitX(u, GetRandomReal(GetRectMinX(gg_rct_Region_000), GetRectMaxX(gg_rct_Region_000)))
    call SetUnitY(u, GetRandomReal(GetRectMinY(gg_rct_Region_000), GetRectMaxY(gg_rct_Region_000)))
    set udg_Player[i] = c
    set u = null
endfunction

function InitTrig_H1 takes nothing returns nothing
    set gg_trg_H1 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_H1, EVENT_PLAYER_UNIT_SELL )
    call TriggerAddCondition( gg_trg_H1, Condition( function Trig_H1_Conditions ) )
    call TriggerAddAction( gg_trg_H1, function Trig_H1_Actions )
endfunction

Actually you should integrate the action into the coundition.

Ah and for the author, if you want to lure people into learning VJass:

JASS:
scope HeroSell initializer OnInit

globals
    unit array PlayerHero [12]
    private real RectXMin
    private real RectYMin
    private real RectXMax
    private real RectYMax
endglobals

    private function OnSell takes nothing returns boolean
        local unit whichUnit = GetSoldUnit()
        local integer ownerId = GetPlayerId(GetOwningPlayer(whichUnit))
            if IsUnitType(whichUnit, UNIT_TYPE_HERO) then
                call RemoveUnit(PlayerHero[ownerId])
                call SetUnitPosition(whichUnit,GetRandomReal(RectXMin,RectXMax),GetRandomReal(RectYMin,RectYMax))
                set PlayerHero[ownerId] = whichUnit
            endif
            set whichUnit = null
            return false
    endfunction

    public function OnInit takes nothing returns nothing
        local trigger t = CreateTrigger()
            set RectXMin = GetRectMinX(gg_rct_Region_000)
            set RectYMin = GetRectMinY(gg_rct_Region_000)
            set RectXMax = GetRectMaxX(gg_rct_Region_000)
            set RectYMax = GetRectMaxY(gg_rct_Region_000)
            call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SELL )
            call TriggerAddCondition(t,Condition( function OnSell ) )
    endfunction

endscope
 
Level 3
Joined
Jun 19, 2010
Messages
9
You should really stop pseudo-jassing. Here is a better version of the script you posted:
JASS:
function Trig_H1_Conditions takes nothing returns boolean
    return IsUnitType(GetSoldUnit(), UNIT_TYPE_HERO) == true
endfunction

function Trig_H1_Actions takes nothing returns nothing
    local integer i = GetPlayerId(GetTriggerPlayer())
    local unit u = GetSoldUnit()
    call RemoveUnit(udg_Player[i])
    call SetUnitX(u, GetRandomReal(GetRectMinX(gg_rct_Region_000), GetRectMaxX(gg_rct_Region_000)))
    call SetUnitY(u, GetRandomReal(GetRectMinY(gg_rct_Region_000), GetRectMaxY(gg_rct_Region_000)))
    set udg_Player[i] = c
    set u = null
endfunction

function InitTrig_H1 takes nothing returns nothing
    set gg_trg_H1 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_H1, EVENT_PLAYER_UNIT_SELL )
    call TriggerAddCondition( gg_trg_H1, Condition( function Trig_H1_Conditions ) )
    call TriggerAddAction( gg_trg_H1, function Trig_H1_Actions )
endfunction

BJ's leak?! Crap, fixing.
 
Top