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

How Trigger Proximity Death?

Status
Not open for further replies.
Level 13
Joined
May 11, 2008
Messages
1,198
So I've got two allies.
They each have their hero, sapper, whatever...
Normally, they can't harm eachother...
But if one of them picks a certain sapper and another picks another kind...and if those two kind of units get to close to eachother...BAM! one sapper kills the other. How do you do this??

Any thoughts? I looked into a unit comes within range but that only works with preplaced units. there was some guy over at thehelper.net claiming to solve this problem but quite frankly, if it works, i can't figure his system out. it won't work for me.

when i try to implement his system the thing that gives me grief is making an event. i keep getting errors!
 
Level 15
Joined
Mar 31, 2009
Messages
1,397
When you spawn that sapper than set it to a Variable and put in 1st

  • Blah
    • Events
      • Time - Every 0.50 seconds of game time
    • Conditions
    • Actions
      • Set UnitLocation = (Position of (Sapper))
      • Region - Center SapperRegion on UnitLocation
  • Blarg
    • Events
      • Unit - A unit enters No region
    • Conditions
      • (Unit-type of (Entering unit)) Equal to Sapper2
    • Actions
      • Unit - Explode (Triggering unit)
      • Unit Group - Pick every unit in (Units in SapperRegion) and do (Unit - Explode (Picked unit))
Be sure to Destroy the variables and stufffff
 
Level 13
Joined
May 11, 2008
Messages
1,198
lol that's interesting but they're only sappers in the world editor, not in gameplay, they don't explode...technically what's happening is a vampire is eating a human...it's a joke based off of both vampirism and varimathras' pissedoff unit quotes. but yeah...that idea might work...anyone else got an opinion?
 
Level 13
Joined
May 11, 2008
Messages
1,198
The_wand_mirror, you just scanned my post instead of reading it, didn't you? I already tried that event. Or well, I guess you said something about it working ok for a simple map instead of a complicated one. Well, I find that if you want to trigger things properly, things need to get complicated at some point, haha. anyway since everyone in my map gets to pick their runner...and it's done by the "altar/tavern" this wouldn't work. If, however, it was done by choosing a neutral hero that becomes a player controlled unit, then that IS a different story and this kind of thing could work out pretty good...

The system maker just made a couple of test maps for it... so yeah I think I'll be able to modify this now. [System] Unit Enters Range - Page 2 - The Helper Forums

BlargHonk's idea would probably work...but since the region needs to be able to move to the unit and it's a possibility that there will be more than a few units needing a region following them around, then that would probably be a hassle to do.
 
Level 11
Joined
Feb 16, 2009
Messages
760
Just use something like:
TRIGGER 1
Event: A unit enters Playable map area
Condition: Unit type of triggering unit equal to sapper
Action: Trigger- add to Trigger 2 the event A unit comes within (Your range) of (Triggering unit)

Trigger 2
Events- None
Condion unit-type of triggering unit equal to sapper
Actions Set TempGroup to Units within (Same range) of triggering unit
Pick every unit in TempGroup and kill (Picked unit)
(Leak remove, dont know by heart)
 
Level 13
Joined
May 11, 2008
Messages
1,198
M4stah, that could work except for the part where you didn't understand the part where i said that there was more than one kind of sapper unit in the map. alternatively i could give an extra unit type to the sappers like giant and well...something else...but i had tried that before and found it's better to be more specific if possible than using things like buffs and unit types. most of the time anyway. the thing is you only have so many unit types so if you try to use them for everything you're going to run out of unit types pretty quick. this method from thehelper.net is good for sure, but the main drawback it seems to have is that it requires me to make an ability for the trigger. other than that, it works pretty good and isn't really a hassle. i think i'll go with it for now.

it looks like this:
JASS:
scope Kill initializer Init

//==================================================||
//                                                  ||
//           Spell Created by Darthfett             ||
//                                                  ||
//             Easy to end spell, use:              ||
//                                                  ||
//    call Kill_Data[UNIT].release()                ||
//      - to finish a spell abruptly                ||
//                                                  ||
//    call Kill_Data.finish(Data[UNIT])             ||
//      - to finish a spell with FX.                ||
//                                                  ||
//==================================================||

globals
    private integer AID_KILL = 'A00S'
endglobals

