• 🏆 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!

Small Code Snippets

Level 12
Joined
Aug 20, 2007
Messages
866
The function main is the function generated by the world editor.
It's the function which is run the first and call all the others init.
Btw it can be custom easily with the jasshelper.

function main() -> InitBlizzard() ->InitMapRects()

JASS:
function InitMapRects takes nothing returns nothing
    set bj_mapInitialPlayableArea = Rect(GetCameraBoundMinX()-GetCameraMargin(CAMERA_MARGIN_LEFT), GetCameraBoundMinY()-GetCameraMargin(CAMERA_MARGIN_BOTTOM), GetCameraBoundMaxX()+GetCameraMargin(CAMERA_MARGIN_RIGHT), GetCameraBoundMaxY()+GetCameraMargin(CAMERA_MARGIN_TOP))
    set bj_mapInitialCameraBounds = GetCurrentCameraBoundsMapRectBJ()
endfunction



For the smallest map possible, 32*32 :


So calculate yourself how many iterations your loop will do, it's pretty huge...

"Irritated" NOT MY CALCULATION "End"
 
Level 11
Joined
Apr 6, 2008
Messages
760
This is a small dummy recycling system i made (took 10 min),its just a simple stack of units and very easy to use. any suggestions or idéa's are welcome :)

JASS:
library DummyRecycling initializer Init

globals
    private constant real WAIT_TIME = 1. //time to wait before "removing" a dummy
    private constant integer Dummy_id = 'hfoo' //dummy rawcode
    private constant integer ARRAY_SIZE = 20 //Max Number of Dummy's (u dont need so many)
    private unit array Dummys [ARRAY_SIZE]
    private integer Total = 0
    private integer Index = 0
endglobals

function CreateDummy takes player P, real x,real y returns unit
    if Total < ARRAY_SIZE then // if the stack isnt full we create or move a unit
        if Index >= Total then //if there no free units we create more
            set Dummys[Index] = CreateUnit(P,Dummy_id,x,y,0.)
            call UnitRemoveAbility(Dummys[Index],'Amov')
            set Total = Total + 1
            set Index = Index + 1
        else //else we move one
            call SetUnitX(Dummys[Index],x)
            call SetUnitY(Dummys[Index],y)
            call SetUnitOwner(Dummys[Index],P,false)
            set Index = Index + 1
        endif
        return Dummys[Index-1]
    debug else
    debug call BJDebugMsg("To many dummy's, increase the ARRAY_SIZE")
    endif
    
    return null
endfunction

function CreateDummyLoc takes player P, location loc returns nothing
    call CreateDummy(P,GetLocationX(loc),GetLocationY(loc))
    call RemoveLocation(loc)
    set loc = null
endfunction

function ReleaseDummy takes unit u returns nothing //this just change the owner of the dummy (maybe we should move them some where?)
    if GetUnitTypeId(u) == Dummy_id then
            call TriggerSleepAction(WAIT_TIME) //maybe use a timer instead?
            call SetUnitOwner(u,Player(15),false)
            set Index = Index - 1
        debug else
        debug call BJDebugMsg("function RemoveDummy: Unit given is not a Dummy Unit")
    endif
endfunction

private function Init takes nothing returns nothing
    set Dummys[Index] = CreateUnit(Player(15),Dummy_id,0.,0.,0.)
    call UnitRemoveAbility(Dummys[Index],'Amov')
    set Total = Total + 1
endfunction

endlibrary

e.g of usage

