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

[JASS] Mana reduce upon movment

Status
Not open for further replies.
Level 29
Joined
Jul 29, 2007
Messages
5,174
I tried making this code that reduces the mana of any mechanical unit on the map that is moving... it isn't working lol.

I can only guess its because I don't know how to use unit groups... lol.

Here's the code

JASS:
// This will reduce the mana of any mechanical unit on the map upon moving.
// The actual value is the distance that unit moves within 0.2 seconds.
// If you want to change that value, see the comment in 13 lines.

function mechanicCon takes nothing returns boolean
    return IsUnitType(GetEnumUnit(),UNIT_TYPE_MECHANICAL)    
endfunction
function mecahnictimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit whichUnit = GetHandleUnit(t, "whichUnit")
    local real x = GetHandleReal(t, "x")
    local real y = GetHandleReal(t, "y")
    local real newx = GetUnitX(whichUnit)
    local real newy = GetUnitY(whichUnit)
    local real distance = DistanceBetweenPointsXY(x, y, newx, newy)
    local real mana = GetUnitStatePercent(whichUnit, UNIT_STATE_MANA, UNIT_STATE_MAX_MANA)
    call SetUnitState(whichUnit, UNIT_STATE_MANA, mana-distance) // if you want to reduce or raise the value, just make it something like "mana-distance*20" or "mana-distance/20"
    call FlushHandleLocals(t)
    call DestroyTimer(t) 
    set t = null
    set whichUnit = null
endfunction
function mechanic takes nothing returns nothing
    local timer t = CreateTimer()
    local group g = CreateGroup()
    local unit whichUnit
    local real x
    local real y
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function mechanicCon)) 
    loop
        set whichUnit = FirstOfGroup(g)
        exitwhen whichUnit == null
        call GroupRemoveUnit(g, whichUnit)
        set x = GetUnitX(whichUnit)
        set y = GetUnitY(whichUnit)
        call SetHandleReal(t, "x", x)
        call SetHandleReal(t, "y", y)
        call SetHandleHandle(t, "whichUnit", whichUnit)
        call TimerStart(t, 0.2, true, function mecahnictimer)
    endloop
    set t = null
    call DestroyGroup(g)
    set g = null
    set whichUnit = null 
endfunction

//==== Init Trigger NewTrigger ====
function InitTrig_NewTrigger takes nothing returns nothing
    set gg_trg_NewTrigger = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic( gg_trg_NewTrigger, 0.20 )
    call TriggerAddAction(gg_trg_NewTrigger, function mechanic)
endfunction
 
Level 11
Joined
Aug 25, 2006
Messages
971
When using a condition/filter function you need to use
JASS:
GetFilterUnit() //This is used inside a condition func.
instead of
JASS:
GetEnumUnit() //This is used during a ForGroup
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Try adding ==true to the end of the condition. Don't ask why, just do it ;). (If it doesn't work then you can remove it)

Also, you're using one timer for all the units, which means it will only work for the last unit! You should recreate the timer within the loop.

Also also, you'll want to set the fact that the timer created within the loop is periodic to false since you destroy it anyways.

Also also also, inline the "x" and "y" variables in "mechanic", there is no reason to have them as variables (just a longer script!)

Also also also also, TriggerRegisterTimerEventPeriodic is a BJ :p

Also also also also also, inline "newx", "newy", "x", and "y" in "mechanictimer".

Also also also also also also, remember to edit your post and update your code when you make changes ;)

(The also also thing is from Monty Python and the Holy Grail, if you haven't seen it)
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Ok it works now, thanks Purple ! :D

Try adding ==true to the end of the condition. Don't ask why, just do it ;). (If it doesn't work then you can remove it)

Seems like I didn't didn't to do that since anyway it returns true/false.

Also, you're using one timer for all the units, which means it will only work for the last unit! You should recreate the timer within the loop.

This fixed it, thanks :thumbs_up:

Also also, you'll want to set the fact that the timer created within the loop is periodic to false since you destroy it anyways.

You were too late, done that before you commented (although I never said I did lol).

Also also also, inline the "x" and "y" variables in "mechanic", there is no reason to have them as variables (just a longer script!)

Didn't get what you are saying...

Also also also also, TriggerRegisterTimerEventPeriodic is a BJ :p

And... ?

Also also also also also, inline "newx", "newy", "x", and "y" in "mechanictimer".

Again didn't get what you are trying to say.

(The also also thing is from Monty Python and the Holy Grail, if you haven't seen it)

Nope haven't seen that.


Now a new question, why would moving about... 20 range or so remove like 180 mana ? :huh:
I could just do something like reduceValue/number but im still wondering about it.

And another question, using a Wait wouldn't work here because not like timers it stops the code from working... right ? (Well the true question is - timers don't stop the code from working, right ? ^^)

Here is the new code

JASS:
// This will reduce the mana of any mechanical unit on the map upon moving.
// The actual value is the distance that unit moves within 0.2 seconds.
// If you want to change that value, see the comment in 13 lines.