public struct Data
    //! runtextmacro PUI()
    unit c
    trigger trig
        
    
    method onDestroy takes nothing returns nothing
        call RemoveTriggerEnterRangeEvent(this.trig) //Destroy the trigger
    endmethod
endstruct

function DestroyTrig takes nothing returns nothing
    call Data(GetCSData(GetExpiredTimer())).release()
    call DestroyTimer(GetExpiredTimer())
endfunction

private function FILTER takes nothing returns boolean
    return GetUnitTypeId(GetFilterUnit()) == 'ufro' and GetWidgetLife(GetCenterUnit()) >= 0.405 //Only kill the unit if it is dead
endfunction

private function Kill takes nothing returns nothing
    local timer t = CreateTimer()
    call KillUnit(GetCenterUnit())
    call SetCSData(t,GetCSData(GetCenterUnit()))
    call TimerStart(t,0,false,function DestroyTrig) //Start a new thread to prevent any trigger problems
    set t = null
endfunction

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == AID_KILL
endfunction

private function Actions takes nothing returns nothing
    local Data d = Data[GetTriggerUnit()]
    local integer i = 0
    if d != 0 then
        call d.release()
    endif
    set d = Data.create()
    set Data[GetTriggerUnit()] = d
    
    set d.c = GetTriggerUnit()
    set d.trig = TriggerRegisterUnitEnterRangeEvent(d.c,250,null)
    call TriggerAddCondition(d.trig,Condition(function FILTER))
    call TriggerAddAction(d.trig,function Kill)
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t,Condition(function Conditions))
    call TriggerAddAction(t,function Actions)
endfunction

endscope
also, it uses these other triggers...
this next one has a lot of extra info so i put
//=====================================
//=====================================
Relevant Trigger Information
//=====================================

like that.
JASS:
scope pickmain initializer I
//=====================================
//=====================================
private function ruserunnerhumanskill takes nothing returns nothing
    call IssueImmediateOrder( GetLastReplacedUnitBJ(), "berserk" )
endfunction

private function userunnerhumanskill takes nothing returns nothing
    call IssueImmediateOrder( GetTrainedUnit(), "berserk" )
endfunction
//=====================================
private function randomedpandaskills takes nothing returns nothing
    call TriggerRegisterUnitEvent( gg_trg_pandaren_flames, GetLastReplacedUnitBJ(), EVENT_UNIT_SPELL_EFFECT )
endfunction
private function randomedmageskills takes nothing returns nothing
    call TriggerRegisterUnitEvent( gg_trg_starfall, GetLastReplacedUnitBJ(), EVENT_UNIT_SPELL_CAST )
    call TriggerRegisterUnitEvent( gg_trg_starfall_off, GetLastReplacedUnitBJ(), EVENT_UNIT_SPELL_ENDCAST )
endfunction 
private function pandaskills takes nothing returns nothing
    call TriggerRegisterUnitEvent( gg_trg_pandaren_flames, GetTrainedUnit(), EVENT_UNIT_SPELL_EFFECT )
endfunction
private function mageskills takes nothing returns nothing
    call TriggerRegisterUnitEvent( gg_trg_starfall, GetTrainedUnit(), EVENT_UNIT_SPELL_CAST )
    call TriggerRegisterUnitEvent( gg_trg_starfall_off, GetTrainedUnit(), EVENT_UNIT_SPELL_ENDCAST )
endfunction 
 
private function randomedtreedemonskills takes nothing returns nothing
    call TriggerRegisterUnitEvent( gg_trg_consume_tree, GetLastReplacedUnitBJ(), EVENT_UNIT_SPELL_EFFECT )
    call TriggerRegisterUnitEvent( gg_trg_teleport_tree, GetLastReplacedUnitBJ(), EVENT_UNIT_SPELL_EFFECT )
endfunction    

private function treedemonskills takes nothing returns nothing
    call TriggerRegisterUnitEvent( gg_trg_consume_tree, GetTrainedUnit(), EVENT_UNIT_SPELL_EFFECT )
    call TriggerRegisterUnitEvent( gg_trg_teleport_tree, GetTrainedUnit(), EVENT_UNIT_SPELL_EFFECT )
endfunction    

private function randomeddemonmageskills takes nothing returns nothing
    call UnitAddItemByIdSwapped( 'I000', GetLastReplacedUnitBJ() )
    call UnitAddItemByIdSwapped( 'I001', GetLastReplacedUnitBJ() )
endfunction

