HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

NEW! JASS function pack, please contribute

08-04-2003, 11:18 PM#76
dataangel
@Peppar: Whoa... using this to create structs didn't even occur to me...

Also, found an interesting snippet in the common.j file:

Code:
// Not currently working correctly...
constant native AbilityId                   takes string  abilityIdString   returns integer
constant native AbilityId2String            takes integer abilityId         returns string

Has anyone tested these to see if they work at all?

And check out this useful stuff that doesn't show in GUI:

Code:
constant native IsUnitInRange       takes unit whichUnit, unit otherUnit, real distance returns boolean
constant native IsUnitInRangeXY     takes unit whichUnit, real x, real y, real distance returns boolean
constant native IsUnitInRangeLoc    takes unit whichUnit, location whichLocation, real distance returns boolean

@Peppar: I noticed that there are functions for testing if destructibles and item are invulnerable, but not one for units. Perhaps converting a unit to item type and and checking if the resulting item is invulnerable will work? That'd be another cool thing to add to function pack. Also, what about converting a special effect type to a unit type, and trying to play its animations? Currently, if you make a special effect with a unit model, there's no way to play its different animations.
08-04-2003, 11:39 PM#77
Peppar
I have tried to convert an item to a unit and use the Change
Vertex Color on it, but it didn't work. I suspect there might be
some variable-type checking at work, which might make things
like IsUnitInvulnerable impossible :/. I'll give it a try though.

Ah and I love finding new functions in common.j :P. Just like an
old junkyard, you'll never know what they go for. I haven't tried
the Ability-functions though. It would be really neat if they
worked.

EDIT: Latest news on the Handle issue. All variables which use
handles seem to share the same array of IDs.

And MY GOD is Jass2 leaking memory like a friggin raincloud. I may
have programmed things wrong, but even as the removed units
IDs were recycled, new units got only higher and higher IDs (I
removed all units shortly after they spawned, so there weren't
more than, say, 5 units on the map at once.)

This might be just the tool to see where maps are leaking
memory though, if it was just me doing things the wrong way.
:ggani:
08-05-2003, 01:29 AM#78
dataangel
Try seeing what happens when it reaches the highest possible id =)
08-05-2003, 08:16 PM#79
Starcraftfreak
I think people don't look enough at common.j. In fact, apart from GUI triggers, you don't need any blizzard.j functions. They are all based upon common.j functions. Common.j holds only function headers, the rest is (I think, it has to be that way) hardcoded in game.dll. Some of you might have discovered that Blizzard.j just contains three types of functions:
1) Function that are not necessary (:P Blizzard):
Code:
function DestroyEffectBJ takes effect whichEffect returns nothing
    call DestroyEffect(whichEffect)
endfunction
In my opinion such a function must waste time.

2) Utility Functions, that are needed for simplicity in the TriggerEditor:
Code:
function AddSpecialEffectLocBJ takes location where, string modelName returns effect
    set bj_lastCreatedEffect = AddSpecialEffectLoc(modelName, where)
    return bj_lastCreatedEffect
endfunction
A professional scripter maybe uses the common.j function AddSpecialEffectLoc instead and stores the returned data into a variable (instead of assigning the last created special effect to a variable). For other functions, the returned value is in some case completely unnecessary so the professional scripter doesn't stores the returned value anywhere and saves memory.

3) Functions that do multiple actions (we are developing the same functions in this thread) for advanced usage:
Check blizzard.j for ReplaceUnitBJ. I don't want to post it now, it's huge.


Additionally, I have created some extented AddSpecialEffect functions:

Code:
function AddSpecialEffectEx takes string modelName, real x, real y, real duration returns nothing
    local effect fx
    local timer t
    local real timeRemaining

    set fx = AddSpecialEffect(modelName, x, y)
    set t = CreateTimer()
    call TimerStart(t, duration, false, null)
    loop
        set timeRemaining = TimerGetRemaining(t)
        exitwhen timeRemaining <= 0
        if (timeRemaining > 2.0) then
            call TriggerSleepAction(0.1 * timeRemaining)
        else
            call TriggerSleepAction(0.10)
        endif
    endloop
    call DestroyTimer(t)
    call DestroyEffect(fx)
endfunction