JASS:
set Temp = CreateDummy(GetOwningPlayer(GetTriggerUnit(),0.,0.)
//dummy stuff
call ReleaseDummy(Temp)

well im in a rush so can't write more (ill get back later)
 
Level 12
Joined
Aug 20, 2007
Messages
866
I don't really get why one would need a dummy recycling system, if you think about it, you only ever need the amount of units to be used when they are used, holding more just uses space, like a leak.

Unless it takes more memory to create unit than it does to run all of those functions to store an already created one, I really don't know, but I feel like the memory usage is from the presence of the unit, not its coming into usage.

EDIT - Something I just thought up, used for calling code without using TriggerEvaluate(), while avoiding constantly destroying the triggers you use

JASS:
library CallCode
globals
    private trigger T = CreateTrigger()
    private conditionfunc C
    private boolean B
endglobals
function CallCode takes code c returns boolean
    set C = TriggerAddCondition(T, Condition(c))
    set B = TriggerEvaluate(T)
    call TriggerRemoveCondition(C)
    return B
endfunction
endlibrary
 
Level 3
Joined
Nov 18, 2007
Messages
48
here is a little function, probably leaked because i am a noob but works ingame perfectly, removes a unit in a period of time like native UnitApplyTimedLife... this function's proper way to use is after death of an unit to clean it faster for example whenever death animation ends of an special effect dummie unit so you don't have to use buggy waits. (pause game doesn't affect waits)

Requieres handle vars


JASS:
function RemoveUnitTimer takes nothing returns nothing
local timer T = GetExpiredTimer()
local unit U = GetHandleUnit(T, "u")
local real duration = GetHandleReal(T, "dur")
if duration > 0.05 then
call SetHandleReal(T,"dur", duration-0.05)
else
call RemoveUnit(U)
call FlushHandleLocals(T)
endif
endfunction
function AddRemoveUnitTimer takes unit U, real duration returns nothing
local timer T = CreateTimer()
call SetHandleReal(T,"dur", duration)
call SetHandleHandle(T,"u", U)
call TimerStart(T,0.05,true, function RemoveUnitTimer)
set T = null
endfunction
 
Level 12
Joined
Aug 20, 2007
Messages
866
Oh, that sounds really good

Like, if you had a projectile that had locust, and then sent it on its path without using the X/Y, the locust would move all f*cked up when it got to a cliff or something, but if you first use the X/Y, then it will do it cleanly?

(I don't have war3 isntalled on this comp, but I would very very much appreciate somebody checking that for me)
 
Level 9
Joined
Mar 25, 2005
Messages
252
Like, if you had a projectile that had locust, and then sent it on its path without using the X/Y, the locust would move all f*cked up when it got to a cliff or something, but if you first use the X/Y, then it will do it cleanly?

I tried to create a unit with locust at the position of a normal unit, but the locusted unit appeared on the side of it, not 'inside' it like it would if I had moved it there with SetUnitX/Y.

(forgot to mention in my earlier post that I was only talking about the moment of creation)
 
Last edited:
Level 12
Joined
Feb 23, 2007
Messages
1,030
JASS:
scope GameClock
globals
private multiboarditem i
private integer c=0
endglobals

private function Deciseconds takes nothing returns string
if ModuloInteger(c,100)>9 then
    return I2S(ModuloInteger(c,100))
else
    return "0"+I2S(ModuloInteger(c,100))
endif
endfunction

private function Seconds takes nothing returns string
if ModuloInteger(c/100,60)>9 then
    return I2S(ModuloInteger(c/100,60))
else
    return "0"+I2S(ModuloInteger(c/100,60))
endif
endfunction

private function Minutes takes nothing returns string
if ModuloInteger(c/6000,60)>9 then
    return I2S(ModuloInteger(c/6000,60))
else
    return "0"+I2S(ModuloInteger(c/6000,60))
endif
endfunction

private function Hours takes nothing returns string
if c/360000>9 then
    return I2S(c/360000)
else
    return "0"+I2S(c/360000)
endif
endfunction

private function Timer takes nothing returns nothing
set c=c+1
call MultiboardSetItemValue(i,Hours()+":"+Minutes()+":"+Seconds()+":"+Deciseconds())
endfunction

private function Actions takes nothing returns nothing
local multiboard m=CreateMultiboard()
call MultiboardSetTitleText(m,"Game Clock")
call MultiboardSetTitleTextColor(m,100,100,255,0)
call MultiboardSetColumnCount(m,1)
call MultiboardSetRowCount(m,1)
call MultiboardDisplay(m,true)
set i=MultiboardGetItem(m,0,0)
call MultiboardSetItemWidth(i,.06)
call MultiboardSetItemValueColor(i,0,255,0,0)
call MultiboardSetItemStyle(i,true,false)
call TimerStart(CreateTimer(),0.01,true,function Timer)
call DestroyTrigger(GetTriggeringTrigger())
set m=null
endfunction
//===========================================================================
function InitTrig_GameClock takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterTimerEvent(t,0,false)
call TriggerAddAction(t,function Actions)
set t=null
endfunction
endscope

JASS:
scope GameClock

globals
private multiboarditem i
private integer c=0
endglobals

private function Seconds takes nothing returns string
if ModuloInteger(c,60)>9 then
    return I2S(ModuloInteger(c,60))
else
    return "0"+I2S(ModuloInteger(c,60))
endif
endfunction

private function Minutes takes nothing returns string
if ModuloInteger(c/60,60)>9 then
    return I2S(ModuloInteger(c/60,60))
else
    return "0"+I2S(ModuloInteger(c/60,60))
endif
endfunction

private function Hours takes nothing returns string
if c/3600>9 then
    return I2S(c/3600)
else
    return "0"+I2S(c/3600)
endif
endfunction

private function Timer takes nothing returns nothing
set c=c+1
call MultiboardSetItemValue(i,Hours()+":"+Minutes()+":"+Seconds())
endfunction

private function Actions takes nothing returns nothing
local multiboard m=CreateMultiboard()
call MultiboardSetTitleText(m,"Game Clock")
call MultiboardSetTitleTextColor(m,100,100,255,0)
call MultiboardSetColumnCount(m,1)
call MultiboardSetRowCount(m,1)
call MultiboardDisplay(m,true)
set i=MultiboardGetItem(m,0,0)
call MultiboardSetItemWidth(i,.06)
call MultiboardSetItemValueColor(i,0,255,0,0)
call MultiboardSetItemStyle(i,true,false)
call TimerStart(CreateTimer(),1,true,function Timer)
call DestroyTrigger(GetTriggeringTrigger())
set m=null
endfunction
//===========================================================================
function InitTrig_GameClock takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterTimerEvent(t,0,false)
call TriggerAddAction(t,function Actions)
set t=null
endfunction

endscope

I improved upon my old timer. Hopefully you like this one.
 
Level 12
Joined
Aug 20, 2007
Messages
866
Errr, when would you need to check just one integer variable?

I think as a concept this is ok, but as code to be used, this isn't too useful as a debugging tool unless you could specify the array being checked, converting it to a textmacro may be helpful
 
Level 6
Joined
Apr 16, 2007
Messages
177
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

this one is bugged.
JASS:
            set StunArray[i]=StunArray[Stun_Total]
needs to be
JASS:
            set StunArray[i]=StunArray[Stun_Total - 1 ]
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
Here is something I use - Get Random Unit In Range:
JASS:
function GRUIR takes real x, real y, real range,player p, boolean Ally,unit w, group z,boolean In,code fil returns unit
    local group g=CreateGroup()
    local unit a=null
    local unit i
    local integer b=0
    call GroupEnumUnitsInRange(g,x,y,range,Condition(fil))
    loop
    set i=FirstOfGroup(g)
    exitwhen i==null
        if(IsUnitAlly(i,p)==Ally and IsUnitInGroup(i,z)==In and (i!=w)) then
            set b=b+1
            if (GetRandomInt(1,b) == 1) then
                set a = i
            endif
        endif
        call GroupRemoveUnit(g,i)
    endloop
    set bj_groupRandomCurrentPick=a
    call DestroyGroup(g)
    set g=null
    set a=null
    return bj_groupRandomCurrentPick
endfunction
Gets a random unit that fits some conditions: it is not a certain unit, it is an ally/enemy of a certain player,
it is in/not in a certain unit group.
Those conditions make this suitable for chain like selection.
The parameters are quite simple:
real x, real y, real range,player p, boolean Ally,unit w, group z,boolean In,code fil

First two are the coordinates for the circle's center. Third is the range.
Fourth is a player you want the random unit to be ally/enemy of. Fifth specifies if you want an enemy or
an ally of the player- true is ally, false means enemy. If you do not want the unit owner to influence the pick use null, false.
Sixth is a unit you want to ignore. If you do not want such a check done use null.
Seventh is a unit group you want the random unit to be in or out. Eighth specifies if you want it to be
in or out of the group - true is in, false is out. If you do not want to check for this use null and false.
Ninth specifies a filter function. For instance:
JASS:
function isun takes nothing returns boolean
    return (IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)==false and IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL)==false and GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>0.405) 
endfunction
 
Last edited:
Level 12
Joined
Apr 27, 2008
Messages
1,228
Because this way saves me a lot of code :p
And Blizzard's people made a good function for random unit from group.
 
Level 18
Joined
Oct 18, 2007
Messages
930
attachment.php


w3x_m.gif
Shapes.w3x
 

Attachments

  • Shape System.w3x
    20.6 KB · Views: 215
  • Shapes.png
    Shapes.png
    392.6 KB · Views: 1,959
Level 9
Joined
Nov 28, 2008
Messages
704
If your using an RPG chat system, and have disabled normal chat, or just want a color to show up when a players unit dies, like in dota, just give the player number to this, and out it spits a color code for a player from 1-12. Im unsure on how brown looks though, as I couldnt find the brown they use in WC3 to copy.. meh.

JASS:
    function PlayerColorCode takes integer PlayerNumber returns string
            if PlayerNumber == 1 then
                return "|cffff0000"
            elseif PlayerNumber == 2 then
                return "|cff0000FF"
            elseif PlayerNumber == 3 then
                return "|cff00ffff"
            elseif PlayerNumber == 4 then
                return "|cff551A8B"
            elseif PlayerNumber == 5 then
                return "|cffffff00"
            elseif PlayerNumber == 6 then
                return "|cffFFA500"
            elseif PlayerNumber == 7 then
                return "|cff00FF00"
            elseif PlayerNumber == 8 then
                return "|cffFFC0CB"
            elseif PlayerNumber == 9 then
                return "|cff9C9C9C"
            elseif PlayerNumber == 10 then
                return "|cffADD8E6"
            elseif PlayerNumber == 11 then
                return "|cff006400"
            elseif PlayerNumber == 12 then
                return "|cff8b4513" 
            endif
            return "Failure to provide a number from 1-12."
    endfunction



If your using the same units for basically everything, but they have no team colors or glows.. heres a tint that requires a player number, and how much transparency you want, and a unit.

JASS:
function TintUnit takes unit TempUnit, integer PlayerNumber, real Transparency returns nothing
        local real array RGB
        if PlayerNumber == 1 then
            set RGB[0] = 100
        elseif PlayerNumber == 2 then
            set RGB[2] = 100
        elseif PlayerNumber == 3 then
            set RGB[1] = 100
            set RGB[2] = 100
        elseif PlayerNumber == 4 then
            set RGB[0] = 32.2
            set RGB[1] = 10.16
            set RGB[2] = 54.3
        elseif PlayerNumber == 5 then
            set RGB[0] = 100
            set RGB[1] = 100
        elseif PlayerNumber == 6 then
            set RGB[0] = 100
            set RGB[1] = 64.45
        elseif PlayerNumber == 7 then
            set RGB[1] = 100
        elseif PlayerNumber == 8 then
            set RGB[0] = 100
            set RGB[1] = 75
            set RGB[2] = 79.3
        elseif PlayerNumber == 9 then
            set RGB[0] = 60.94
            set RGB[1] = 60.94
            set RGB[2] = 60.94
        elseif PlayerNumber == 10 then
            set RGB[0] = 67.58
            set RGB[1] = 84.38
            set RGB[2] = 89.84
        elseif PlayerNumber == 11 then
            set RGB[1] = 39.06
        elseif PlayerNumber == 12 then
            set RGB[0] = 54.3
            set RGB[1] = 26.95
            set RGB[2] = 7.42
        endif
        call SetUnitVertexColorBJ( TempUnit, RGB[0], RGB[1], RGB[2], Transparency )
        set TempUnit = null
    endfunction




Edit: Due to my other functions being made while I didnt have the actual color codes, and whatever.. I present the Library (requires vJass) of Color..

JASS:
library Colors initializer Init_Colors
                    //Color codes for players. Has three functions: GPCC, GPCN, and GPCNU.
globals
    string array ColorCodes     //Variables are faster, and require much less if/then/elses.
endglobals

function GPCC takes integer i returns string //Short for Get Player Color Code
    if i > -1 and i < 12 then
        return ColorCodes[i]
    endif                                               //This should be used if you want to use custom names in a custom chat system using a different variable, or just coloring something randomly when you have no player.
    return "|CFF000000"
endfunction

function GPCN takes player p returns string   //Short for Get Player Colored Name
    return ColorCodes[GetPlayerId(p)] + GetPlayerName(p) + "|r"         //Should be used when you want a colored player name.
endfunction

function GPCNU takes player p returns string //Short for Get Player Colored Name Unfinished (refering to the missing "|r".. could be used for rnadom things, I suppose. Like Mooglefrooglian the Nurb has fallen. "the Nurb" could be colored as well as the name.
    return ColorCodes[GetPlayerId(p)] + GetPlayerName(p)                    //Should be used when you want to add something else also colored the same as the name. I dont see much use, but hey, why not?
endfunction

function Init_Colors takes nothing returns nothing
    set ColorCodes[0] = "|cFFff0303"
    set ColorCodes[1] = "|cFF0042ff"
    set ColorCodes[2] = "|cFF1ce6b9"
    set ColorCodes[3] = "|cFF540081"
    set ColorCodes[4] = "|cFFfffc01"
    set ColorCodes[5] = "|cFFfeba0e"    //Using data from [url]http://www.wc3campaigns.net/showpost.php?p=596801&postcount=5[/url]
    set ColorCodes[6] = "|cFF20c000"  //Its apparently copied directly from the war3.mpq itself, who am I to argue?
    set ColorCodes[7] = "|cFFe55bb0"
    set ColorCodes[8] = "|cFF959697"
    set ColorCodes[9] = "|cFF7ebff1"
    set ColorCodes[10] = "|cFF106246"
    set ColorCodes[11] = "|cFF4e2a04"
endfunction

endlibrary
 
Last edited:
Level 16
Joined
Feb 22, 2006
Messages
960
JASS:
    function PlayerColorCode takes integer PlayerNumber returns string
            if PlayerNumber == 1 then
                return "|cffff0000"
            elseif PlayerNumber == 2 then
                return "|cff0000FF"
            elseif PlayerNumber == 3 then
                return "|cff00ffff"
            elseif PlayerNumber == 4 then
                return "|cff551A8B"
            elseif PlayerNumber == 5 then
                return "|cffffff00"
            elseif PlayerNumber == 6 then
                return "|cffFFA500"
            elseif PlayerNumber == 7 then
                return "|cff00FF00"
            elseif PlayerNumber == 8 then
                return "|cffFFC0CB"
            elseif PlayerNumber == 9 then
                return "|cff9C9C9C"
            elseif PlayerNumber == 10 then
                return "|cffADD8E6"
            elseif PlayerNumber == 11 then
                return "|cff006400"
            elseif PlayerNumber == 12 then
                return "|cff8b4513" 
            endif
            return "Failure to provide a number from 1-12."
    endfunction

this sys seems rly senseless, becuase it only returns the color code, there are othere systems which returns whole name + colorcode :O

JASS:
function TintUnit takes unit TempUnit, integer PlayerNumber, real Transparency returns nothing
        local real array RGB
        if PlayerNumber == 1 then
            set RGB[0] = 100
        elseif PlayerNumber == 2 then
            set RGB[2] = 100
        elseif PlayerNumber == 3 then
            set RGB[1] = 100
            set RGB[2] = 100
        elseif PlayerNumber == 4 then
            set RGB[0] = 32.2
            set RGB[1] = 10.16
            set RGB[2] = 54.3
        elseif PlayerNumber == 5 then
            set RGB[0] = 100
            set RGB[1] = 100
        elseif PlayerNumber == 6 then
            set RGB[0] = 100
            set RGB[1] = 64.45
        elseif PlayerNumber == 7 then
            set RGB[1] = 100
        elseif PlayerNumber == 8 then
            set RGB[0] = 100
            set RGB[1] = 75
            set RGB[2] = 79.3
        elseif PlayerNumber == 9 then
            set RGB[0] = 60.94
            set RGB[1] = 60.94
            set RGB[2] = 60.94
        elseif PlayerNumber == 10 then
            set RGB[0] = 67.58
            set RGB[1] = 84.38
            set RGB[2] = 89.84
        elseif PlayerNumber == 11 then
            set RGB[1] = 39.06
        elseif PlayerNumber == 12 then
            set RGB[0] = 54.3
            set RGB[1] = 26.95
            set RGB[2] = 7.42
        endif
        call SetUnitVertexColorBJ( TempUnit, RGB[0], RGB[1], RGB[2], Transparency )
        set TempUnit = null
    endfunction

maybe someone could use this one, but why should someone change the whole color of an unit, looks ugly in the most cases
 
Level 6
Joined
Apr 16, 2007
Messages
177
this sys seems rly senseless, becuase it only returns the color code, there are othere systems which returns whole name + colorcode :O



maybe someone could use this one, but why should someone change the whole color of an unit, looks ugly in the most cases

Use the PlayerColor[ i ] from my Utilities library instead, it is much more efficient.
+ It can do lots of other stuff too.

For the Tinting, I'ld highly recommend using a 2d array. You could Save all the nasty if then elses. Also it is bugged, you try to access uninitialized array fields.

Please fix this.
 
Level 6
Joined
Apr 16, 2007
Messages
177
Uninitialized array fields default to 0, 0.00, false, null, ... .

They default to "undefined behaviour", I thought. I will check it out and tell you my results.
EDIT: Hmh, true. You never end learning ; )

