• 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.

[Trigger] Passive Mana Rupture

Status
Not open for further replies.
Level 4
Joined
Aug 20, 2004
Messages
65
Just in case someone doesn't know what rupture from DotA does, it causes a unit to lose life when ever it moves. I hope someone can tell me how to make a leak-less, permanent, passive version for mana (when ever the unit with this skill moves it loses X mana per X unit it moves) that hopefully won't lag down the game. This is just out of my meager world editor skills, and any version I make would probably be really laggy or leaky. If anyone does this, thank you.
 
Level 11
Joined
Feb 22, 2006
Messages
752
Here's a distance tracking system I made a few weeks ago. I've modified it to destroy mana. You will need vJass compiler for it. Copy it into Custom Script section or any trigger.



JASS:
library Tracking_System

//Config - do NOT change the names of the variables

globals
    real minlossincrement = 1.00 //this the minimum amount of mana a unit stands to lose before the system actually destroys the mana
    real trackingtimeout = 0.04 //this is how often the timer that tracks all of the units will fire
endglobals

//End Config

//Private Data

struct distancedata
    unit u
    real x
    real y
    real d = 0.00
    real lossfactor = 0.00
    real destroydelay = 0.00
    boolean dead = false
    boolean destroyplease = false
    method onDestroy takes nothing returns nothing
        call SetUnitUserData( .u, 0 )
    endmethod
endstruct
globals
    private timer distancetimer = CreateTimer()
    private distancedata array distancearray
    private integer distancetotal = 0
endglobals
private function Distance_Update takes nothing returns nothing
    local distancedata data
    local real newx
    local real newy
    local real dx
    local real dy
    local real mana
    local integer counter = 0
    loop
        exitwhen ( counter >= distancetotal )
        set data = distancearray[counter]
        if ( data.destroyplease ) then
            //struct (tracking) is slated for destruction, so rearrange array members so you don't get gaps in the array and then destroy struct
            set distancearray[counter] = distancearray[distancetotal - 1]
            set distancetotal = distancetotal - 1
            call data.destroy()
            set counter = counter - 1 //because of the way we rearranged the array members, we need to make sure ALL members get checked
        else
            if ( data.dead ) then
                //if unit is dead, we check to see if delay time is 0; if it is we slate struct for destruction, else we countdown the delay
                if ( data.destroydelay <= 0.00 ) then
                    set data.destroyplease = true
                else
                    set data.destroydelay = data.destroydelay - trackingtimeout
                endif
            else
                set newx = GetUnitX( data.u )
                set newy = GetUnitY( data.u )
                set dx = newx - data.x
                set dy = newy - data.y
                set data.d = data.d + SquareRoot( dx * dx + dy * dy ) //update distance
                if ( ( data.d * data.lossfactor ) >= minlossincrement ) then
                    //time to destroy mana
                    set mana = GetUnitState( data.u, UNIT_STATE_MANA )
                    if ( ( mana - data.d * data.lossfactor ) <= 0.00 ) then
                        call SetUnitState( data.u, UNIT_STATE_MANA, 0.00 )
                    else
                        call SetUnitState( data.u, UNIT_STATE_MANA, mana - data.d * data.lossfactor )
                    endif
                    set data.d = 0.00
                endif
                //update your unit coordinates
                set data.x = newx
                set data.y = newy
                if ( GetWidgetLife( data.u ) < 0.405 ) then
                    //if unit is dead, it obviously can't move anymore, so we slate the struct (tracking) for destruction after the delay time
                    set data.dead = true
                endif
            endif
        endif
        set counter = counter + 1
    endloop
    if ( distancetotal == 0 ) then
        //if no units are being tracked, running timer is useless and wastes memory, so pause timer
        call PauseTimer( distancetimer )
    endif
endfunction

//End Private Data

//Control Functions

function Distance_AddUnitTracking takes unit u, real lossfactor, real destroydelay returns nothing
    local distancedata data = distancedata.create()
    set data.u = u
    set data.x = GetUnitX( u )
    set data.y = GetUnitY( u )
    set data.lossfactor = lossfactor
    set data.destroydelay = destroydelay
    call SetUnitUserData( u, data ) //since structs are integer arrays, we can save them in unit's Custom Value
    if ( distancetotal == 0 ) then
        call TimerStart( distancetimer, trackingtimeout, true, function Distance_Update )
        //if there were no other units being tracked (i.e. timer was paused), start the timer
    endif
    //update your array variables
    set distancearray[distancetotal] = data
    set distancetotal = distancetotal + 1
endfunction

function Distance_ModifyLossFactor takes unit u, real lossfactor returns boolean 
    local distancedata data = GetUnitUserData( u )
    if ( data == 0 ) then
        return false //if no tracking exists on that unit, return false
    endif
    set data.lossfactor = lossfactor
    return ( data.lossfactor == lossfactor ) //will return true if it successfully resets distance
endfunction

function Distance_DestroyTracking takes unit u returns boolean
    local distancedata data = GetUnitUserData( u )
    if ( data == 0 ) then
        return false //if no tracking exists on that unit, return false
    endif
    set data.destroyplease = true
    return ( data.destroyplease ) //will return true if it sucessfully sets up tracking to be destroyed
endfunction

//End Control Functions

endlibrary




Code:
Documentation

function Distance_AddUnitTracking takes unit u, real lossfactor, real destroydelay returns nothing

unit u is the unit you are adding the tracking (or your rupture ability) to
real lossfactor is the ratio between distance traveled in wc3 distance units to 
    mana lost (keep in mind that melee attack range in wc3 is 100.00 distance)
real destroydelay is how long the system waits after a unit dies before
    destroying tracking (kind of useless for your purposes, left it in for compat)

You will need to call this function on every unit that will have your rupture 
ability.


function Distance_ModifyLossFactor takes unit u, real lossfactor returns boolean

unit u is the unit for which you are modifying the loss factor
real lossfactor is the new lossfactor

This function allows you to modify the mana loss factor for a unit with 
tracking. If you try to use it on a unit without tracking, it will return false.


function Distance_DestroyTracking takes unit u returns boolean

unit u is the unit you want to destroying tracking for.

Use this function to destroy tracking and free up system memory for units 
that don't need tracking anymore. There is no need to call this function whenever a unit dies, however, because the system automatically destroys 
tracking for dead units.
 
Status
Not open for further replies.
Top