function AddSpecialEffectLocEx takes string modelName, location where, real duration returns nothing
    local effect fx
    local timer t
    local real timeRemaining

    set fx = AddSpecialEffectLoc(modelName, where)
    set t = CreateTimer()
    call TimerStart(t, duration, false, null)
    loop
        set timeRemaining = TimerGetRemaining(t)
        exitwhen timeRemaining <= 0
        if (timeRemaining > 2.0) then
            call TriggerSleepAction(0.1 * timeRemaining)
        else
            call TriggerSleepAction(0.10)
        endif
    endloop
    call DestroyTimer(t)
    call DestroyEffect(fx)
endfunction

function AddSpecialEffectTargetEx takes string modelName, widget targetWidget, string attachPointName, real duration returns nothing
    local effect fx
    local timer t
    local real timeRemaining

    set fx = AddSpecialEffectTarget(modelName, targetWidget, attachPointName)
    set t = CreateTimer()
    call TimerStart(t, duration, false, null)
    loop
        set timeRemaining = TimerGetRemaining(t)
        exitwhen timeRemaining <= 0
        if (timeRemaining > 2.0) then
            call TriggerSleepAction(0.1 * timeRemaining)
        else
            call TriggerSleepAction(0.10)
        endif
    endloop
    call DestroyTimer(t)
    call DestroyEffect(fx)
endfunction

As you might know, if you are creating many special effects, you will soon get a big slowdown. Keeping track of all created special effects is also difficult and messy. If you use my functions, and specify a reasonable amount of time (about 0.1 sec more than the effect needs), you can save a lot of memory and improve the performance.

I played around a bit and found out that after about 750 created Special Effects, the game performance slows down from about 41 fps to 10 fps. Plus after around 800 created Special Effects, weird graphic bugs appear (check the attachment, this should be a Mountain King).
When using my function, it goes down to 21 fps while displaying the effect, but goes up to 41 after the duration is over.
Some of you might notice that I copied most of the blizzard.j function PolledWait for the code to wait until the time is over. But instead of calling it and accessing blizzard.j globals, I copied it and repleaced the references to the globals to values. In my opinion this save some memory and performance.
08-06-2003, 12:23 AM#80
dataangel
@SCFreak: The first version of AddSpecialEffectLoc() you show takes a point -- but then in your AddSpecialEffectEx you pass x/y coords instead. Also you should check out Peppar's version of essentially the same functions, but not nearly as complicated:

(I added the target version)

Code:
function AddSpecialEffectLocWithTimer_Child takes nothing returns nothing
    local effect tempeffect = bj_lastCreatedEffect
    local real duration     = bj_enumDestructableRadius
    call PolledWait( duration )
    call DestroyEffect( tempeffect )
endfunction

function AddSpecialEffectLocWithTimer takes location whichLocation, string whichEffect, real duration returns nothing
    local trigger dispatcher = CreateTrigger()
    set bj_enumDestructableRadius = duration
    call AddSpecialEffectLocBJ( whichLocation, whichEffect )
    call TriggerAddAction( dispatcher, function AddSpecialEffectLocWithTimer_Child )
    call TriggerExecute( dispatcher )
    call DestroyTrigger( dispatcher )
endfunction

function AddSpecialEffectTargetUnitWithTimer_Child takes nothing returns nothing
    local effect tempeffect = bj_lastCreatedEffect
    local real duration     = bj_enumDestructableRadius
    call PolledWait( duration )
    call DestroyEffect( tempeffect )
endfunction

function AddSpecialEffectTargetUnitWithTimer takes string whichAttach, unit whichUnit, string whichEffect, real duration returns nothing
    local trigger dispatcher = CreateTrigger()
    set bj_enumDestructableRadius = duration
    call AddSpecialEffectTargetUnitBJ(whichAttach, whichUnit, whichEffect)
    call TriggerAddAction( dispatcher, function AddSpecialEffectTargetUnitWithTimer_Child )
    call TriggerExecute( dispatcher )
    call DestroyTrigger( dispatcher)
endfunction

@Aiur: Your code has a bug -- if I put 10 points in the first skill it thinks I've put a point in the second one. Edit: I just noticed you used 1333 as an example of being full. When I add this to the pack I'll include comments warning people.