Here's my randomset macro:
JASS:
//! textmacro RandomSet takes NAME, TYPE, ELEMENTS, DEFAULT
private struct $NAME$
    $TYPE$ array random     [ $ELEMENTS$ ]
    $TYPE$ array random_left[ $ELEMENTS$ ]
    integer randoms_left = 0
    integer randoms      = 0
    static method create takes nothing returns $NAME$
        return .allocate()
    endmethod
    
    method get takes nothing returns $TYPE$
        local integer index
        local $TYPE$ result
        if .randoms_left > 0 then
            set .randoms_left = .randoms_left - 1
            set  index  = GetRandomInt( 0, .randoms_left )
            set  result = .random_left[ index ]
            set .random_left[ index ] = .random_left[ .randoms_left ]
            return result
        endif
        return $DEFAULT$
    endmethod
    
    method reset takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen i > .randoms
            set .random_left[ i ] = .random[ i ]
            set i = i + 1
        endloop
        set .randoms_left = .randoms
    endmethod
    
    method append takes $TYPE$ toappend returns nothing
        set .random[ .randoms ] = toappend
        set .randoms = .randoms + 1
        set .random_left[ .randoms_left ] = toappend
        set .randoms_left = .randoms_left + 1
    endmethod
endstruct
//! endtextmacro

