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

Small Code Snippets

Wait, so "f" is that facing angle and "a" determines how wide the cone is?

Yeah. Think as center point as a unit(whit it's facing) and the 'a' as the half of the complete cone angle. I had designed this ability for a hero that did damage to units in front of him.

Nice. What about a 3D version?

just make 2 axis (e.g: AxiXY and AxiXZ) and check it for both axis.
 
But it would be much easier to use and slightly quicker if you made that in just one function. You might as well do it (if it's like you say it wouldn't exactly be hard or time-consuming).

well I'll think about it. Since a generic function needs more considerations, like the 3rd axi.
 
Main problem with that being 2 Cos calls and the angle limitation for a (0-pi/4). I had posted a similiar script that used an angle instead of the coordinates, but covered all angles. It's somewhere in this thread...

Cosine is a very fast function, specially in newer processors that have the SSE2 structure. Second the angle isn't limited. You can even insert negative angles and angles that exceed 2*pi. The cone angle is just 2 times the angle you insert in.

Perhaps you should check how the math in it works, before commenting anything.
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
I took a long look at your function and I must say that using trigonometrical function in this case is pretty smart. It gets rid of all those crap, like "negative angle", "more than 2 PI" etc. I tried to make a IsUnitInCone function myself, but it has like 10++ lines... :D
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
[vJASS] GetBounceVector

Lulz. I made this little function in vJASS, lul.


JASS:
globals
    private constant location l = Location(0., 0.)
    private constant location l2 = Location(0., 0.)
    private constant real SR = 1.//The accuracy. Higher values means less accuracy and setting it to 0 will make the function fail.
endglobals

struct vector
    real xvel
    real yvel
    real zvel
    
    static method GetBounceVector takes real x, real y, real xvel, real yvel, real zvel, real re returns vector
        local real vx
        local real vy
        local real vz
        local real px
        local real py
        local real pz
        local vector v = vector.allocate()
        call MoveLocation(l, x-SR, y)
        call MoveLocation(l2, x+SR, y)
        set vx = GetLocationZ(l) - GetLocationZ(l2)
        call MoveLocation(l, x, y-SR)
        call MoveLocation(l2, x, y+SR)
        set vy = GetLocationZ(l) - GetLocationZ(l2)
        set vz = (xvel*vx + yvel*vy + zvel*SR)/(vx*vx + vy*vy + SR*SR)
        set px = vx*vz
        set py = vy*vz
        set pz = SR*vz
         
        set v.xvel = (xvel - px) - px*re
        set v.yvel = (yvel - py) - py*re
        set v.zvel = (zvel - pz) - pz*re
        return v
    endmethod
endstruct
It just returns a vector with the velocities an entity should have after hitting the ground. It takes the coordinates for where your entity hits the ground (real x, real y), the velocities it has (real xvel, real yvel, real zvel), and it's restitution (real re). For those who don't know what restitution is, it's just how bouncy the entity is. It goes from 0-1, 0 means it doesn't bounce and 1 means it will bounce out from the ground with the same speed, but in another direction.
 
A bit complicated, but I guess that's needed for the terrain height checking...

tbh anyone who would do anything this function could be used in would just code it themselves...

hmm, too bad that function uses GetLocationZ, because it causes desyncs with some terrain changes and abilities.
 
Terrain deformations caused by abilities are sync'd. Otherwise, I don't see why anyone'd want to make a terrain deformation for just one player - wouldn't it desync when units walked over it and such anyway?

I heard Stomp, thunderclap and some other caused desynquing. However, I haven't tested it myself.
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
That's stupid... I guess dynamic terrain defomations (like waves and ripples) aren't sync'd right either? Meh. People generally wouldn't use something that needed bounce vectors and abilities like stomp in the same map...

Why wouldn;t hey :p

And if they do, they can just sync the values from this function before they do the actual bounce.
 
Level 11
Joined
Apr 29, 2007
Messages
826
mh, simple script to get the last target of any unit. Just needed this and thought someone might think it's useful.
JASS:
library_once GUT initializer Init

    globals
        private widget array saved
    endglobals

    function GetUnitCurrentTarget takes unit u returns widget
        return saved[GetHandleId(u)-0x100000]
    endfunction
    
    private function Flush takes nothing returns nothing
        set saved[GetHandleId(GetTriggerUnit())-0x100000] = null
    endfunction
    
    private function Work takes nothing returns nothing
        set saved[GetHandleId(GetTriggerUnit())-0x100000] = GetOrderTarget()
    endfunction

    private function Init takes nothing returns nothing
        local trigger trg = CreateTrigger()
        
        call TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
        call TriggerAddAction(trg, function Work)
        
        set trg = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_DEATH)
        call TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
        call TriggerAddAction(trg, function Flush)

        set trg = null
    endfunction