EDIT: I'm learning PHP/MySQL right now, so maybe I'll rig together a function pack site myself =)
08-06-2003, 06:45 PM#81
Starcraftfreak
datanangel, I think you misunderstood quite much.
1) As long as a function is optimized, it can be as complicated as it is, it just has to work as fast as possible. And in my opinion including the PolledWait function is faster than calling it.
2) These functions work only for already created effects (I don't even understand how they are supposed to work). My functions should work as a replacement for the common.j functions to create a special effect and remove it after the time is over.
08-06-2003, 07:31 PM#82
Peppar
Starcraftfreak: In reply to 2), the functions do work, you were
probably just looking at the child-functions. To use these
functions call AddSpecialEffectLocWithTimer or
AddSpecialEffectTargetUnitWithTimer. The reason for the
functions having child functions is so that the trigger that called
the function can resume its execution directly instead of having to
wait for the effect to end.
08-06-2003, 07:34 PM#83
Starcraftfreak
Sorry, I forgot to add the screenshot of the weird Mountain King in the last post.
Unfortunately I can't add an attachment to an existing post, so sorry for the double post.
08-06-2003, 09:37 PM#84
dataangel
Quote:
Originally posted by Starcraftfreak
datanangel, I think you misunderstood quite much.
1) As long as a function is optimized, it can be as complicated as it is, it just has to work as fast as possible. And in my opinion including the PolledWait function is faster than calling it.

It's true that some programming languages allow inline functions, where instead of calling the function it copy and pastes the contents of the function it's 'calling' when you compile it -- and that's there for speed reasons. However, seeing as there's no way to benchmark this, there's no way to tell whether or not the overhead for calling the function means worse performance. As it is, it maybe making performance worse by making a longer .j file for the game to parse.

Quote:
2) These functions work only for already created effects (I don't even understand how they are supposed to work). My functions should work as a replacement for the common.j functions to create a special effect and remove it after the time is over.


I'm not sure why you think they only work for already created effects -- they don't. They actually create an effect. The bj_ variables are only used because a global was needed. The way they work is actually simple once you get the whole story:

I wanted to create a special effect with timer function, so I just made a function that made a local effect variable, stored the special effect created in it, did a polled wait for the duration, and then destroyed it. The problem with this is that the trigger that used my function would stop until the PolledWait in my function was over. To get around this Peppar made the functions I posted, which create a dummy trigger (the _Child functions are the actions for this dummy trigger) and have the PolledWait occur in this dummy trigger. Because using a PolledWait in a trigger makes war3 use threads -- the trigger that calls my function no longer waits for the PolledWait to end.

I hope that clears things up =)
08-06-2003, 09:40 PM#85
dataangel
Quote:
Originally posted by Starcraftfreak
Sorry, I forgot to add the screenshot of the weird Mountain King in the last post.
Unfortunately I can't add an attachment to an existing post, so sorry for the double post.


You can create similar wierd effects by storing variables in array elements higher than 8192, or giving ground units obscene flying heights =)
08-06-2003, 09:54 PM#86
Aiursrage2k
I think this would be a better solution then what I had earlier put up. As for the ten level bug, I could think of no easy solution... :bgrun:


//requires strlen
Code:
function setLevel takes unit u, integer num returns nothing 
     call SetUnitUserData( u,GetUnitUserData(u)+ R2I(Pow(I2R(10),I2R(num))) ) 
endfunction 

function getLevel takes unit u, integer num returns integer 
     local string str = I2S(GetUnitUserData(u))
     local string rev = ""
     local integer i = strlen(str)

     loop
       exitwhen i < 1
       set rev = rev + SubStringBJ(str,i,i)
       set i = i - 1
     endloop
     return S2I(SubStringBJ(rev,num+1,num+1)) 
endfunction 
08-06-2003, 10:43 PM#87
Peppar
Quote:
Originally written by Aiursrage2k
function power takes integer num, integer exp returns integer

There is a native function just like it, except it takes reals. You
might want to consider using it.
Code:
native Pow takes real x, real power returns real
I think the idea is great :) Many a modder probably tears his hair
off when not getting the levelup triggers to work.

EDIT: Constant? What difference does it make, do you reckon? :P
08-06-2003, 11:17 PM#88
dataangel
@peppar: How's the Handle2Int experimentation coming? :ggani:
08-06-2003, 11:26 PM#89
Peppar
I made a dialog engine, using only the triggering queue array :)
Don't worry, it positions itself in the higher indexes not disturbing
the trigger queue. There is a 100-trigger limit to it. I'll test and
comment it some further, then I'll post it here. It uses HandleToInt
and some other.
08-06-2003, 11:34 PM#90
dataangel
@peppar: There's still a ton of stuff I want to try, like scaling special effects =)