You can use it to pop a random item from a set of predefined items. To reappend all the predefined items, use the reset method.
This is extremly useful when you want to distribute random items without having to fear an item would get picked twice, eg for an -all random mode or random name distribution.

Example usage:
JASS:
//! runtextmacro RandomSet( "heroset", "integer", "25", "H000" )

scope RandomMode initializer INIT
globals
    unit array Hero // The Player Heroes
    heroset heroes // The Heroes in the map
endglobals

function RandomMode takes nothing returns nothing
    local integer i = 0
    loop
        exitwhen i > MAX_PLAYER_SLOT
        set Hero[ i ] = CreateUnit( Players[ i ], heroes.get(), StartLocX[ i ], StartLocY[ i ], 270 )
        set i = i + 1
    endloop
endfunction

private function INIT takes nothing returns nothing
    set heroes = heroset.create()
    call heroes.append( 'H000' )
    call heroes.append( 'H001' )
    call heroes.append( 'H002' )
    call heroes.append( 'H003' )
    call heroes.append( 'H004' )
    call heroes.append( 'H005' )
    call heroes.append( 'U000' )
    call heroes.append( 'U001' )
    call heroes.append( 'U002' )
    call heroes.append( 'U003' )
    call heroes.append( 'U004' )
    call heroes.append( 'U005' )
    call heroes.append( 'N000' )
    call heroes.append( 'N001' )
    call heroes.append( 'N002' )
    call heroes.append( 'N003' )
    call heroes.append( 'N004' )
    call heroes.append( 'N005' )
    call heroes.append( 'O000' )
    call heroes.append( 'O001' )
    call heroes.append( 'O002' )
    call heroes.append( 'O003' )
    call heroes.append( 'O004' )
    call heroes.append( 'O005' )