endlibrary
 
Last edited:
Level 11
Joined
Apr 29, 2007
Messages
826
You should use hashtable for this as something like this doesn't need to be quick and the current form is quite error prone.

Yeah, I first used a hashtable. But I somehow dislike using alot of hashtables, so I used arrays instead.
well..
JASS:
library_once GUT initializer Init

    globals
        private hashtable hash
    endglobals

    function GetUnitCurrentTarget takes unit u returns widget
        return LoadWidgetHandle(hash, GetHandleId(u), 0)
    endfunction

    private function Flush takes nothing returns nothing
        call FlushChildHashtable(hash, GetHandleId(GetTriggerUnit()))
    endfunction

    private function Work takes nothing returns nothing
        call SaveWidgetHandle(hash, GetHandleId(GetTriggerUnit()), 0, GetOrderTarget())
    endfunction

    private function Init takes nothing returns nothing
        local trigger trg = CreateTrigger()

        call TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
        call TriggerAddAction(trg, function Work)

        set trg = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_DEATH)
        call TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
        call TriggerAddAction(trg, function Flush)

        set trg = null
        set hash = InitHashtable()
    endfunction

endlibrary
 
Last edited:
Level 6
Joined
Apr 16, 2007
Messages
177
Shouldn't you also add something to clear the target once the unit gets a non/point target order?
Else I could issue the unit to stop and it would still have a target for the code...

What might work too would be changing the event from ISSUED_TARGET_ORDER to ISSUED_ORDER (as far as I remember there was such an event)

cu, Serra
 
well here's another snippet:
JASS:
////////////////////////////////////////////////////
// function Round
////////////////////////////////////////////////////
//Function: Rounds a real to its nearest integer
//
//Explanation: takes a real number, multiplies it by 2
//and takes the integer part, then rests the old 
//number's integer part. Example:takes 0.8; 0.8*2 = 1.6, 
// integer part of 1.6 = 1, - the integer part of 0.8
// that is 0, returns 1 - 0 = 1, so 0.8 rounds to 1
/////////////////////////////////////////////////////

function Round takes real q returns integer
return R2I(q*2.00) - R2I(q)
endfunction

oh and cJass:
JASS:
#define inline_Round(r) = R2I(r*2.00) - R2I(r);
//or
int Round(float r) { return R2I(r*2.00) - R2I(r); }

it's a "fast"(type casting is already terrible) round function. However it only rounds to integers.
 
Level 16
Joined
Feb 22, 2006
Messages
960
hm why multiplying it by 2?... that way would be shorter:
JASS:
function Round takes real q returns integer
     return R2I(q+0.5)
endfunction

so lets say we have 0.8 .... it would be 0.8+0.5 and in integer 1 because 1,3....
if we would have 0.3+0.5 the integer would be 0. 0.3 rounded is 0.
 
Level 9
Joined
Nov 28, 2008
Messages
704
I just found cJass like a week ago, still loving it up.

Also, for those who may not know (it's a relatively unused trick), you can disable normal wc3 lighting with:

JASS:
call SetDayNightModels("", "")

You then can just use light models, like the one found on the torch item, to brighten things. It creates a really neat effect, and I'm using it in my Impossible Survival map.

http://img10.imageshack.us/img10/5572/76882351.jpg

Just can't go wrong with custom lighting in WC3.

Here's a basic MDL lgith. It is self explanatory how to change it pretty much. Don't forget to change to MDX.

Note: If you turn off lighting any time other than init, it tends to have a dleay of a second or two before the terrain turns black. Never figured out why.. so be sure to use it at init if you want accurate results. NOT at 0.01 seconds of gameplay.
 

Attachments

  • BaseLight.mdl
    503 bytes · Views: 113
hm why multiplying it by 2?... that way would be shorter:
JASS:
function Round takes real q returns integer
     return R2I(q+0.5)
endfunction

so lets say we have 0.8 .... it would be 0.8+0.5 and in integer 1 because 1,3....
if we would have 0.3+0.5 the integer would be 0. 0.3 rounded is 0.

yeah, well they were old functions, but appears this is better.
 
Level 14
Joined
Nov 23, 2008
Messages
187
hm why multiplying it by 2?... that way would be shorter:
JASS:
function Round takes real q returns integer
     return R2I(q+0.5)
endfunction

so lets say we have 0.8 .... it would be 0.8+0.5 and in integer 1 because 1,3....
if we would have 0.3+0.5 the integer would be 0. 0.3 rounded is 0.

What about negative values? They are rounded incorrectly with this function.
For example, q = -0.9, so rounded value should be -1, but R2I(-0.9+0.5) returns 0. Even if q = -1,4, it is rounded to 0 too.
 
Level 9
Joined
Nov 28, 2008
Messages
704
I was talking to someone, and they mentioned they didn't know a proper way to tell how many players are in game. So her eis just a simple example that detects people playing that aren't computers.

Written in pyJass and cJass.

JASS:
function CountNumberOfPlayers takes nothing returns int:
    int i = 0
    int numberofplayers = 0
    loop:
        exitwhen i > 11
        if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(i)) == MAP_CONTROL_USER:
            numberofplayers++
        i++
    return numberofplayers