private function demonmageskills takes nothing returns nothing
    call UnitAddItemByIdSwapped( 'I000', GetTrainedUnit() )
    call UnitAddItemByIdSwapped( 'I001', GetTrainedUnit() )
endfunction

 
private function randomchaser takes nothing returns nothing
call ReplaceUnitBJ(GetTrainedUnit(), udg_chasers_random[GetRandomInt(0, 9)], bj_UNIT_STATE_METHOD_DEFAULTS )
if GetUnitTypeId(GetLastReplacedUnitBJ()) == 'Edem' then
    call randomedmageskills()
else
    if GetUnitTypeId(GetLastReplacedUnitBJ()) == 'Ofar' then
        call randomedpandaskills()
    endif
endif
endfunction
//=====================================
//===================================== 
private function randomrunner takes nothing returns nothing
call ReplaceUnitBJ(GetTrainedUnit(), udg_runners_random[GetRandomInt(0, 25)], bj_UNIT_STATE_METHOD_DEFAULTS )
if GetUnitTypeId(GetLastReplacedUnitBJ()) == 'unec' then
    call randomedtreedemonskills()
else
    if GetUnitTypeId(GetLastReplacedUnitBJ()) == 'hdhw' then
        call randomeddemonmageskills()
    else
        if GetUnitTypeId(GetLastReplacedUnitBJ()) == 'otau' then
            call ruserunnerhumanskill()
        else
        endif
    endif
endif
endfunction
//=====================================
private function pnameset takes nothing returns nothing
    call SetPlayerName( GetOwningPlayer(GetTriggerUnit()), udg_strings[( GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit())) + 12 )] ) 
endfunction 
 
private function setmbiconitemreplaced takes nothing returns nothing
    call MultiboardSetItemIconBJ( udg_mainmultiboard, 1, S2I(udg_mbp[GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))]), udg_icons[GetUnitPointValue(GetLastReplacedUnitBJ())])
endfunction

private function setmbiconitemtrained takes nothing returns nothing
    call MultiboardSetItemIconBJ( udg_mainmultiboard, 1, S2I(udg_mbp[GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))]), udg_icons[GetUnitPointValue(GetTrainedUnit())])
endfunction

private function setmbitemname takes nothing returns nothing
    call MultiboardSetItemValueBJ( udg_mainmultiboard, 1, S2I(udg_mbp[GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))]), GetPlayerName(GetOwningPlayer(GetTriggerUnit())) )
endfunction
    
private function rru takes nothing returns nothing
    call UnitAddItemByIdSwapped( 'phlt', GetLastReplacedUnitBJ() )
    call RemoveUnit(GetTriggerUnit())
endfunction
    
private function ru takes nothing returns nothing
    call UnitAddItemByIdSwapped( 'phlt', GetTrainedUnit() )
    call RemoveUnit(GetTriggerUnit())
endfunction

private function spawnflyer takes nothing returns nothing
    call ReplaceUnitBJ(GetTriggerUnit(), 'nnht', bj_UNIT_STATE_METHOD_RELATIVE)
endfunction

private function rpuset takes nothing returns nothing
    set udg_pickedunit[GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))] = GetLastReplacedUnitBJ()
endfunction
private function puset takes nothing returns nothing
    set udg_pickedunit[GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))] = GetTrainedUnit()
endfunction






private function A takes nothing returns nothing

//=====================================
//=====================================
if GetUnitTypeId(GetTriggerUnit()) == 'ncbf' or GetUnitTypeId(GetTriggerUnit()) == 'ncbe' or GetUnitTypeId(GetTriggerUnit()) == 'ndmg' then
    if GetUnitTypeId(GetTrainedUnit()) == 'edot' then
        call randomrunner()
        call rpuset()
        call pnameset()
        call setmbiconitemreplaced()
        call setmbitemname()
        call spawnflyer()
//=====================================
    else
        if GetUnitTypeId(GetTrainedUnit()) == 'unec' then
            call treedemonskills()
            call puset()
            call pnameset()
            call setmbiconitemtrained()
            call setmbitemname()
            call spawnflyer()
        else
            if GetUnitTypeId(GetTrainedUnit()) == 'hdhw' then
                call demonmageskills()
                call puset()
                call pnameset()
                call setmbiconitemtrained()
                call setmbitemname()
                call spawnflyer()
            else