endfunction
endscope
 
Last edited:
Level 17
Joined
Apr 27, 2008
Messages
2,455
JASS:
function GroupEnumUnitsOfTypeById takes group whichGroup, integer unitid, boolexpr filter returns nothing
        call GroupEnumUnitsOfType(whichGroup,UnitId2String(unitid),filter)
endfunction

Really simple, but I figured this way only a few days ago, I always thought that the function GroupEnumUnitsOfType did nothing, and we had Enum all the units for each players and then filter the unitid. (lame gui example)

So call me noob if you want, but i don't care :p

EDIT : Aha i know why Blizzard doesn't use it like that, UnitId2String is bugged, it always returns null , if you load a saved game.
 
Last edited:
Level 9
Joined
Nov 28, 2008
Messages
704
Vector Sums:

If your map is knockback heavy, and a unit can can have multiple knockbacks sending them off course at a time..for realisms sake, if you get thrown to the left, then a knockback hits you up instantly.. well.. according to physics, that would take one hell of a hit., or else a knockback to the up and right.

So, heres a vector sum calculation.

JASS:
    function VectorSum takes real f1, real a1, real f2, real a2, integer i returns nothing //f = force, a = angle
        local real resultant
        if a1 == a2 then
            set Dayta[i].Change = f1 + f2        //Roar. Same angle? Just give it one. Why do more calculations?
            set Dayta[i].Angle = a2 //Could also be a1.
            return
        endif
        if f1 == 0 or f2 == 0 then
            set Dayta[i].Change = f2        //Roar. No force? Just apply the one. Why do more calculations?
            set Dayta[i].Angle = a2                   //If your applying 0 force you're a retard. So, were using the second force and angle.
            return
        endif
        set resultant = SquareRoot(f1 * f1 + f2 * f2 - 2 * f1 * f2 * Cos(3.1415927- a2 + a1)) // The last part could be misunderstood. To get proper angles, you need to have your angle pointing in a compass direction. 0 is the best choice to avoid using half pi, etc.
        set Dayta[i].Change = resultant                                                                                               // to make this point in a compass direction, we minus angle one so that the whole triangle shifts onto the x axis. We are plussing it though becausr to get the angle opposite
        set Dayta[i].Angle = Acos((f2 * f2 - f1 * f1 - resultant * resultant) / ( -2 * f1 * resultant)) + a1       // our resultant, we do 180 - (a2 - a1) the minus signs cancel, we are left with - a2 + a1. This lines + a1 at the end simply shifts our imaginary triangle back to its original position.
        return
    endfunction