Dont forget cj_types.j (which I reccomend including in map header always anyways)
 
Level 9
Joined
Nov 28, 2008
Messages
704
A project I spent a week on. I always wanted to make a preprocessor for WC3, and it was accomplished. It lets you not have to endblock anything, like the python language.

JASS:
library MiscFunctions:
    function Add takes int a, int b returns int:
        return a + b

Is a perfectly valid example.

JASS:
        if spell(ID).Type == NOTARGET:
            IssueImmediateOrder(FakeHero, spell(ID).Order)

Im relying on cJass for set/call removal, but whatever.

It isnt incredibly useful, but it is rather nice or so I found. I wrote it in Python, the same week I found the language because it is such an amazing syntax. It's just too bad I'm too lazy to add in range(x) and things.
 
Sorry dude, I fixed it now XD

Edit:
omg, python Jass now? what's next? an ASM x86 Jass?

let's try to add functions in common Jass, vJass and cJass. I doubt anyone will use somthing different. Starting by ZINC and other freaky weird experiments around to dizzy ppl more.
Seconded. Why the hell do we need to be able to code JASS in every language?
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
I think vJass is in a desperate need for a brainfuck syntax. It'll make jassers really happy.

I totaly agree.
But whitespace would be more readable.
Maybe a new language - the combination of brainfuck and whitespace.
Every working block of code would be worthy of a screenshot.
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
Lol, syntax highlighting for whitespace... :p. Ok, enough spamming, guys, PurplePoot will be mad at us when he sees this (so we have about two years to relax until then :p).

P.S. Btw, Anachron, your link appears to be broken.

EDIT: Yeah, Lolcode pwns! I would want Lolcode syntax even more than brainfuck or whitespace.
 
Level 9
Joined
Nov 28, 2008
Messages
704
I would use lolcode as well.

Here's a simple "pool" cJass template. It lets you store a list of things, and randomly get them. It lets you call a function when it's empty.

JASS:
function interface Pool_EmptyFunction takes nothing returns nothing
#include "cj_types.j"
#define CreatePool(name, type, endfunction) = 
{
    struct name
        static type array List
        static int Count = -1
        static Pool_EmptyFunction EF = endfunction
        static method Add takes type data returns nothing
            .Count++
            List[.Count] = data
        endmethod
        static method Get takes nothing returns type
            int rand = GetRandomInt(0, .Count)
            type selection = List[rand]
            List[rand] = List[.Count]
            .Count--
            if .Count < 0 then
                .EF.execute()
            endif
            return selection
        endmethod
    endstruct
}

An example usage being:

JASS:
CreatePool(names, string, 0)

function Trig_Init_Test_Actions takes nothing returns nothing
    names.Add("Lol")
    names.Add("Frog")
    names.Add("Bear")
    BJDebugMsg(names.Get())
endfunction

//===========================================================================
function InitTrig_Init_Test takes nothing returns nothing
    set gg_trg_Init_Test = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Init_Test, function Trig_Init_Test_Actions )
endfunction

I personally find that much, much cleaner than textmacros. But that's just me.
 
Last edited:
Level 9
Joined
Nov 28, 2008
Messages
704
Yeah, I just rememberd I forgot to post the converted code. My bad. Fixed. (it was 3 AM anyways. >.>)

How about a recycler template too, while Im at it? A simple template to recycle just about anything.

JASS:
#include "cj_types.j"
#define CreateRecyclable(name, type, creator, cleaner) =
{
    scope name##RecyclerScope initializer Init
        globals
            private hashtable Hash
        endglobals
        private function Init takes void returns void
            Hash = InitHashtable()
        endfunction
        struct name
            bool Used
            type Recyclee
            static method Get takes void returns type
                thistype r = thistype.create()
                if not r.Used then
                    r.Recyclee = creator
                    r.Used = true
                    SaveInteger(Hash, GetHandleId(r.Recyclee), 0, int(r))
                endif
                return r.Recyclee
            endmethod
            static method Give takes type r returns void
                cleaner
                thistype(LoadInteger(Hash, GetHandleId(r), 0)).destroy()
                r = null
            endmethod
        endstruct
    endscope
}
CreateRecyclable(groups, group, CreateGroup(), GroupClear(r))
CreateRecyclable(timers, timer, CreateTimer(), PauseTimer(r))