//=====================================
//=====================================
                if GetUnitTypeId(GetTrainedUnit()) == 'otau' then
                    call userunnerhumanskill()
                    call puset()
                    call pnameset()
                    call setmbiconitemtrained()
                    call setmbitemname()
                    call spawnflyer()
//=====================================
                else
                    call puset()
                    call pnameset()
                    call setmbiconitemtrained()
                    call setmbitemname()
                    call spawnflyer()
                endif
            endif
        endif
    endif
else
if GetUnitTypeId(GetTriggerUnit()) == 'nfnp' then
    if GetUnitTypeId(GetTrainedUnit()) == 'edry' then
        call randomchaser()
        call rpuset()
        call pnameset()
        call setmbitemname()
        call setmbiconitemreplaced()
        call rru()
    else
        if GetUnitTypeId(GetTrainedUnit()) == 'Edem' then
            call mageskills()
            call puset()
            call pnameset()
            call setmbitemname()
            call setmbiconitemtrained()
            call ru()
        else
            if GetUnitTypeId(GetTrainedUnit()) == 'Ofar' then
                call pandaskills()
                call puset()
                call pnameset()
                call setmbitemname()
                call setmbiconitemtrained()
                call ru()
            else
                call puset()
                call pnameset()
                call setmbitemname()
                call setmbiconitemtrained()
                call ru()
            endif
        endif
    endif
else
endif
endif
endfunction




//===========================================================================
private function I takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_TRAIN_FINISH )
    call TriggerAddAction( t, function A )
endfunction

endscope