This is the function for my map, and it calculates the magnitude and direction, then sets it to one of my globals.. youll have to modify it for your map, Im too lazy, and I didnt want to be unefficient since Im going to use it so much to actually make two functions of the same thing and have them return the results, since to figure out the angle you need the side as well.

Or else you could do sine law, but then your running the risk of ambiguous case, etc..
 
Last edited:
Level 9
Joined
Nov 28, 2008
Messages
704
Rofl? Im sorry, are you aware what it does?

A vector is something with magnitude and direction. (ie, knocking back a unit x distance at angle a)

If you have a 10N force up, and a 10N force down, you should get 0 n net force total.

I think your talking about adding coordinates or something.

Edit: Oh, and a minor error.. -2 * f1 * f2 should be -2 * f1 * resultant.

Edit2: I was bored, so I spent 30 seconds making two images in paint which looks like XD.

Oh, and I made a better color for players functioon.. library thing.. wahtever back a page.
 

Attachments

  • Untitled.jpg
    Untitled.jpg
    20.9 KB · Views: 153
  • Untitled2.jpg
    Untitled2.jpg
    29 KB · Views: 201
Last edited:
Level 12
Joined
Apr 27, 2008
Messages
1,228
Rofl? Im sorry, are you aware what it does?

A vector is something with magnitude and direction. (ie, knocking back a unit x distance at angle a)

If you have a 10N force up, and a 10N force down, you should get 0 n net force total.

I think your talking about adding coordinates or something.

Edit: Oh, and a minor error.. -2 * f1 * f2 should be -2 * f1 * resultant.

Edit2: I was bored, so I spent 30 seconds making two images in paint which looks like XD.

Oh, and I made a better color for players functioon.. library thing.. wahtever back a page.

The way you do it you may need such a system, but it is rather complicated that way.
You store a vector by size and 1(2) angle(s). While the easiest way would be to represent it by two other vectors. Those are not just any vectors, but such that are parallel to the coordinate lines (the x and the Y (and the z) )
Like a vector that is 1 unit long and has a angle of 45 degrees with the x line, it can be represented with with two vectors, one parallel to the x line with size (Square Root of 2)/2 and one parallel to the y line, perpendicular to the first one with size (also)( Square root of 2)/2.
Now, if you want to sum up two vectors all you have to do is sum independently the x vectors of both and the y vectors of both.
If we sum up the vector from my example (1 unit long 45 degrees) with another of the same length and direction: we get:
New x = (Square Root of 2)/2 + (Square Root of 2)/2 = Square root of 2
New y = (Square Root of 2)/2 + (Square Root of 2)/2 = Square root of 2
The size of their sum(the new vector) will be 2 and will point at 45 degrees(what a surprise).
 
Level 9
Joined
Nov 28, 2008
Messages
704
That would also work, but Im pretty sure what I have currently also works.

You could also figure out the individual x and y components with sin y/hypotenuse, and cos x/hypotenuse.

I think yours might take slightly less calcuating power though.. Ill take a look into it.

I find mine slightly less complicated to do though... yours requires adding the 2 x components and 2 y components, then figuring out an angle by Atan while mine is just cosine law.

Although... your is probably easier, thinking on it :p. Just, after all the time I spent figuring out my 180 - a2 + a1, I dont feel inclined to change it.
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
That would also work, but Im pretty sure what I have currently also works.

You could also figure out the individual x and y components with sin y/magnitude, and cos x/magnitude.

I think yours might take slightly less calcuating power though.. ill take a look into it.

Nobody said yours did not work, but it just complicates a rather simple task.

slightly? :p
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
Both methods require the storage of 2 variables.
Storing the size and angle causes you to have a ridiculously complicated(compared to the other method) calculation. It is more cpu intensive with 3 comparisons running most of the time and a really long line of calculations.
You mean that when you want to use the vector, you have to calculate its size from the two vectors you have, suppose so. But this is just another pointless complication. Wc3 is running with a 3d coordinate system. So if you want to apply some vector you directly apply it to the unit's x and unit's y(or only a partition of it).
For instance the vector from my example x=(Square root of 2) /2 y==(Square root of 2) /2
You want to apply it to some unit that is at coordinates (521, -730) - you just add the above: (521+(Square root of 2) /2,-730+(Square root of 2) /2)
P.s. you have an error in the
JASS:
   if f1 == 0 or f2 == 0 then
            set Dayta[i].Change = f2 //Roar. No force? Just apply the one. Why do more calculations?
            set Dayta[i].Angle = a2 //If your applying 0 force you're a retard. So, were using the second force and angle.
            return
        endif
