• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Small Code Snippets

Level 18
Joined
Oct 18, 2007
Messages
930
I really like these to :)

JASS:
function CheckDegrees takes real Deg returns real
    if Deg > 360 then
        return Deg - 360
    elseif Deg < 0 then
        return Deg + 360
    endif
endfunction

and this

JASS:
function CheckRadians takes Rad returns real
    local real PI2 = bj_PI*2
    if Rad > PI2 then
        return Rad - PI2
    elseif Rad < PI2 then
        return Rad + PI2
    endif
endfunction

This is only useful if you want to keep the angle from 0 to 360.

Edit: Fixed error :D
 
Last edited:
Level 18
Joined
Oct 18, 2007
Messages
930
Btw, a trigger recycler :D ( Would this work? :p )
JASS:
library TriggerRecycler
    globals
        private constant integer MAX = 409550

        private trigger array X[MAX]
        private integer i = 0
    endglobals

    function NewTrigger takes nothing returns trigger
        if i == 0 then
            set X[0] = CreateTrigger()
        else
            set i = i - 1
        endif

        call EnableTrigger(X[i])
        return X[i]
    endfunction

    function ReleaseTrigger takes trigger t returns nothing
        if t == null then
             call BJDebugMsg("ReleaseTrigger: Can't release a null Trigger!")
             return
        endif

        if i == MAX then
            call BJDebugMsg("ReleaseTrigger: Limit reached, Destroying Trigger!")
            call DestroyTrigger(t)
        else
            call TriggerClearActions(t)
            call TriggerClearConditions(t)
            call ResetTrigger(t)
            call DisableTrigger(t)

            set X[i] = t
            set i = i + 1
        endif
    endfunction
endlibrary

Edit:
Made a simple TriggerUtils ( Based entirely on Vexorian's TimerUtils )
JASS:
library_once TriggerUtils

    globals
        private constant integer MAX_HANDLE_ID_COUNT = 408000
        // values lower than 8191: very fast, but very unsafe.
        // values bigger than 8191: not that fast, the bigger the number is the slower the function gets
    endglobals
    
    private function H2I takes handle h returns integer
        return h
        return 0
    endfunction

    globals
        private integer array data[MAX_HANDLE_ID_COUNT]
        private constant integer MIN_HANDLE_ID=0x100000
    endglobals

    function SetTriggerData takes trigger t, integer value returns nothing
        debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
        debug     call BJDebugMsg("SetTriggerData: Handle id too big, increase the max handle id count or use gamecache instead!")
        debug endif
        set data[H2I(t)-MIN_HANDLE_ID]=value
    endfunction

    function GetTriggerData takes trigger t returns integer
        debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
        debug     call BJDebugMsg("GetTimerData: Handle id too big, increase the max handle id count or use gamecache instead")
        debug endif
        return data[H2I(t)-MIN_HANDLE_ID]
    endfunction
    
    globals
        private trigger array tT
        private integer tN = 0
        private constant integer HELD=0x98829022
    endglobals
    
    function NewTrigger takes nothing returns trigger
        if (tN==0) then
            set tT[0]=CreateTrigger()
        else
            set tN=tN-1
        endif
        call SetTriggerData(tT[tN],0)
        
        call EnableTrigger(tT[tN])
        return tT[tN]
    endfunction

    function ReleaseTrigger takes trigger t returns nothing
        if(t==null) then
            debug call BJDebugMsg("ReleaseTrigger: attempt to release a null trigger")
            return
        endif
        if (tN==8191) then
            debug call BJDebugMsg("ReleaseTrigger: Trigger stack is full, destroying timer!!")

            //stack is full, the map already has much more troubles than the chance of bug
            call DestroyTrigger(t)
        else
            call TriggerClearActions(t)
            call TriggerClearConditions(t)
            call ResetTrigger(t)
            call DisableTrigger(t)
            
            if(GetTriggerData(t)==HELD) then
                debug call BJDebugMsg("ReleaseTrigger: Double free!")
                return
            endif
            call SetTriggerData(t,HELD)
            set tT[tN]=t
            set tN=tN+1
        endif    
    endfunction

endlibrary

Could be useful :D
 
Last edited:
Level 6
Joined
Apr 16, 2007
Messages
177
But if you use this from the start it wont reach 730. :p

You mean, If I use it on every real I ever have?

set angle = CheckAngle( CheckAngle(a1) + CheckAngle(a2) )

?

Should be slower than a simple modulo approach.
JASS:
library TriggerRecycler
    globals
        private constant integer MAX = 409550

        private trigger array X[MAX]
        private integer i = 0
    endglobals

    function NewTrigger takes nothing returns trigger
        if i == 0 then
            set X[0] = CreateTrigger()
        else
            set i = i - 1
        endif

        call EnableTrigger(X[i])
        return X[i]
    endfunction

    function ReleaseTrigger takes trigger t returns nothing
        if t == null then
             call BJDebugMsg("ReleaseTrigger: Can't release a null Trigger!")
             return
        endif

        if i == MAX then
            call BJDebugMsg("ReleaseTrigger: Limit reached, Destroying Trigger!")
            call DestroyTrigger(t)
        else
            call TriggerClearActions(t)
            call TriggerClearConditions(t)
            call ResetTrigger(t)
            call DisableTrigger(t)

            set X[i] = t
            set i = i + 1
        endif
    endfunction
endlibrary

Would not work, you are accessing the same 0 index all the time and are even trying to access negative indicies.
JASS:
    function NewTrigger takes nothing returns trigger
        if i == 0 then
            set X[0] = CreateTrigger()
            // i is 0 and won't be changed oO
        else
            set i = i - 1
        endif

        call EnableTrigger(X[i])
        return X[i]
    endfunction
 
Level 6
Joined
Apr 16, 2007
Messages
177
the 0 index is for 0 aviable triggers, so it makes one. If there is an aviable trigger that have been stored through the release trigger it would work :)

kk I just think the 'store at creation' way, not the 'store at destruction'. The way you posted it would work, though. *I'm getting too tired to read your code, lately >< Just ignore this ;)*
 
Last edited:
Level 16
Joined
Feb 22, 2006
Messages
960
maybe this two functions could be usefull, the first one checks if there is an item in a specific slot and the seconds checks if the inventory is full (second requires first one)

JASS:
function IsItemInSlot takes unit u, integer slot returns boolean
     return GetItemTypeId(UnitItemInSlot(u,slot)) > 0
endfunction

function IsInventoryFull takes unit u returns boolean
    local integer i = 0
    local boolean b = true
    loop
        exitwhen i >= 6
        if IsItemInSlot(u,i) != true then
            set b = false
        endif
        set i = i + 1
    endloop
    return b
endfunction
 
Last edited:
Level 23
Joined
Nov 29, 2006
Messages
2,482
You could optimize the first of those two alot. Instead of what you did a better one would be:
JASS:
function IsItemInSlot takes unit u, integer slot returns boolean
    return GetItemTypeId(UnitItemInSlot(u,slot)) > 0
endfunction
 