JASS:
library CSData

    //****************************************************************************************************
    // CSData 15.3
    // ___________
    // CSDatas are like UserData in units and items, they are faster than gamecache unless you have more
    // than 8191 handles in your map. In that case it would be a little slower but only for those
    // handles. And if you have more than 8191 handles your map is too slow already anyways.
    //
    // Notice that for public spells or systems to be distributed you should only use these
    // for private objects (those who the mapper would never have access to) If you are making something
    // for your map you can use them wherever you want.
    //
    // Best to be used in conjunction to CSArrays so you just specify an array id for a handle.
    //
    // DO NOT USE THIS ON THESE HANDLE TYPES: -lightning, -ubersplat, -image, -texttag,
    //                                        -any 'argument' handle (like playerstate, damagetype, etc)
    //
    //****************************************************************************************************

    //====================================================================================================
    globals
        private constant integer MAX_HANDLE_ID_COUNT = 408000
        // values lower than 8191: very fast, but very unsafe.
        // values bigger than 8191: not that fast, the bigger the number is the slower the function gets
        // Most maps don't really need a value bigger than 50000 here, but if you are unsure, leave it
        // as the rather inflated value of 408000
    endglobals

    //=================================================================================================
    // a.k.a H2I, changed name to CS_H2I to prevent conflicts with other systems, it then stayed that
    // instead of changing to a private or public function since many outside spells use it.
    //
    function CS_H2I takes handle h returns integer
        return h
        return 0
    endfunction

    //==================================================================================================
    globals
        private integer array csdata[MAX_HANDLE_ID_COUNT]
        private constant integer MIN_HANDLE_ID=0x100000
    endglobals

    //It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
    function SetCSData takes handle h, integer v returns nothing
        debug if(CS_H2I(h)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
        debug     call BJDebugMsg("SetCSData: Handle id too big, increase the max handle id count or use gamecache instead")
        debug endif
        set csdata[CS_H2I(h)-MIN_HANDLE_ID]=v
    endfunction

    function GetCSData takes handle h returns integer
        debug if(CS_H2I(h)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
        debug     call BJDebugMsg("SetCSData: Handle id too big, increase the max handle id count or use gamecache instead")
        debug endif
        return csdata[CS_H2I(h)-MIN_HANDLE_ID]
    endfunction

endlibrary

JASS:
//==============================================================================
//  PUI -- Perfect Unit Indexing by Cohadar -- v5.1
//==============================================================================
//
//  PURPOUSE:
//       * Extending UnitUserData()
//       * This is basically perfect hashing algorithm for units
//
//  HOW TO USE:
//       * You have only one function at your disposal GetUnitIndex(unit)
//         It will return a unique index for each unit in range 1..8190
//
//       * What you will do with that index is all up to you
//         Of course using global arrays is the most obvious choice
//         Advanced jassers will think of a couple of more clever ones ofc.
//
//       * There are also 2 textmacros available at the end of library code
//         They can be used for easier attaching to units
//         PUI for structs 
//         PUI_PROPERTY for unit, integer, real, boolean and string variables
//
//  PROS: 
//       * You can use any number of systems that previously could not work together
//         because they all required exclusive access of UnitUserData()
//
//       * You can also use this to attach spell data structs to casters
//
//       * There are no SetUnitIndex() or ClearUnitIndex() functions here
//         Each unit gets assigned one index that cannot be changed
//         That index will be automatically recycled when unit is removed from the game.
//
//  CONS:
//       * This system uses UnitUserData() itself
//         That means that if you want to use PUI you must recode 
//         any other system that uses UnitUserData() to use GetUnitIndex() instead
//
//       * If you use UnitIndex for arrays of non-native types (timers, effects and similar)
//         you must check if timer on that index already exists before you create a new one.
//         This can happen if GetUnitIndex() assigns a recycled index (index of some dead and removed unit)
//         to the newly created unit for which you intended to use timer for
//
//       * All in all this is not a sys for newbies, it gives great power,
//         but it requires knowledge and carefull handling
//
//  DETAILS:
//       * System is using unit array to keep track of all units with an index.
//         Array is periodically checked for removed units,
//         when removed unit is found, index is recycled.
//         Indexes have "decay time" to prevent bugs
//         caused by attaching to "Can't Raise, Does not decay" type units,
//         or by using RemoveUnit() function
//
//  SYSTEM COMMANDS: (debug mode only, red player only)
//
//       * type -pui to display indexes of currently selected units
//       * type -puistats to display some stats
//
//  THANKS TO:
//       * Vexorian - for his help with PUI textmacro
//
//  HOW TO IMPORT:
//       * Just create a trigger named PUI
//       * convert it to text and replace the whole trigger text with this one
//
//==============================================================================


library PUI initializer Init

//==============================================================================
globals    
    //-----------------------------------------------
    private constant real INDEX_DECAY_TIME = 5.  // seconds
    
    //-----------------------------------------------    
    private constant real PERIOD = 0.03125   // 32 fps
        
    //-----------------------------------------------
    private constant integer DECAY_TICKS = R2I(INDEX_DECAY_TIME/PERIOD)
    
    //-----------------------------------------------
    private integer array Indexz
    private unit    array Unitz
    private integer array Decayz
    private integer array Tickz

    private integer maxindex = 0
    private integer topindex = 0
    private integer decayindex = 0
    private integer checker  = 0
    private integer decayer  = 0
    private integer tick = 0
endglobals


//==============================================================================
private function PeriodicRecycler takes nothing returns boolean
    local integer temp
    
    set tick = tick + 1
    
    if topindex > decayindex then
        set checker = checker + 1
        if checker > topindex then
            set checker = decayindex + 1
        endif
        if (GetUnitUserData(Unitz[checker])==0) then
            set decayindex = decayindex + 1
            set Unitz[checker] = Unitz[decayindex]
            
            // swap(checker, decayindex)
            set temp = Indexz[checker]
            set Indexz[checker] = Indexz[decayindex]
            set Indexz[decayindex] = temp
            
            set Decayz[decayindex] = DECAY_TICKS
            set Tickz[decayindex] = tick
        endif
    endif

    if decayindex > 0 then
        set decayer = decayer + 1
        if decayer > decayindex then
            set decayer = 1
        endif
        set Decayz[decayer] = Decayz[decayer] - (tick-Tickz[decayer])
        if Decayz[decayer] > 0 then
            set Tickz[decayer] = tick
        else
            // swap(decayer, decayindex)
            set temp = Indexz[decayer]
            set Indexz[decayer] = Indexz[decayindex]
            set Indexz[decayindex] = temp
            
            set Unitz[decayindex] = Unitz[topindex]
            
            // swap(decayindex, topindex)
            set temp = Indexz[decayindex]
            set Indexz[decayindex] = Indexz[topindex]
            set Indexz[topindex] = temp
            
            set decayindex = decayindex - 1
            set topindex = topindex - 1
        endif    
    endif
    
    return false
endfunction

//==============================================================================
//  Main and only function exported by this library
//==============================================================================
function GetUnitIndex takes unit whichUnit returns integer
    local integer index
    
    debug if whichUnit == null then
    debug   call BJDebugMsg("|c00FF0000ERROR: PUI - Index requested for null unit")
    debug   return 0
    debug endif
    
    set index = GetUnitUserData(whichUnit)

    if index == 0 then
        set topindex = topindex + 1
        if topindex > maxindex then
            set maxindex = topindex
            set Indexz[topindex] = topindex
        endif
        set index = Indexz[topindex]
        set Unitz[topindex] = whichUnit
       
        call SetUnitUserData(whichUnit, index)
        set index = GetUnitUserData(whichUnit)
       
        // this happens when requesting unit index for removed unit
        debug if index == 0 then
        debug     call BJDebugMsg("|c00FFCC00WARNING: PUI - Bad unit handle")
        debug endif
        
        //debug call BJDebugMsg("|c00FFCC00PUI: Index assigned #" + I2S(index))
    endif
    
    return index
endfunction

//==============================================================================
private function DisplayStats takes nothing returns nothing
    call BJDebugMsg("=============================================")    
    call BJDebugMsg("Biggest index ever = " + I2S(maxindex))    
    call BJDebugMsg("Indexes in use = " + I2S(topindex-decayindex))
    call BJDebugMsg("Decaying indexes = " + I2S(decayindex))
    call BJDebugMsg("Released indexes = " + I2S(maxindex-topindex))
    call BJDebugMsg("=============================================")    
endfunction

//===========================================================================
private function DisplaySelectedEnum takes nothing returns nothing
    call BJDebugMsg( "PUI(" + ( GetUnitName(GetEnumUnit()) + ( ") = " + I2S(GetUnitUserData(GetEnumUnit())) ) ) )
endfunction

//===========================================================================
private function DisplaySelected takes nothing returns nothing
    local group g = CreateGroup()
    call SyncSelections()
    call GroupEnumUnitsSelected(g, Player(0), null)
    call ForGroup(g, function DisplaySelectedEnum)
    call DestroyGroup(g)
    set  g = null
endfunction

//==============================================================================
private function Init takes nothing returns nothing
    local trigger trig 
    
    set trig = CreateTrigger()
    call TriggerRegisterTimerEvent( trig, PERIOD, true )
    call TriggerAddCondition( trig, Condition(function PeriodicRecycler) )

    debug set trig = CreateTrigger()
    debug call TriggerRegisterPlayerChatEvent( trig, Player(0), "-pui", true )
    debug call TriggerAddAction( trig, function DisplaySelected )      
    
    debug set trig = CreateTrigger()
    debug call TriggerRegisterPlayerChatEvent( trig, Player(0), "-puistats", true )
    debug call TriggerAddAction( trig, function DisplayStats )
endfunction

endlibrary


//===========================================================================
//  Allowed PUI_PROPERTY TYPES are: unit, integer, real, boolean, string
//  Do NOT put handles that need to be destroyed here (timer, trigger, ...)
//  Instead put them in a struct and use PUI textmacro
//===========================================================================
//! textmacro PUI_PROPERTY takes VISIBILITY, TYPE, NAME, DEFAULT
$VISIBILITY$ struct $NAME$
    private static unit   array pui_unit
    private static $TYPE$ array pui_data
    
    //-----------------------------------------------------------------------
    //  Returns default value when first time used
    //-----------------------------------------------------------------------
    static method operator[] takes unit whichUnit returns $TYPE$
        local integer pui = GetUnitIndex(whichUnit)
        if .pui_unit[pui] != whichUnit then
            set .pui_unit[pui] = whichUnit
            set .pui_data[pui] = $DEFAULT$
        endif
        return .pui_data[pui]
    endmethod
    
    //-----------------------------------------------------------------------
    static method operator[]= takes unit whichUnit, $TYPE$ whichData returns nothing
        local integer pui = GetUnitIndex(whichUnit)
        set .pui_unit[pui] = whichUnit
        set .pui_data[pui] = whichData
    endmethod
endstruct
//! endtextmacro

//===========================================================================
//  Never destroy PUI structs directly.
//  Use .release() instead, will call .destroy()
//===========================================================================
//! textmacro PUI
    private static unit    array pui_unit
    private static integer array pui_data
    private static integer array pui_id
    
    //-----------------------------------------------------------------------
    //  Returns zero if no struct is attached to unit
    //-----------------------------------------------------------------------
    static method operator[] takes unit whichUnit returns integer
        local integer pui = GetUnitIndex(whichUnit)
        if .pui_data[pui] != 0 then
            if .pui_unit[pui] != whichUnit then
                // recycled handle detected
                call .destroy(.pui_data[pui])
                set .pui_unit[pui] = null
                set .pui_data[pui] = 0            
            endif
        endif
        return .pui_data[pui]
    endmethod
    
    //-----------------------------------------------------------------------
    //  This will overwrite already attached struct if any
    //-----------------------------------------------------------------------
    static method operator[]= takes unit whichUnit, integer whichData returns nothing
        local integer pui = GetUnitIndex(whichUnit)
        if .pui_data[pui] != 0 then
            call .destroy(.pui_data[pui])
        endif
        set .pui_unit[pui] = whichUnit
        set .pui_data[pui] = whichData
        set .pui_id[whichData] = pui
    endmethod

    //-----------------------------------------------------------------------
    //  If you do not call release struct will be destroyed when unit handle gets recycled
    //-----------------------------------------------------------------------
    method release takes nothing returns nothing
        local integer pui= .pui_id[integer(this)]
        call .destroy()
        set .pui_unit[pui] = null
        set .pui_data[pui] = 0
    endmethod
//! endtextmacro
JASS:
library BoolexprUtils initializer init
    globals
        boolexpr BOOLEXPR_TRUE=null
        boolexpr BOOLEXPR_FALSE=null
    endglobals

    private function rettrue takes nothing returns boolean
        return true
    endfunction

    private function retfalse takes nothing returns boolean
        return false
    endfunction

    private function init takes nothing returns nothing
        set BOOLEXPR_TRUE=Condition(function rettrue)
        set BOOLEXPR_FALSE=Condition(function retfalse)
    endfunction
endlibrary

and finally, after all that...this is the primary system that needs all those others...
JASS:
library EnterRange uses CSData,PUI,BoolexprUtils

//===============
//
//       Enter Range v1.02
//      Created by Darthfett
//
// Requires:
//     CSData
//     PUI
//
// Place in a trigger called "EnterRange"
//
//  Provides the unit which the entering unit 
//      came in range of: "GetCenterUnit()"
//
//===============

private struct Data
    //! runtextmacro PUI()
    
    unit whichUnit
    trigger t
    
    static method create takes unit whichUnit returns Data
        local Data d = Data[whichUnit]
        if d != 0 then
            call d.release()
        endif
        set d = Data.allocate()
        set d.t = CreateTrigger()
        set d.whichUnit = whichUnit
        call SetCSData(d.t,d)
        set Data[whichUnit] = d
        return d
    endmethod
        
    method onDestroy takes nothing returns nothing
        call SetCSData(.t,0)
        call DestroyTrigger(.t)
    endmethod
endstruct

//Use the function below to create a trigger with the event
function TriggerRegisterUnitEnterRangeEvent takes unit whichUnit, real range, boolexpr filter returns trigger
    local Data d = Data.create(whichUnit)
    if filter == null then
        call TriggerRegisterUnitInRange(d.t,whichUnit,range,BOOLEXPR_TRUE)
    else
        call TriggerRegisterUnitInRange(d.t,whichUnit,range,filter)
    endif
    return d.t
endfunction

//Use the function below to get the unit which the entering unit came in range of
function GetCenterUnit takes nothing returns unit
    return Data(GetCSData(GetTriggeringTrigger())).whichUnit
endfunction

//Use the function below to dispose of the trigger and event for the unit.
function RemoveUnitEnterRangeEvent takes unit whichUnit returns boolean
    local Data d = Data[whichUnit]
    if d == 0 then
        return false
    endif
    call d.release()
    return true
endfunction

//This will destroy the trigger and clean the struct, but it is NOT recommended.
function RemoveTriggerEnterRangeEvent takes trigger t returns boolean
    local Data d = GetCSData(t)
    if d == 0 then
        return false
    endif
    call d.release()
    return true
endfunction

endlibrary

sometimes i think it's hilarious just how much text a computer needs to do some really simple tasks...

the ability i used was a modified berserk...and well anyway i had to change the hotkey because my sapper would otherwise try to build.
it's a really interesting system because you cast the ability once, at least in the case of my kill unit trigger...and then as soon as the unit gets in range of the no-no unit...he dies.

so i just set up a trigger as soon as the unit is done building i force the unit to use berserk. it works out well too since it doesn't mess up his rally point or anything like that.
 
Status
Not open for further replies.
Top