part.
Should be:
JASS:
   if f1 == 0 then
            set Dayta[i].Change = f2 
            set Dayta[i].Angle = a2
            return
        endif
   if f2 == 0 then
            set Dayta[i].Change = f1 
            set Dayta[i].Angle = a1 
            return
        endif
or anything else that works.
But it is just better to use something like:
JASS:
struct Vector
 private real x
 private real y
 static method create takes real q,real w returns Vector
     local Vector data=Vector.allocate()
     set data.x=q
     set data.y=w
     return data
 endmethod
 public static method Sum takes Vector q,Vector w returns Vector
     local Vector data=Vector.create(q.x+w.x,q.y+w.y)
     return data
 endmethod
 method add takes Vector q returns nothing
    set this.x=this.x+q.x
    set this.y=this.y+q.y
 endmethod
 method GetX takes nothing returns real
   return this.x
 endmethod
 method GetY takes nothing returns real
   return this.y
 endmethod
endstruct

And anywhere you can just:
JASS:
local Vector a=Vector.create(246,321)
local Vector b=Vector.create(754,679)
local Vector c=Vector.Sum(a,b)//c = (1000,1000)
call a.add(c)//a=(1246,1321)
call SetUnitX(some_unit,a.GetX())
call SetUnitY(some_unit,a.GetY())
//You can always add just a part of the vector
call SetUnitX(some_other_unit,c.GetX()/5)
call SetUnitY(some_other_unit,c.GetY()/5)

Note that the above uses vJass and Vectors must be destroyed.
 
Last edited:
Level 9
Joined
Nov 28, 2008
Messages
704
Very nice system.

Alas, I made the vector calculation for my knockback system. It needs to have one vector at a time to move.

It will move in that vector its degrees. I am not just adding a unit's x and y's once, in which case yours would basically own all.

And my error there will never happen in my map, I never plan on adding 0 force :). In a case where anything could happen, your swould work better though.
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
Where have i said that you need to add to the unit's x and y only once. On the contrary, I said that if you need, you can add a small partition(several times or whatever suits you).
Like in the bottom of my previous post.
It is not my system or anything, it is just something I wiped up in a few minutes, especially for that post.
If you intend not to add null forces why did you add the "or f2 == 0" part?
It is still better to be on the safe side(with no glitches).
 
Level 9
Joined
Nov 28, 2008
Messages
704
I agree, safe side is better - and I added that because I dont intend to add a null force, but Im viewing it as a force being added to a force already being exerted on my units.

My units CAN be 0, which is why I added it.

And I will never add a null force, so..

Yes, on the safe side is better anyways though. Thanks again.

And yes, Im sorry, I was rushed, you can use your system much more effectively my adding the x and y components of the force and reconstructing the angle from the new force. It would require much less calculating power.

A rough copy would look something like this:

JASS:
function Vectorsum takes real f1, real a1, real f2, real a2 returns real

    local real af
    local real ff
    local real x
    local real y   //x and y being the individual components of the new vector

    set x = Cos(a1) * f1 + Cos(a2) * f2
    set y = Sin(a1) * f1 + Sin(a2) * f2
    set af = Atan(y/x)
    set ff = SquareRoot(x * x + y * y)

    //return af or ff.. or put them in variables.. or copy the function twice or something, return af once and ff in the other...

endfunction
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
:)

Global Variables should be best.

I posted vJass seeing you used it.

P.s. Recently I have become obsessed with performance :p
If only more of the Game Developers were like me ;)
 
Level 9
Joined
Nov 28, 2008
Messages
704
Finished (using something like 60% of the calculating power?)

JASS:
globals
    real af
    real ff    //angle final and force final
endglobals


function VectorSum takes real f1, real a1, real f2, real a2 returns nothing

    local real x
    local real y   //x and y being the individual components of the new vector

    if f1 == 0 then
         set ff = f2
         set af = a2
         return
     elseif f2 == 0 then    //Dividing by 0 usually results in the end of existence as we know it.
         set ff = f1
         set af = a1
         return
     endif

    set x = Cos(a1) * f1 + Cos(a2) * f2
    set y = Sin(a1) * f1 + Sin(a2) * f2

    set af = Atan2(y, x)
    set ff = SquareRoot(x * x + y * y)

endfunction

(Oh, and to anyone using this, its in radians)

Heres cosine law as well. Probably less efficient... but it works. Unsure about the above. Uses the same globals.

JASS:
globals
    real af
    real ff    //angle final and force final
endglobals