Level 6
Joined
Apr 16, 2007
Messages
177
JASS:
function IsItemInSlot takes unit u, integer slot returns boolean
    return GetItemTypeId(UnitItemInSlot(u,slot)) > 0
endfunction

function IsItemInSlot takes unit u, integer slot returns boolean
    return UnitItemInSlot(u,slot) != null
endfunction
shouldn't that work, too?

also the second one does not need to loop through the whole inventory, it can return false with the first free slot found:

JASS:
function IsInventoryFull takes unit u returns boolean
    local integer i = 0
    loop
        exitwhen i >= 6
        if not IsItemInSlot(u,i) then
            return false
        endif
        set i = i + 1
    endloop
endfunction

best wishes and thanks for the functions (I'll use them for my tradesys :)), Davey Jones
 
Level 16
Joined
Feb 22, 2006
Messages
960
JASS:
function IsItemInSlot takes unit u, integer slot returns boolean
    return GetItemTypeId(UnitItemInSlot(u,slot)) > 0
endfunction

function IsItemInSlot takes unit u, integer slot returns boolean
    return UnitItemInSlot(u,slot) != null
endfunction
shouldn't that work, too?

also the second one does not need to loop through the whole inventory, it can return false with the first free slot found:

JASS:
function IsInventoryFull takes unit u returns boolean
    local integer i = 0
    loop
        exitwhen i >= 6
        if not IsItemInSlot(u,i) then
            return false
        endif
        set i = i + 1
    endloop
endfunction

best wishes and thanks for the functions (I'll use them for my tradesys :)), Davey Jones

that makes no big diffrence if i loop the whole inv or till the first one which is empty
 
Level 6
Joined
Apr 16, 2007
Messages
177
that makes no big diffrence if i loop the whole inv or till the first one which is empty

true, just 100% better at average. But as we're allready whining for proxies that just do 50% worse, why not for this one? Same for the other one.

Also my version is shorter by two lines and saves a local variable ;D

anyhow, I don't see no point in doing potentially 6 calls where only 1 is necessary ;)

best wishes, Davey
 
Level 17
Joined
Jun 17, 2007
Messages
1,433
To keep out a potential deluge of threads with very small functions, I've created this thread for you to post relatively short functions you wish to share.

Normal or long length snippets (nearing coding systems or libraries and so on) still go the same place as always.

So, if you have your own special GetClosestUnit, Log, or whatever function, post it here!


D'you guys think I should merge the GetPlayerColorTag functions into here? They sort of fit into either place, due to the fact that there have been several of them presented.


Functions
JASS:
//Uses global unit udg_ClosestUnit
function GetClosestUnit takes real x, real y, boolexpr e returns unit
    local real md = 100000
    local group g = CreateGroup()
    local unit u
    local real dx
    local real dy
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, e)
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        call GroupRemoveUnit(g, u)
        set dx = GetUnitX(u) - x
        set dy = GetUnitY(u) - y
        if (dx * dx + dy * dy) / 100000 < md then
            set udg_ClosestUnit = u
            set md = (dx * dx + dy * dy) / 100000
        endif
    endloop
    call DestroyGroup(g)
    call DestroyBoolExpr(e)
    set g = null
    return udg_ClosestUnit
endfunction
JASS:
//***************************
//----GetUnitSomewhere by Quraji----
//***************************
//
// To use in your map simply paste this whole code into your custom script
// section, or an empty trigger (above all functions that will use this code)
//
// (feel free to omit this section from your code, I only ask credit if
// you copy this function for your own system/submitted code, no credits
// needed if you use it in a map)
//
// Contains one main function:
//
//
// GetUnitSomewhere takes real sourceX, real sourceY, real range, boolean outsiderange, boolean nearest, boolean considerdead, boolexpr cond returns unit
// Don't let the number of parameters scare you, this is easy to use. This
// function allows you to select the nearest or farthest unit inside or outside
// a designated circle.
//
// Parameters:
//
// real sourceX and real sourceY
// these are the X and Y coordinates of the point at the center of the area
// to be considered.
//
// real range
// this is the range of the function, or the radius of the area to be considered
// (a circle).
//
// boolean outsiderange
// if false, the function will consider units inside the circle, if true it will
// consider all units selected BUT the ones in the circle.
// (remember that the circle's radius is decided by the range parameter)
//
// boolean nearest
// if true, the function will select the nearest unit to the center point inside
// the area to be considered (as you'd expect a normal GetClosestUnit()
// function to do. if false, however, it will select the farthest unit
//
// boolean considerdead
// if false the function will ignore dead units.
// (leave this at false unless you need the function to select recently killed
// units)
//
// boolexpr cond
// finally, this is where you add your own conditions if you need them by
// using a boolexpr. if you don't, pass "Condition(function ReturnTrue)"
//
// function GetUnitSomewhereEx takes real x, real y, real range returns unit
// A simplified version, returns a non-dead unit within range
//
// function GetUnitSomewhereExCond takes real x, real y, real range, boolexpr cond returns unit
// A simplified version, returns a non-dead unit within range, matching condition
//
// Extra feature:
//
// This function sets the bj_lastHauntedGoldMine game variable to the unit
// it selects, as well as returning the unit. This enables JASS users to use
// the function as normal, but provides a convenience for GUI users, as they
// can simply select the unit from the drop down menu for any unit field by
// selecting "Last Haunted Gold Mine". This also allows all variables to be
// nulled. If you wish this variable not to be tampered with, uncomment the
// "return winner" line of code at the bottom of the function.
//**********************

function ReturnTrue takes nothing returns boolean
  return true
endfunction

function GetUnitSomewhere takes real sourceX, real sourceY, real range, boolean outsiderange, boolean nearest, boolean considerdead, boolexpr cond returns unit
 local group g=CreateGroup()
 local unit current
 local unit winner
 local real currentX
 local real currentY
 local real dist
 local real rangeorig = range

   if outsiderange then
     call GroupEnumUnitsInRect(g,bj_mapInitialPlayableArea,cond)
   else
     call GroupEnumUnitsInRange(g,sourceX,sourceY,range,cond)
   endif

   if not nearest then
     set range=.0
   endif

   loop

    set current=FirstOfGroup(g)
     exitwhen current==null

       if GetWidgetLife(current)>0.405 or considerdead then

         set currentX=GetWidgetX(current)-sourceX
         set currentY=GetWidgetY(current)-sourceY
         set dist=SquareRoot(currentX*currentX+currentY*currentY)

         if outsiderange then
           set range=dist
           set outsiderange = not outsiderange
         endif

         if (outsiderange and (dist > rangeorig)) or outsiderange == false then

           if (nearest and dist<=range) or (not nearest and dist>=range) then

             set winner=current
             set range=dist

           endif

         endif

       endif

     call GroupRemoveUnit(g,current)
   endloop

     call DestroyGroup(g)

     set g=null
set current=null

     //return winner
     //uncomment above line if you wish bj_lastHauntedGoldMine to remain
//untampered with

     set bj_lastHauntedGoldMine=winner
     set winner=null

   return bj_lastHauntedGoldMine
endfunction

function GetUnitSomewhereEx takes real x, real y, real range returns unit
  return GetUnitSomewhere(x,y,range,false,true,false, Condition(function ReturnTrue))
endfunction

function GetUnitSomewhereExCond takes real x, real y, real range, boolexpr cond returns unit
  return GetUnitSomewhere(x,y,range,false,true,false,cond)
endfunction
JASS:
//Uses global group udg_enumGrp
//Uses global unit udg_ClosestUnit
function GetClosestUnit takes real x, real y, boolexpr e returns unit
    local real md = 100000
    local unit u
    local real dx
    local real dy
    call GroupEnumUnitsInRect(udg_enumGrp, bj_mapInitialPlayableArea, e)
    loop
        set u = FirstOfGroup(udg_enumGrp)
        exitwhen u == null
        call GroupRemoveUnit(udg_enumGrp, u)
        set dx = GetUnitX(u) - x
        set dy = GetUnitY(u) - y
        if (dx * dx + dy * dy) / 100000 < md then
            set udg_ClosestUnit = u
            set md = (dx * dx + dy * dy) / 100000
        endif
    endloop
    return udg_ClosestUnit
endfunction
JASS:
globals
    integer array StunArray
    integer StunTotal=0
endglobals

struct stundata
    unit u=null
    real d=0
    boolean destroyplease=false
endstruct

function StunUnit_KeepStunned takes nothing returns nothing
    local integer i = 0
    local stundata dat
    loop
        exitwhen i==Stun_Total
        set dat=StunArray[i]
        if dat.destroyplease then
            set Stun_Total=Stun_Total-1
            set StunArray[i]=StunArray[Stun_Total]
            call dat.destroy()
            set i=i-1
        else
            set dat.d=dat.d-0.01
            call SetUnitPosition(dat.u,GetUnitX(dat.u),GetUnitY(dat.u))
            set dat.destroyplease=(dat.d<=0)
        endif
        set i=i+1
    endloop
    if Stun_Total==0 then
        call ReleaseTimer(GetExpiredTimer())
    endif
endfunction

function StunUnit takes unit u,real d returns nothing
    local stundata dat=stundata.create()
    set dat.d=d
    set dat.u=u
    if (Stun_Total==0) then
        call TimerStart(NewTimer(),.01,true,function StunUnit_KeepStunned)
    endif
    set Stun_Total=Stun_Total+1
    set StunArray[Stun_Total-1]=dat
endfunction
JASS:
function PreloadSoundPath takes string path returns nothing
    local sound snd = CreateSound(path, false, false, false, 10, 10, "")
    call SetSoundVolume(snd, 0)
    call StartSound(snd)
    call KillSoundWhenDone(snd)
    set snd = null
endfunction
JASS:
library QuickTimer
    //============================================================================
    // Attaches and integer to a timer and makes it expire after about 0 seconds.
    //
    function TimerExpireQuick takes timer t, integer data, code handlerFunc returns nothing
        call TimerStart(t, data/2147483648., false, handlerFunc)
    endfunction

    //============================================================================
    // Returns the integer attached to a timer.
    //
    function QuickTimerGetData takes timer t returns integer
        return R2I(TimerGetTimeout(t)*2147483648.)
    endfunction
endlibrary
I think it'd also be a good idea to mention any systems those functions require.
 
Level 11
Joined
May 26, 2005
Messages
194
GetCamOffset

GetCamOffset(x,y) is the only function to access from outside the library.
It returns the camera z offset on a given terrain position, useful for placing the camera correctly for 3rd person cams and so on...
however, does not work for destructables with an overfly-z-size, nor for water

for everything else, it works so precise that you wont see any inaccuracy with your eyes, i made a 3d flight simulator using it, and the cam sticks to the plane very well

Code:
library cameramap initializer cameramapInit
    globals
        location cameramapLoc
        real array camOffset[256][256]
        real mapMinX
        real mapMinY
        real mapMaxX
        real mapMaxY
    endglobals

    function GetGridCamOffset takes integer ix, integer iy, integer offx, integer offy returns real
        local real r
        local integer ixl = ix-1
        local integer ixr = ix+1
        local integer iyd = iy-1
        local integer iyu = iy+1
        if ixl<0 then
            set ixl = 0
        endif
        if iyd<0 then
            set iyd = 0
        endif
        if ixr>256 then
            set ixr=256
        endif
        if iyu>256 then
            set iyu=256
        endif
        if offx>0 then
            if offy>0 then
                set r =   .089696*camOffset[ixl][iyu]+ .139657*camOffset[ix][iyu]+ .097349*camOffset[ixr][iyu]
                set r = r+.130989*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .139657*camOffset[ixr][iy]
                set r = r+.082587*camOffset[ixl][iyd]+ .130989*camOffset[ix][iyd]+ .089696*camOffset[ixr][iyd]
            elseif offy<0 then
                set r =   .082587*camOffset[ixl][iyu]+ .130989*camOffset[ix][iyu]+ .089696*camOffset[ixr][iyu]
                set r = r+.130989*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .139657*camOffset[ixr][iy]
                set r = r+.089696*camOffset[ixl][iyd]+ .139657*camOffset[ix][iyd]+ .097349*camOffset[ixr][iyd]
            else
                set r =   .084604*camOffset[ixl][iyu]+ .134226*camOffset[ix][iyu]+ .091913*camOffset[ixr][iyu]
                set r = r+.134017*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .142877*camOffset[ixr][iy]
                set r = r+.084604*camOffset[ixl][iyd]+ .134226*camOffset[ix][iyd]+ .091913*camOffset[ixr][iyd]
            endif
        elseif offx<0 then
            if offy>0 then
                set r =   .097349*camOffset[ixl][iyu]+ .139657*camOffset[ix][iyu]+ .089696*camOffset[ixr][iyu]
                set r = r+.139657*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .130989*camOffset[ixr][iy]
                set r = r+.089696*camOffset[ixl][iyd]+ .130989*camOffset[ix][iyd]+ .082587*camOffset[ixr][iyd]
            elseif offy<0 then
                set r =   .089696*camOffset[ixl][iyu]+ .130989*camOffset[ix][iyu]+ .082587*camOffset[ixr][iyu]
                set r = r+.139657*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .130989*camOffset[ixr][iy]
                set r = r+.097349*camOffset[ixl][iyd]+ .139657*camOffset[ix][iyd]+ .089696*camOffset[ixr][iyd]
            else
                set r =   .091913*camOffset[ixl][iyu]+ .134226*camOffset[ix][iyu]+ .084604*camOffset[ixr][iyu]
                set r = r+.142877*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .134017*camOffset[ixr][iy]
                set r = r+.091913*camOffset[ixl][iyd]+ .134226*camOffset[ix][iyd]+ .084604*camOffset[ixr][iyd]
            endif
        else
            if offy>0 then
                set r =   .091913*camOffset[ixl][iyu]+ .142877*camOffset[ix][iyu]+ .091913*camOffset[ixr][iyu]
                set r = r+.134226*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .134226*camOffset[ixr][iy]
                set r = r+.084604*camOffset[ixl][iyd]+ .134017*camOffset[ix][iyd]+ .084604*camOffset[ixr][iyd]
            elseif offy<0 then
                set r =   .084604*camOffset[ixl][iyu]+ .134017*camOffset[ix][iyu]+ .084604*camOffset[ixr][iyu]
                set r = r+.134226*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .134226*camOffset[ixr][iy]
                set r = r+.091913*camOffset[ixl][iyd]+ .142877*camOffset[ix][iyd]+ .091913*camOffset[ixr][iyd]
            else
                set r =   .086125*camOffset[ixl][iyu]+ .136429*camOffset[ix][iyu]+ .086125*camOffset[ixr][iyu]
                set r = r+.136429*camOffset[ixl][iy] + .109784*camOffset[ix][iy] + .136429*camOffset[ixr][iy]
                set r = r+.086125*camOffset[ixl][iyd]+ .136429*camOffset[ix][iyd]+ .086125*camOffset[ixr][iyd]
            endif
        endif
        return r
    endfunction

    function GetCamOffset takes real x, real y returns real
        local integer iXLo = R2I((x-mapMinX)/512.+.5)
        local integer iYLo = R2I((y-mapMinY)/512.+.5)
        local integer iXHi = iXLo+1
        local integer iYHi = iYLo+1
        local integer iChkXLo
        local integer iChkXLoOff
        local integer iChkXHi
        local integer iChkXHiOff
        local integer iChkYLo
        local integer iChkYLoOff
        local integer iChkYHi
        local integer iChkYHiOff
        local real XLo
        local real YLo
        local real XHi
        local real YHi
        local real rX
        local real rY
        local real r
        local real LoDX = (x-mapMinX)-(iXLo*512.-256.)
        local real LoDY = (y-mapMinY)-(iYLo*512.-256.)
        if LoDX<=12 then
            set iChkXLo = iXLo
            set iChkXLoOff = 0
            set iChkXHi = iXLo
            set iChkXHiOff = 1
        elseif LoDX<500 then
            set iChkXLo = iXLo
            set iChkXLoOff = 1
            set iChkXHi = iXHi
            set iChkXHiOff =-1
        else
            set iChkXLo = iXHi
            set iChkXLoOff =-1
            set iChkXHi = iXHi
            set iChkXHiOff = 0
        endif
        if LoDY<=12 then
            set iChkYLo = iYLo
            set iChkYLoOff = 0
            set iChkYHi = iYLo
            set iChkYHiOff = 1
        elseif LoDY<500 then
            set iChkYLo = iYLo
            set iChkYLoOff = 1
            set iChkYHi = iYHi
            set iChkYHiOff =-1
        else
            set iChkYLo = iYHi
            set iChkYLoOff =-1
            set iChkYHi = iYHi
            set iChkYHiOff = 0
        endif
        set XLo = iChkXLo*512.+iChkXLoOff*12.-256.
        set XHi = iChkXHi*512.+iChkXHiOff*12.-256.
        set YLo = iChkYLo*512.+iChkYLoOff*12.-256.
        set YHi = iChkYHi*512.+iChkYHiOff*12.-256.
        set rX = ((x-mapMinX)-XLo)/(XHi-XLo)
        set rY = ((y-mapMinY)-YLo)/(YHi-YLo)
        set r =   GetGridCamOffset(iChkXHi,iChkYHi,iChkXHiOff,iChkYHiOff)*rX*rY
        set r = r+GetGridCamOffset(iChkXLo,iChkYHi,iChkXLoOff,iChkYHiOff)*(1-rX)*rY
        set r = r+GetGridCamOffset(iChkXHi,iChkYLo,iChkXHiOff,iChkYLoOff)*rX*(1-rY)
        set r = r+GetGridCamOffset(iChkXLo,iChkYLo,iChkXLoOff,iChkYLoOff)*(1-rX)*(1-rY)
        return r
    endfunction

    function cameramapInit_GridSub takes nothing returns nothing
        local integer index
        local integer iX = -6
        local integer iY
        local real z
        local real r
        local real x = bj_cineFadeContinueRed
        local real y = bj_cineFadeContinueBlue
        local real i = 64 //9*4+12*2+4
        call MoveLocation(cameramapLoc,x,y)
        set z = GetLocationZ(cameramapLoc)
        set r = 0.
        call MoveLocation(cameramapLoc,x-128.,y)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x,y)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x+128.,y)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x-128.,y+128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x,y+128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x+128.,y+128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x-128.,y-128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x,y-128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x+128.,y-128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i

        call MoveLocation(cameramapLoc,x-256.,y-128.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x-256.,y)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x-256.,y+128.)
        set r = r+GetLocationZ(cameramapLoc)*2./i

        call MoveLocation(cameramapLoc,x+256.,y-128.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x+256.,y)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x+256.,y+128.)
        set r = r+GetLocationZ(cameramapLoc)*2./i

        call MoveLocation(cameramapLoc,x-128.,y-256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x,y-256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x+128.,y-256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i

        call MoveLocation(cameramapLoc,x-128.,y+256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x,y+256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x+128.,y+256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i

        call MoveLocation(cameramapLoc,x+256.,y+256.)
        set r = r+GetLocationZ(cameramapLoc)*1./i
        call MoveLocation(cameramapLoc,x+256.,y-256.)
        set r = r+GetLocationZ(cameramapLoc)*1./i
        call MoveLocation(cameramapLoc,x-256.,y+256.)
        set r = r+GetLocationZ(cameramapLoc)*1./i
        call MoveLocation(cameramapLoc,x-256.,y-256.)
        set r = r+GetLocationZ(cameramapLoc)*1./i
        set bj_cineFadeContinueGreen = r
    endfunction

    function cameramapInit takes nothing returns nothing
        local real x
        local real y
        local integer iX = 0
        local integer iY
        local rect map = GetWorldBounds()
        set mapMinX = GetRectMinX(map)
        set mapMinY = GetRectMinY(map)
        set mapMaxX = GetRectMaxX(map)
        set mapMaxY = GetRectMaxY(map)
        call RemoveRect(map)
        set map = null
        set x = mapMinX+256.
        set y = mapMinY+256.
        set cameramapLoc = Location(0,0)
        loop
            exitwhen x+iX*512.>mapMaxX
            set iY = 0
            loop
                exitwhen y+iY*512.>mapMaxY
                set bj_cineFadeContinueRed = x+iX*512.
                set bj_cineFadeContinueBlue = y+iY*512.
                call ExecuteFunc("cameramapInit_GridSub")
                set camOffset[(iX+1)][iY+1] = bj_cineFadeContinueGreen
                set iY = iY + 1
            endloop
            set iX = iX + 1
        endloop
        call RemoveLocation(cameramapLoc)
        set cameramapLoc = null
    endfunction
endlibrary
 
Level 6
Joined
Apr 16, 2007
Messages
177
GetCamOffset(x,y) is the only function to access from outside the library.
It returns the camera z offset on a given terrain position, useful for placing the camera correctly for 3rd person cams and so on...
however, does not work for destructables with an overfly-z-size, nor for water

for everything else, it works so precise that you wont see any inaccuracy with your eyes, i made a 3d flight simulator using it, and the cam sticks to the plane very well

Code:
library cameramap initializer cameramapInit
    globals
        location cameramapLoc
        real array camOffset[256][256]
        real mapMinX
        real mapMinY
        real mapMaxX
        real mapMaxY
    endglobals

    function GetGridCamOffset takes integer ix, integer iy, integer offx, integer offy returns real
        local real r
        local integer ixl = ix-1
        local integer ixr = ix+1
        local integer iyd = iy-1
        local integer iyu = iy+1
        if ixl<0 then
            set ixl = 0
        endif
        if iyd<0 then
            set iyd = 0
        endif
        if ixr>256 then
            set ixr=256
        endif
        if iyu>256 then
            set iyu=256
        endif
        if offx>0 then
            if offy>0 then
                set r =   .089696*camOffset[ixl][iyu]+ .139657*camOffset[ix][iyu]+ .097349*camOffset[ixr][iyu]
                set r = r+.130989*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .139657*camOffset[ixr][iy]
                set r = r+.082587*camOffset[ixl][iyd]+ .130989*camOffset[ix][iyd]+ .089696*camOffset[ixr][iyd]
            elseif offy<0 then
                set r =   .082587*camOffset[ixl][iyu]+ .130989*camOffset[ix][iyu]+ .089696*camOffset[ixr][iyu]
                set r = r+.130989*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .139657*camOffset[ixr][iy]
                set r = r+.089696*camOffset[ixl][iyd]+ .139657*camOffset[ix][iyd]+ .097349*camOffset[ixr][iyd]
            else
                set r =   .084604*camOffset[ixl][iyu]+ .134226*camOffset[ix][iyu]+ .091913*camOffset[ixr][iyu]
                set r = r+.134017*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .142877*camOffset[ixr][iy]
                set r = r+.084604*camOffset[ixl][iyd]+ .134226*camOffset[ix][iyd]+ .091913*camOffset[ixr][iyd]
            endif
        elseif offx<0 then
            if offy>0 then
                set r =   .097349*camOffset[ixl][iyu]+ .139657*camOffset[ix][iyu]+ .089696*camOffset[ixr][iyu]
                set r = r+.139657*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .130989*camOffset[ixr][iy]
                set r = r+.089696*camOffset[ixl][iyd]+ .130989*camOffset[ix][iyd]+ .082587*camOffset[ixr][iyd]
            elseif offy<0 then
                set r =   .089696*camOffset[ixl][iyu]+ .130989*camOffset[ix][iyu]+ .082587*camOffset[ixr][iyu]
                set r = r+.139657*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .130989*camOffset[ixr][iy]
                set r = r+.097349*camOffset[ixl][iyd]+ .139657*camOffset[ix][iyd]+ .089696*camOffset[ixr][iyd]
            else
                set r =   .091913*camOffset[ixl][iyu]+ .134226*camOffset[ix][iyu]+ .084604*camOffset[ixr][iyu]
                set r = r+.142877*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .134017*camOffset[ixr][iy]
                set r = r+.091913*camOffset[ixl][iyd]+ .134226*camOffset[ix][iyd]+ .084604*camOffset[ixr][iyd]
            endif
        else
            if offy>0 then
                set r =   .091913*camOffset[ixl][iyu]+ .142877*camOffset[ix][iyu]+ .091913*camOffset[ixr][iyu]
                set r = r+.134226*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .134226*camOffset[ixr][iy]
                set r = r+.084604*camOffset[ixl][iyd]+ .134017*camOffset[ix][iyd]+ .084604*camOffset[ixr][iyd]
            elseif offy<0 then
                set r =   .084604*camOffset[ixl][iyu]+ .134017*camOffset[ix][iyu]+ .084604*camOffset[ixr][iyu]
                set r = r+.134226*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .134226*camOffset[ixr][iy]
                set r = r+.091913*camOffset[ixl][iyd]+ .142877*camOffset[ix][iyd]+ .091913*camOffset[ixr][iyd]
            else
                set r =   .086125*camOffset[ixl][iyu]+ .136429*camOffset[ix][iyu]+ .086125*camOffset[ixr][iyu]
                set r = r+.136429*camOffset[ixl][iy] + .109784*camOffset[ix][iy] + .136429*camOffset[ixr][iy]
                set r = r+.086125*camOffset[ixl][iyd]+ .136429*camOffset[ix][iyd]+ .086125*camOffset[ixr][iyd]
            endif
        endif
        return r
    endfunction

    function GetCamOffset takes real x, real y returns real
        local integer iXLo = R2I((x-mapMinX)/512.+.5)
        local integer iYLo = R2I((y-mapMinY)/512.+.5)
        local integer iXHi = iXLo+1
        local integer iYHi = iYLo+1
        local integer iChkXLo
        local integer iChkXLoOff
        local integer iChkXHi
        local integer iChkXHiOff
        local integer iChkYLo
        local integer iChkYLoOff
        local integer iChkYHi
        local integer iChkYHiOff
        local real XLo
        local real YLo
        local real XHi
        local real YHi
        local real rX
        local real rY
        local real r
        local real LoDX = (x-mapMinX)-(iXLo*512.-256.)
        local real LoDY = (y-mapMinY)-(iYLo*512.-256.)
        if LoDX<=12 then
            set iChkXLo = iXLo
            set iChkXLoOff = 0
            set iChkXHi = iXLo
            set iChkXHiOff = 1
        elseif LoDX<500 then
            set iChkXLo = iXLo
            set iChkXLoOff = 1
            set iChkXHi = iXHi
            set iChkXHiOff =-1
        else
            set iChkXLo = iXHi
            set iChkXLoOff =-1
            set iChkXHi = iXHi
            set iChkXHiOff = 0
        endif
        if LoDY<=12 then
            set iChkYLo = iYLo
            set iChkYLoOff = 0
            set iChkYHi = iYLo
            set iChkYHiOff = 1
        elseif LoDY<500 then
            set iChkYLo = iYLo
            set iChkYLoOff = 1
            set iChkYHi = iYHi
            set iChkYHiOff =-1
        else
            set iChkYLo = iYHi
            set iChkYLoOff =-1
            set iChkYHi = iYHi
            set iChkYHiOff = 0
        endif
        set XLo = iChkXLo*512.+iChkXLoOff*12.-256.
        set XHi = iChkXHi*512.+iChkXHiOff*12.-256.
        set YLo = iChkYLo*512.+iChkYLoOff*12.-256.
        set YHi = iChkYHi*512.+iChkYHiOff*12.-256.
        set rX = ((x-mapMinX)-XLo)/(XHi-XLo)
        set rY = ((y-mapMinY)-YLo)/(YHi-YLo)
        set r =   GetGridCamOffset(iChkXHi,iChkYHi,iChkXHiOff,iChkYHiOff)*rX*rY
        set r = r+GetGridCamOffset(iChkXLo,iChkYHi,iChkXLoOff,iChkYHiOff)*(1-rX)*rY
        set r = r+GetGridCamOffset(iChkXHi,iChkYLo,iChkXHiOff,iChkYLoOff)*rX*(1-rY)
        set r = r+GetGridCamOffset(iChkXLo,iChkYLo,iChkXLoOff,iChkYLoOff)*(1-rX)*(1-rY)
        return r
    endfunction

    function cameramapInit_GridSub takes nothing returns nothing
        local integer index
        local integer iX = -6
        local integer iY
        local real z
        local real r
        local real x = bj_cineFadeContinueRed
        local real y = bj_cineFadeContinueBlue
        local real i = 64 //9*4+12*2+4
        call MoveLocation(cameramapLoc,x,y)
        set z = GetLocationZ(cameramapLoc)
        set r = 0.
        call MoveLocation(cameramapLoc,x-128.,y)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x,y)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x+128.,y)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x-128.,y+128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x,y+128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x+128.,y+128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x-128.,y-128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x,y-128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i
        call MoveLocation(cameramapLoc,x+128.,y-128.)
        set r = r+GetLocationZ(cameramapLoc)*4./i

        call MoveLocation(cameramapLoc,x-256.,y-128.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x-256.,y)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x-256.,y+128.)
        set r = r+GetLocationZ(cameramapLoc)*2./i

        call MoveLocation(cameramapLoc,x+256.,y-128.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x+256.,y)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x+256.,y+128.)
        set r = r+GetLocationZ(cameramapLoc)*2./i

        call MoveLocation(cameramapLoc,x-128.,y-256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x,y-256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x+128.,y-256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i

        call MoveLocation(cameramapLoc,x-128.,y+256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x,y+256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i
        call MoveLocation(cameramapLoc,x+128.,y+256.)
        set r = r+GetLocationZ(cameramapLoc)*2./i

        call MoveLocation(cameramapLoc,x+256.,y+256.)
        set r = r+GetLocationZ(cameramapLoc)*1./i
        call MoveLocation(cameramapLoc,x+256.,y-256.)
        set r = r+GetLocationZ(cameramapLoc)*1./i
        call MoveLocation(cameramapLoc,x-256.,y+256.)
        set r = r+GetLocationZ(cameramapLoc)*1./i
        call MoveLocation(cameramapLoc,x-256.,y-256.)
        set r = r+GetLocationZ(cameramapLoc)*1./i
        set bj_cineFadeContinueGreen = r
    endfunction

    function cameramapInit takes nothing returns nothing
        local real x
        local real y
        local integer iX = 0
        local integer iY
        local rect map = GetWorldBounds()
        set mapMinX = GetRectMinX(map)
        set mapMinY = GetRectMinY(map)
        set mapMaxX = GetRectMaxX(map)
        set mapMaxY = GetRectMaxY(map)
        call RemoveRect(map)
        set map = null
        set x = mapMinX+256.
        set y = mapMinY+256.
        set cameramapLoc = Location(0,0)
        loop
            exitwhen x+iX*512.>mapMaxX
            set iY = 0
            loop
                exitwhen y+iY*512.>mapMaxY
                set bj_cineFadeContinueRed = x+iX*512.
                set bj_cineFadeContinueBlue = y+iY*512.
                call ExecuteFunc("cameramapInit_GridSub")
                set camOffset[(iX+1)][iY+1] = bj_cineFadeContinueGreen
                set iY = iY + 1
            endloop
            set iX = iX + 1
        endloop
        call RemoveLocation(cameramapLoc)
        set cameramapLoc = null
    endfunction
endlibrary

Cool system, wrong thread.
This is for "Small Code Snippets" (see title) ;)
 
Level 11
Joined
May 26, 2005
Messages
194
i was unable to upload it in the jass section, and this doesnt fit to spells, so i thought small code snippets would be the most fitting topic

i actually would prefer this in a single thread, too, as it isnt some small non-sense function like some of the others here, though it can be used as easily
 
Level 6
Joined
Jun 4, 2009
Messages
91
I think this will fit here, and I hope no one already posted something alike :
It allow to change the name or a color of a player for some player only, so other people won't see any change. It avoid desynchronisations.
It can be used to hide a force to from one other, giving him the same name as a neutral computer player

JASS:
scope PlayerUtilities initializer PlayerUtilitiesInit

    globals
        //the original players names
        string array PlayersNames
        playercolor array PlayersColors
    endglobals
    
    
    //------------------------------
    //changing the name of a player
    //------------------------------
    function ChangePlayerNameForForceOnly takes player whichPlayer, string newName, force forWho returns nothing
        local string name = GetPlayerName(whichPlayer)
        if ( IsPlayerInForce(GetLocalPlayer(), forWho) ) then
            set name = newName
        endif
        call SetPlayerName(whichPlayer, name)
    endfunction
    
    function ChangePlayerNameForPlayerOnly takes player whichPlayer, string newName, player forWho returns nothing
        local string name = GetPlayerName(whichPlayer)
        if ( GetLocalPlayer() == forWho ) then
            set name = newName
        endif
        call SetPlayerName(whichPlayer, name)
    endfunction
    
    function RetrievePlayerName takes player whichPlayer returns nothing
        call SetPlayerName(whichPlayer, PlayersNames[GetPlayerId(whichPlayer)])
    endfunction
    
    function RetrievePlayerNameForForceOnly takes player whichPlayer, force forWho returns nothing
        local string name = GetPlayerName(whichPlayer)
        if ( IsPlayerInForce(GetLocalPlayer(), forWho) ) then
            set name = PlayersNames[GetPlayerId(whichPlayer)]
        endif
        call SetPlayerName(whichPlayer, name)
    endfunction
    
    function RetrievePlayerNameForPlayerOnly takes player whichPlayer, player forWho returns nothing
        local string name = GetPlayerName(whichPlayer)
        if ( GetLocalPlayer() == forWho ) then
            set name = PlayersNames[GetPlayerId(whichPlayer)]
        endif
        call SetPlayerName(whichPlayer, name)
    endfunction
    
    //-------------------------------
    //changing the color of a player
    //-------------------------------
    function ChangePlayerColorForForceOnly takes player whichPlayer, playercolor newColor, force forWho returns nothing
        local playercolor color = GetPlayerColor(whichPlayer)
        if ( IsPlayerInForce(GetLocalPlayer(), forWho) ) then
            set color = newColor
        endif
        call SetPlayerColor(whichPlayer, color)
    endfunction
    
    function ChangePlayerColorForPlayerOnly takes player whichPlayer, playercolor newColor, player forWho returns nothing
        local playercolor color = GetPlayerColor(whichPlayer)
        if ( GetLocalPlayer() == forWho ) then
            set color = newColor
        endif
        call SetPlayerColor(whichPlayer, color)
    endfunction
    
    function RetrievePlayerColor takes player whichPlayer returns nothing
        call SetPlayerColor(whichPlayer, PlayersColors[GetPlayerId(whichPlayer)])
    endfunction
    
    function RetrievePlayerColorForForceOnly takes player whichPlayer, force forWho returns nothing
        local playercolor color = GetPlayerColor(whichPlayer)
        if ( IsPlayerInForce(GetLocalPlayer(), forWho) ) then
            set color = PlayersColors[GetPlayerId(whichPlayer)]
        endif
        call SetPlayerColor(whichPlayer, color)
    endfunction
    
    function RetrievePlayerColorForPlayerOnly takes player whichPlayer, player forWho returns nothing
        local playercolor color = GetPlayerColor(whichPlayer)
        if ( GetLocalPlayer() == forWho ) then
            set color = PlayersColors[GetPlayerId(whichPlayer)]
        endif
        call SetPlayerColor(whichPlayer, color)
    endfunction
    
    function PlayerUtilitiesInit takes nothing returns nothing
        local integer index = 0
        loop
            exitwhen index > 11
            set PlayersNames[index] = GetPlayerName(Player(index))
            set PlayersColors[index] = GetPlayerColor(Player(index))
            set index = index + 1
        endloop
    endfunction
    
endscope
 
Level 6
Joined
Oct 4, 2008
Messages
263
JASS:
function GroupEnumClosestNUnits takes real x, real y, boolexpr e, integer num, group g returns nothing
    local unit u
    local group gl =
    local integer i = 0
    call GroupEnumUnitsInRect(gl, GetPlayableMapRect(), e)
    loop
        exitwhen i>num-1
        set u = GetClosestUnit(x, y, null)
        if IsUnitInGroup(u, gl) then
            call GroupAddUnit(g, u)
            call GroupRemoveUnit(gl, u)
        endif
    endloop

Dependant on silvenon's GetClosestUnit. will add the num closest units to location (x,y) to a specified group.
 
Level 9
Joined
Nov 28, 2008
Messages
704
how about a simple timer system that does things X amount of times, which you can attach data to? I can't help but feel we have something like that... :p

JASS:
struct TimerSystem
    timer Timer
    integer Ticks
    //attach some extra data here, and you can steal it any time!
    static method create takes timer Timer, integer Ticks returns TimerSystem
        local TimerSystem System = TimerSystem.allocate()
        set System.Timer = Timer 
        set System.Ticks = Ticks
        return System
    endmethod
    method onDestroy takes nothing returns nothing
        call PauseTimer(.Timer)
        call DestroyTimer(.Timer)
        set .Timer = null
    endmethod
    static method Find takes timer Timer returns TimerSystem
        local integer i = 1
        loop
            if Timer == TimerSystem(i).Timer then
                set TimerSystem(i).Ticks = TimerSystem(i).Ticks - 1
                if TimerSystem(i).Ticks < 0 then
                    call TimerSystem(i).destroy()
                    return 0
                endif
                return TimerSystem(i)
            endif
            set i = i + 1
        endloop
        return 0
    endmethod
endstruct

Precreate a timer, periodic, start it, and then create your system. Inside the function, just call the TimerSystem.Find(GetExpiredTmer()) and you can get anything you want (just don't forget to check if it returned 0! if it did, return). Instant win.

JASS:
local TimerSystem System = TimerSystem.Find(GetExpiredTimer())
        if integer(System) < 1 then
            return
        endif
 
Last edited:
Level 14
Joined
Mar 4, 2009
Messages
1,156
This is a script I made that will revive trees that die for some reason. Whether it be a peasant picking at it or a spell that destroys trees like flame strike.

JASS:
function RegrowTrees takes nothing returns nothing
    local destructable tree=GetDyingDestructable()
    call TriggerSleepAction(10)
    call DestructableRestoreLife( tree, GetDestructableMaxLife(tree), true )
    set tree=null
endfunction

function Trig_Int_Tree_Revival takes nothing returns nothing
    local integer d=GetDestructableTypeId(GetEnumDestructable())
    if d=='ATtr' or d=='BTtw' or d=='KTtw' or d=='YTft' or d=='YTct' or d=='YTwt' or d=='JTwt' or d=='DTsh' or d=='FTtw' or d=='CTtr' or d=='ITtw' or d=='NTtw' or d=='OTtw' or d=='ZTtw' or d=='WTst' or d=='LTlt' or d=='GTsh' or d=='Xtlt' or d=='WTtw' or d=='ATtc' or d=='BTtc' or d=='CTtc' or d=='ITtc' or d=='ZTtc' then
    call TriggerRegisterDeathEvent( gg_trg_Regrow_Trees, GetEnumDestructable() )
    call TriggerAddAction(gg_trg_Regrow_Trees,function RegrowTrees)
endif
endfunction

function Int_Tree_Revive takes nothing returns nothing
    call EnumDestructablesInRect(GetPlayableMapRect(), null, function Trig_Int_Tree_Revival)
endfunction

___________

I will add a test map later

i don´t understand JASS much but ...

if you set a lot of health to trees (shit + enter you know it...) its almost impossible to cut them out,accept if your worker takes 500000 wood per hit,and it would be very hard anyway

BTW does the stun system stop the unit if he uses spell like wind walk xD

sry have to ask :D
 
Level 11
Joined
Apr 29, 2007
Messages
826
Simple PathableCheck version, it's way better and more exactly than using Vexorian's (because it uses 2 items)
vJASS Version:

JASS:
library PathableCheck initializer PathableInit

globals
    private item i
    private item i2
endglobals

function PathableCheck takes real x, real y returns boolean

    if i == null then
        set i = CreateItem( 'ciri', x, y )
    endif

    if i2 == null then
        set i2 = CreateItem( 'ciri', x, y )
    endif
    
    call SetItemPosition( i, x, y )
    call SetItemPosition( i2, x, y )
    
    
    if ( GetItemX( i ) == x and GetItemY( i ) == y ) and not ( GetItemX( i2 ) == x and GetItemY( i2 ) == y ) then
        call SetItemVisible( i, false )
        call SetItemVisible( i2, false )
        return true
    endif
    
    call SetItemVisible( i, false )
    call SetItemVisible( i2, false )
    
    return false
endfunction

private function PathableInit takes nothing returns nothing
    set i = CreateItem( 'ciri', 0, 0 )
    call SetItemVisible( i, false )
    
    set i2 = CreateItem( 'ciri', 0, 0 )
    call SetItemVisible( i2, false )
endfunction


endlibrary

non-vJASS version:
JASS:
function PathableCheck takes real x, real y returns boolean

    local item i = CreateItem( 'ciri', x, y )
    local item i2 = CreateItem( 'ciri', x, y )
    
    call SetItemPosition( i, x, y )
    call SetItemPosition( i2, x, y )
    
    if ( GetItemX( i ) == x and GetItemY( i ) == y ) and not ( GetItemX( i2 ) == x and GetItemY( i2 ) == y ) then
        call RemoveItem( i )
        call RemoveItem( i2 )
        return true
    endif
    
    call RemoveItem( i )
    call RemoveItem( i2 )
    return false
    
endfunction
 
Last edited:
Level 11
Joined
Apr 29, 2007
Messages
826
ehm.... I dont see any sens in this... just doing the thing 2 times wtf oO....
it's not better nor more exactly

It is better because it also detects cliffs with destructables on it and deep water.

Let's say, if theres a cliff with only 1 destructable on it, like this:

xxx
xTx
xxx

The other function would return true on the place with the tree, while mine would return false.
 
Level 11
Joined
May 26, 2005
Messages
194
xD.Schurke dont claim yourself a vJass devil if you do not even understand that function...

it does not do the whole thing twice:

using one item has a big problem, as warcraft seems to search for other pathable spots only on the same cliff level, and if theres no valid point, then the item is just created inside the tree or inside the deep water (because deep water is a cliff level on its own, it will never find the nearby shallow water)

and now this script creates a second item and checks whether the second item is NOT at the position it was created on... because that position should be blocked by the created item, warcraft will only ignore this when the first item is inside a non-pathable area itself...

JASS:
if ( GetItemX( i ) == x and GetItemY( i ) == y ) and not ( GetItemX( i2 ) == x and GetItemY( i2 ) == y ) then

its all about the "not"
 
Level 16
Joined
Feb 22, 2006
Messages
960
ehm this doesn't work.... you can test it, it will also return true if it's in deep water <.<

so don't blame me!

here screen or didnt happen <.<

also the thing with one item also detects destructables on another cliff level it does exactly the same
 

Attachments

  • omg.JPG
    omg.JPG
    269.6 KB · Views: 214
Level 13
Joined
Nov 22, 2006
Messages
1,260
This determines the difference between two angles (it's a positive value). It takes radians.

JASS:
    function AngleDist takes real a1, real a2 returns real
        local real d = 0
        local real r = a1 + bj_PI
        
        if a1 < 0 then
            set a1 = 2 * bj_PI + a1
        endif
        
        if a2 < 0 then
            set a2 = 2 * bj_PI + a2
        endif
        
        set d = a2 - a1
        
        if d < 0 then
            set d = -d
        endif
        
        if r > 2 * bj_PI then
            set r = r - 2 * bj_PI
        endif
        
        if d > r then
            set d = 2 * bj_PI - d
        endif
        
        return d
    endfunction
 
Level 7
Joined
Mar 24, 2008
Messages
184
Yet another function to check if a certain point can be walked (ignores units but not buildings or doodads), it's quite precise but also very sensitive.
The biggest difference with other similar functions is it doesn't use an item but a unit with windwalk.

It requires a dummy unit and a permanent windwalk ability that will be automatically created through the object merger lines.
The two //! lines are Object merger commands that will automatically create the dummy unit and the ability, if you don't want to use this feature just delete the two lines

JASS:
//**************************************************************************
// ** **
// ** Check Pathability Function **
// ** ————————————— **
// ** **
// ** A Function that checks if a unit can walk over a certain area **
// ** (Ignores units but not buildings, trees and other obstacles) **
// ** **
// ** By: Majin **
// ** 
// ** **
// **************************************************************************
//! external ObjectMerger w3a ANwk perw aefs "" Owk1 1 0.00 Owk2 1 0.00 Owk3 1 0.00 Owk4 1 0 aher 0 amcs 1 0 ahdu 1 0.00 adur 1 0.00 alev 1 acdn 1 0.00 anam "Permawalk" ansf ""
//! external ObjectMerger w3u ewsp patc uabi Aloc,Avul ushr 0 umdl "None.mdl" upgr "" unam "Pathchecker"

library Walkable initializer init
    globals
        //ID of the dummy unit used for the path checker function (has to be an invulnerable locusted unit with No model)
        constant integer PATHCHECKERID = 'patc'
        //ID of the permanent windwalk spell used for the path checker function
        constant integer SPELLPATHID = 'perw'
        unit pathchecker
        rect pathrect
    endglobals
    
    function AntiLeak takes nothing returns boolean
        return true
    endfunction
    
    function HideItems takes nothing returns nothing
        call SetItemVisible(GetEnumItem(), false)    
    endfunction
    
    function UnHideItems takes nothing returns nothing
        call SetItemVisible(GetEnumItem(), true)    
    endfunction
    
    function IsPointWalkable takes real x, real y returns boolean
        local boolean b
        call SetUnitPosition(pathchecker,x,y)
        set b=((GetUnitX(pathchecker)-x)*(GetUnitX(pathchecker)-x)+((GetUnitY(pathchecker)-y)*(GetUnitY(pathchecker)-y))<=1)
        if (b==false) then
            call MoveRectTo(pathrect, x, y)
            call EnumItemsInRect(pathrect,truefilter,function HideItems)
            call SetUnitPosition(pathchecker,x,y)
            set b=((GetUnitX(pathchecker)-x)*(GetUnitX(pathchecker)-x)+((GetUnitY(pathchecker)-y)*(GetUnitY(pathchecker)-y))<=1) 
            call EnumItemsInRect(pathrect,truefilter,function UnHideItems)
        endif
        return b
    endfunction

    function init takes nothing returns nothing
        //Using 0 on a map that had its bounds changed will cause the rect to not be created
        local real x = GetRectMinX(bj_mapInitialPlayableArea)
        local real y = GetRectMinY(bj_mapInitialPlayableArea)
        set pathrect=Rect(x,y,x+200.00,y+200.00)
        //It seems it doesn't matter for units instead
        set pathchecker=CreateUnit( Player(PLAYER_NEUTRAL_PASSIVE), PATHCHECKERID, 0, 0, 0)
        call UnitAddAbility(pathchecker, SPELLPATHID)
        call IssueImmediateOrder( pathchecker, "windwalk" )
    endfunction
endlibrary
 
Last edited:
Level 7
Joined
Mar 24, 2008
Messages
184
I don't think that's what he meant. Make the object entirely in the ObjectMerger line, don't just do a merge.

EDIT: Like this (for the unit)
JASS:
//! external ObjectMerger w3u ewsp patc uabi Aloc,Avul ushr 0 umdl "None.mdl" upgr "" unam "Pathchecker"

Honestly i didn't know you could do that too with the object merger, but it's always good to know new things :)

Putting the unit for now, i'll do the ability later (btw i had to change the upgr part with "" instead of none)

I must admit that I still didn't learn the object merger part in JNGP, but I probably meant that you should ad an object merger call which makes the windwalk ability and the dummy unit when you save the map.

Well the object merger script i put did that actually, it just required external files
 
Last edited:
Well I also have my shares:

IsPointinCone:

Jass:
JASS:
function IsPointInCone takes real x1, real y1, real x2, real y2, real f, real a returns boolean
    return Cos(Atan2(y2-y1,x2-x1)-f) > Cos(a)
endfunction

cJass:
JASS:
bool IsPointInCone(float x1,float y1,float x2,float y2,float f,float a) { 
    return Cos(Atan2(y2-y1,x2-x1)-f) > Cos(a); 
}

sketcht.jpg


Pretty much this function helps detect if a point is within the cone facing of other point. The function takes both points, the facing of the center point (imagine it as unit facing)[in the image the facing is 0º] and takes the angle of the cone axi. This last angle must range from 0 to pi. In the example the angle is 45º|PI/4 but the covered zone is 90º. Have that in mind.
 
Top