function mechanicCon takes nothing returns boolean
    return IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL)    
endfunction
function mecahnictimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit whichUnit = GetHandleUnit(t, "whichUnit")
    local real x = GetHandleReal(t, "x")
    local real y = GetHandleReal(t, "y")
    local real newx = GetUnitX(whichUnit)
    local real newy = GetUnitY(whichUnit)
    local real distance = DistanceBetweenPointsXY(x, y, newx, newy)
    local real mana = GetUnitStatePercent(whichUnit, UNIT_STATE_MANA, UNIT_STATE_MAX_MANA)
    if distance > 0 then
        call SetUnitState(whichUnit, UNIT_STATE_MANA, mana-distance) // if you want to reduce or raise the value, just make it something like "mana-distance*20" or "mana-distance/20"
    endif
    call FlushHandleLocals(t)
    call DestroyTimer(t) 
    set t = null
    set whichUnit = null
endfunction
function mechanic takes nothing returns nothing
    local timer t = CreateTimer()
    local group g = CreateGroup()
    local unit whichUnit
    local real x
    local real y
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function mechanicCon)) 
    loop
        set whichUnit = FirstOfGroup(g)
        exitwhen whichUnit == null
        call GroupRemoveUnit(g, whichUnit)
        set t = null
        set t = CreateTimer()
        set x = GetUnitX(whichUnit)
        set y = GetUnitY(whichUnit)
        call SetHandleReal(t, "x", x)
        call SetHandleReal(t, "y", y)
        call SetHandleHandle(t, "whichUnit", whichUnit)
        call TimerStart(t, 0.2, false, function mecahnictimer)
    endloop
    set t = null
    call DestroyGroup(g)
    set g = null
    set whichUnit = null 
endfunction

//==== Init Trigger NewTrigger ====
function InitTrig_NewTrigger takes nothing returns nothing
    set gg_trg_NewTrigger = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic( gg_trg_NewTrigger, 0.20 )
    call TriggerAddAction(gg_trg_NewTrigger, function mechanic)
endfunction
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Ok, it doesn't work... lol.

It takes about 400 mana for a range of 20 or so.
I tried making it mana-distace/100, it still takes around 400 for some reason...

It also took mana when the distance was 0 (the unit didn't move) for some unknown reason so I added that condition (distance > 0).

Here's the new code
JASS:
// This will reduce the mana of any mechanical unit on the map upon moving.
// The actual value is the distance that unit moves within 0.2 seconds.
// If you want to change that value, see the comment in 13 lines.

function mechanicCon takes nothing returns boolean
    return IsUnitType(GetFilterUnit(),UNIT_TYPE_MECHANICAL)    
endfunction
function mecahnictimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit whichUnit = GetHandleUnit(t, "whichUnit")
    local real x = GetHandleReal(t, "x")
    local real y = GetHandleReal(t, "y")
    local real distance = DistanceBetweenPointsXY(x, y, GetUnitX(whichUnit), GetUnitY(whichUnit))
    local real mana = GetUnitStatePercent(whichUnit, UNIT_STATE_MANA, UNIT_STATE_MAX_MANA)
    if distance > 0 then
        call SetUnitState(whichUnit, UNIT_STATE_MANA, mana-distance) // if you want to reduce or raise the value, just make it something like "mana-distance*20" or "mana-distance/20"
    endif
    call FlushHandleLocals(t)
    call DestroyTimer(t) 
    set t = null
    set whichUnit = null
endfunction
function mechanic takes nothing returns nothing
    local timer t = CreateTimer()
    local group g = CreateGroup()
    local unit whichUnit
    local real x
    local real y
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Condition(function mechanicCon)) 
    loop
        set t = null
        set whichUnit = FirstOfGroup(g)
        exitwhen whichUnit == null
        call GroupRemoveUnit(g, whichUnit)
        set t = CreateTimer()
        call SetHandleReal(t, "x", GetUnitX(whichUnit))
        call SetHandleReal(t, "y", GetUnitY(whichUnit))
        call SetHandleHandle(t, "whichUnit", whichUnit)
        call TimerStart(t, 0.2, false, function mecahnictimer)
    endloop
    call DestroyGroup(g)
    set g = null
    set whichUnit = null 
endfunction

//==== Init Trigger NewTrigger ====
function InitTrig_NewTrigger takes nothing returns nothing
    set gg_trg_NewTrigger = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic( gg_trg_NewTrigger, 0.20 )
    call TriggerAddAction(gg_trg_NewTrigger, function mechanic)
endfunction
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
No, if it works already it's fine.

It has to do with the fact that booleans are 4-byte in warcraft, and are not always equal to 1 or 0. Apparently == and the lack thereof compare it differently (where == assumes 0 = false, and otherwise assumes 1 = true). I haven't looked too much into the explanation, but it's something along those lines.
 
Status
Not open for further replies.
Top