function VectorSum takes real f1, real a1, real f2, real a2 returns nothing //f = force, a = angle
    local real resultant
    if f1 == 0 then
        set ff = f2
        set af = a2
        return
    elseif f2 == 0 then         //Less calculations for something that will probably happen a lot (0 force on one or the other)
        set ff = f1
        set af = a1
        return
    endif
    set resultant = SquareRoot(f1 * f1 + f2 * f2 - 2 * f1 * f2 * Cos(3.1415927- a2 + a1)) // The last part could be misunderstood. To get proper angles, you need to have your angle pointing in a compass direction. 0 is the best choice to avoid using half pi, etc.
    set ff = resultant // to make this point in a compass direction, we minus angle one so that the whole triangle shifts onto the x axis. We are plussing it though becausr to get the angle opposite
    set af = Acos((f2 * f2 - f1 * f1 - resultant * resultant) / ( -2 * f1 * resultant)) + a1 // our resultant, we do 180 - (a2 - a1) the minus signs cancel, we are left with - a2 + a1. This lines + a1 at the end simply shifts our imaginary triangle back to its original position.
    return
endfunction
 
Last edited:
Level 18
Joined
Oct 18, 2007
Messages
930
Useful vJass functions

IsPointWalkable func
JASS:
library CheckSystem initializer Init

    globals
        private constant integer I_ID = 'sehr'
        private item I = null
    endglobals

    function IsPointWalkable takes real x, real y returns boolean
        call SetItemPosition(I, x, y)
        return GetItemX(I) == x and GetItemY(I) == y
    endfunction

    private function Init takes nothing returns nothing
        set I = CreateItem(I_ID, 0, 0) 
        call SetItemVisible(I, false)
    endfunction
endlibrary
 
Last edited:
Level 14
Joined
Nov 23, 2008
Messages
187
You forgot something...

JASS:
    private function Init takes nothing returns nothing
        // call CreateItem(I_ID, 0, 0)
        set I = CreateItem(I_ID, 0, 0)
        call SetItemVisible(I, false)
    endfunction

And why don't use standard function IsTerrainPathable for this?

JASS:
// teh inline friendly
function IsPointWalkable takes real x, real y returns boolean
  return not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
endfunction
 
Level 18
Joined
Oct 18, 2007
Messages
930
You forgot something...

JASS:
    private function Init takes nothing returns nothing
        // call CreateItem(I_ID, 0, 0)
        set I = CreateItem(I_ID, 0, 0)
        call SetItemVisible(I, false)
    endfunction

And why don't use standard function IsTerrainPathable for this?

JASS:
// teh inline friendly
function IsPointWalkable takes real x, real y returns boolean
  return not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
endfunction

:eek: forgot to do set I = ...

And this is more accurate than the Terrain Pathable. And this applies to doodads, buildings, destructables, walls, but not units. It applies to unwalkable terrain and outside map. So it is pretty nifty ;)
 
Level 16
Joined
Jun 9, 2008
Messages
734
IsPointWalkable func
JASS:
library CheckSystem initializer Init

    globals
        private constant integer I_ID = 'sehr'
        private item I = null
    endglobals

    function IsPointWalkable takes real x, real y returns boolean
        call SetItemPosition(I, x, y)
        return GetItemX(I) == x and GetItemY(I) == y
    endfunction

    private function Init takes nothing returns nothing
        set I = CreateItem(I_ID, 0, 0) 
        call SetItemVisible(I, false)
    endfunction
endlibrary

it's looks like vexorian checkpathability()??
WC3Jass.com :: View script - CheckPathability (By Vexorian)
 
Level 7
Joined
Oct 21, 2008
Messages
234
IsAngleBetweenAngles(real match, real max, real min)

IsAngleBetweenAngles(real match, real max, real min)
by Zacharias

This is a function to check if an angle is between two other angles. It returns true if max>match>min.
The function it self is not complex, but full of math :wink: added some comments for those who want to study this function :wink:

JASS:
function IsAngleBetweenAngles takes real Match, real Max, real Min returns boolean
    // note: all operations do only modify the interval of match, min and max

    // set match, max, min to interval [0,2*PI)
    set Match = ModuloReal(Match,2*bj_PI)
    set Max = ModuloReal(Max,2*bj_PI)
    set Min = ModuloReal(Min,2*bj_PI)
    
    // bring min under match, even if min gets negative
    // min e (-2*PI,2*PI)
    loop
        exitwhen Match >= Min
        set Min = Min - 2*bj_PI
    endloop
    // bring max over min (max is positive (modulo))
    // max > min, max e [0,2*PI)
    loop
        exitwhen Max > Min
        set Max = Max + 2*bj_PI
    endloop
    // as min is over -2*PI, max cant get negative through the following function
    loop
        exitwhen (Max-Min) < 2*bj_PI
        set Max = Max - 2*bj_PI
    endloop
    
    // result:
    // max > min
    // min e (-2*PI,2*PI)
    // max e [0,2*PI)
    // match e [0,2*PI)

    return (Max>=Match)
endfunction
 
Level 6
Joined
Apr 16, 2007
Messages
177
IsAngleBetweenAngles(real match, real max, real min)
by Zacharias

This is a function to check if an angle is between two other angles. It returns true if max>match>min.
The function it self is not complex, but full of math :wink: added some comments for those who want to study this function :wink:

I have another way that should be more efficient. It turns the whole circle by a few degree, making the whole thing a lot easier to evaluate.
JASS:
function IsAngleBetweenAnglesSJ takes real whichangle, real min, real max returns boolean
  if whichangle > max then
    return ( min > max and min < whichangle )
  endif
  set min = min - max
  set whichangle = whichangle - max
  
  return (min<whichangle and whichangle<0)
endfunction

EDIT: Typo
 
Last edited:
Top