Sample usage using the two created:

JASS:
local timer t = timers.Get()
timers.Give(t)

The concept can be applied to anything, even recycling of units, where your code would be:

JASS:
CreateRecyclable(dummys, unit, CreateUnit(Player(0), id, 0, 0, 0), HideUnit(r))

I need to test the code, but it seems sound.

Rounding to a base:

JASS:
#define Round(num) = Round(num, 1)
    real Rou##nd(real num, real base){
        num /= base
        if num < 0:
            num -= .5
        else:
            num += .5
        return R2I(num) * base}

If you want something rounded to the nearest .1, base is .1 If you want the nearest tens, like 111 to be rounded to 110, base is 10. Simple.
 
Last edited:
Level 11
Joined
Apr 29, 2007
Messages
826
Simple function to check if a path is blocked by another unit.

JASS:
library IsPathBlocked

        // Configurables
    globals
        private constant real CHECK_DISTANCE = 64
        private constant real CHECK_RADIUS = 128
    endglobals

    globals
        private group check = CreateGroup()
        public unit Target = null
    endglobals
    
    private function CheckPath takes real x, real y, code func returns boolean
        call GroupEnumUnitsInRange(check, x, y, CHECK_RADIUS, Filter(func))
        set Target = FirstOfGroup(check)
        
        return Target != null
    endfunction
    
    function IsPathBlocked takes real x1, real y1, real x2, real y2, code func returns boolean
        local real distance = SquareRoot((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
        local real angle = Atan2(y2-y1, x2-x1)
        
        local real sin = Sin(angle)
        local real cos = Cos(angle)
        
        loop
            exitwhen distance <= 0
            
            if CheckPath.evaluate(x1, y1, func) then
                return true
            endif
            
            set x1 = x1+CHECK_DISTANCE*cos
            set y1 = y1+CHECK_DISTANCE*sin
            
            set distance = distance-CHECK_DISTANCE
        endloop
        
        return false
    endfunction
    
endlibrary
 
Module for structs (uses Table) that easily store, load and remove struct instances.


JASS:
//|**************************************************************************
//|    TableMacros v. 1.0
//|     by Anachron
//|
//|     Implement this module into your struct to use it.
//|
//|     New methods:
//|     ------------
//|     
//|     private static method initTable takes nothing returns nothing
//|     > Initializes the Table.
//|     
//|     public method save takes nothing returns nothing
//|     > Saves the instance.
//|     
//|     public method remove takes nothing returns nothing
//|     > Kills the instance, using Table.flush before the destroy() call.
//|     
//|     public static method load takes $KTYPE$ id returns thistype
//|     > Loads the instance from the InstanceTable.
//|     
//|**************************************************************************
globals
    constant boolean TM_DISPLAY_NOTICES = false
endglobals

module TableMacros requires Table
    private static Table INSTANCES = 0
    private integer ID = 0   

    private static method onInit takes nothing returns nothing
        set thistype.INSTANCES = Table.create()
    endmethod

    public method save takes nothing returns nothing
        set thistype.INSTANCES[.ID] = integer(this)
        debug if TM_DISPLAY_NOTICES then
            debug call BJDebugMsg("TableMacros_NOTICE: [|cffffcc00$TNAME$|r] SAVED (|cffffcc00Key|r: " + I2S(.ID) + " | |cffffcc00ID|r: " + I2S(integer(this)) + " )")
        debug endif
    endmethod
    
    public method remove takes nothing returns nothing
        debug if TM_DISPLAY_NOTICES then
            debug call BJDebugMsg("TableMacros_NOTICE: [|cffffcc00$TNAME$|r] KILLED (|cffffcc00Key|r: " + I2S(.ID) + " | |cffffcc00ID|r: " + I2S(integer(this)) + " )")
        debug endif
        call thistype.INSTANCES.flush(.ID)
        call .destroy()
    endmethod
    
    public static method load takes integer id returns thistype
        debug if TM_DISPLAY_NOTICES then
            debug call BJDebugMsg("TableMacros_NOTICE: [|cffffcc00$TNAME$|r] LOADED (|cffffcc00Key|r: " + I2S(id) + " | |cffffcc00ID|r: " + I2S(integer(thistype(thistype.INSTANCES[id]))) + " )")
        debug endif
        return thistype(thistype.INSTANCES[id])
    endmethod
endmodule
 
Top