PUI Error

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
Hey there.
I'm creating some sort of casting trigger for my boss on my map but I ran into a little problem with the newest PUI. I'm also using Cohadar's Damage Deteciton system (that requires PUI).
I get this error:
JASS:
Comparing two variables of different primitive types (except real and integer) is not allowed

on this line:
JASS:
if DP(illidan) == true then

But I need to check when DP is true...

Other way maybe is to use ordinary GetUnitIndex with an assigned global array, if this can't be accomplished with the nasty macro properties, right?

JASS:

scope WhenToCast

//! runtextmacro PUI_PROPERTY("private", "boolean", "DP", "true")

private function DemPact takes unit illidan returns nothing
    call TriggerSleepAction(60.)
    set DP[illidan] = true
endfunction

private function Cast takes nothing returns boolean
    local unit illidan = GetTriggerUnit()
    local unit dmgr = GetEventDamageSource()
    local real x
    local real y
    if IsUnitType(illidan, UNIT_TYPE_HERO) == true and GetOwningPlayer(illidan) == Player(PLAYER_NEUTRAL_AGGRESSIVE) == true then
        if GetWidgetLife(illidan) < 4700. then
            if DP(illidan) == true then
                set x = GetUnitX(dmgr)
                set y = GetUnitY(dmgr)
                call IssuePointOrder(illidan, "carrionswarm", x, y)
                set DP[illidan] = false
                call DemPact.execute(illidan)
            endif
        endif
    endif
    set illidan = null
    set dmgr = null
    return true
endfunction

function InitTrig_WhenToCast takes nothing returns nothing
    call TriggerAddCondition(GlobalOnDamageTrigger, Condition(function Cast))
endfunction

endscope


PUI:
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

Damage Detection:
JASS:

//==============================================================================
//  DD -- DAMAGE DETECTION SYSTEM BY COHADAR -- v1.0
//==============================================================================
//
//  PURPOUSE:
//       * detects when unit is damaged (not when it is attacked)
//
//  HOW TO USE:
//       * To register damage you will have to assign conditions to a GlobalOnDamageTrigger
//
//       ---------------------------------------------------------------------------------
//       call TriggerAddCondition( GlobalOnDamageTrigger, Condition(function YourCondition) )
//       ---------------------------------------------------------------------------------
// 
//       * Or assign an action to a GlobalOnDamageTrigger
//       ---------------------------------------------------------------------------------
//       call TriggerAddAction( GlobalOnDamageTrigger, function YourAction )
//       ---------------------------------------------------------------------------------
//     
//       * Condition functions MUST take nothing and return boolean
//
//       * Condition functions MUST ALWAYS RETURN TRUE or system will not work
//        
//       * System will first execute all conditions and then all actions
//
//       * Do NOT use waits in Conditions, you can use waits in actions
//
//       * Conditions are faster than actions
//
//       * Do NOT destroy, null or in any other way modify GlobalOnDamageTrigger
//
//       * Inside your Action or Condition you can use this functions
//
//       ---------------------------------------------------------------------------------
//         GetTriggerUnit() - damaged unit 
//         GetEventDamage() - amount of damage (real)
//         GetEventDamageSource() - unit that did the damage, this can be null.
//       ---------------------------------------------------------------------------------
//
//  PROS: 
//       * This is the most optimized OnDamage system of all times,
//         also the most simple one to use. (I am so modest<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile    :)" loading="lazy" data-shortname=":)" />
//
//       * You can use UnitDamageTarget() and similar functions in your actions and conditions
//         This system is resistant to requrzion. (thanks to PUI)
//
//  CONS:
//       * None by itself, 
//         but it uses PUI and hence has all PROS and CONS that come with PUI
//
//  DETAILS:
//       * Just read the code, it is short and comments are good
//
//  THANKS TO:
//       * emjlr3 for showing me his OnAttack sys
//
//  HOW TO IMPORT:
//       * Just create a trigger named DamageDetection
//       * convert it to text and replace the whole trigger text with this one
//
//==============================================================================


library DamageDetection initializer Init uses PUI

globals
    //===========================================================================
    //  This trigger is the only thing this system exports
    //  This trigger will be executed when ever ANY unit on the map is damaged
    //===========================================================================    
    trigger GlobalOnDamageTrigger

    // prevents requrzion
    private boolean array ignore 
    
    // array of OnDamage triggers, one unit - one trigger
    private trigger array OnDamagePerUnit 
endglobals


//===========================================================================
// Per Unit OnDamage triggers call this function,
// This function then calls GlobalOnDamageTrigger
//===========================================================================
private function OnDamage takes nothing returns boolean
    local unit u = GetTriggerUnit()
    local integer index = GetUnitIndex(u)
    
    //call BJDebugMsg(&quot;|c0000FF00&quot; + &quot;OnDamage&quot;)
    
    if ignore[index] then
        //call BJDebugMsg(&quot;|c0000FF00&quot; + &quot;endless requrzion prevented&quot;)
    else
        // mutex <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />
        set ignore[index] = true
        if TriggerEvaluate(GlobalOnDamageTrigger) then
            call TriggerExecute(GlobalOnDamageTrigger)
        else
            call BJDebugMsg(&quot;|c00FF0000&quot; + &quot;ERROR: Conditions for GlobalOnDamageTrigger MUST return TRUE&quot;)
        endif
        
        set ignore[index] = false
    endif

    set u = null 
    return false
endfunction 


// makes sure one and only one OnDamage trigger is created per unit
private function LinkOnDamageTrigger takes unit u returns nothing
    local integer index = GetUnitIndex(u)
    local trigger trig = OnDamagePerUnit[index]
    
    // index was recycled so we destroy trigger because 
    // it belongs to previous unit on that index
    if (trig != null) then
        call DestroyTrigger(trig)
    endif

    set trig = CreateTrigger()
    
    //call BJDebugMsg(&quot;Registering OnDamage for &quot; + GetUnitName(u))
    call TriggerRegisterUnitEvent(trig, u, EVENT_UNIT_DAMAGED)   
    call TriggerAddCondition(trig,Condition(function OnDamage))    
    
    set trig = null
endfunction

//Add damage trigger to units who enter map
private function AddTriggers takes nothing returns boolean
    local unit u = GetTriggerUnit()
    call LinkOnDamageTrigger(u)
    set u = null
    return false
endfunction

//Add damage trigger to preplaced units
private function FirstGroup takes nothing returns nothing
    local unit u = GetEnumUnit()   
    call LinkOnDamageTrigger(u)
    set u = null
endfunction

// Init
private function Init takes nothing returns nothing
    local trigger entmap_trig
    local group g
    
    // One trigger to OnDamage them all
    set GlobalOnDamageTrigger = CreateTrigger()
    
    // register OnDamage for preplaced units
    set g = CreateGroup()
    call GroupEnumUnitsInRect(g,bj_mapInitialPlayableArea, null)
    call ForGroup(g,function FirstGroup)
    call DestroyGroup(g)
    set g = null    
   
    // create trigger that registers OnDamage for units that enter the map
    set entmap_trig = CreateTrigger()
    call TriggerRegisterEnterRectSimple(entmap_trig, bj_mapInitialPlayableArea)
    call TriggerAddCondition(entmap_trig,Condition(function AddTriggers))
    set entmap_trig = null
endfunction

endlibrary
 

Artificial

Without Intelligence
Reaction score
326
Try changing this:
JASS:
if DP(illidan) == true then
to this:
JASS:
if DP[illidan] == true then
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
Oh, right. Forgot this type brackets. I'm still used to using "( )" brackets, maybe that's why I have forgotten that. ^^
Thanks, +rep
/ when I can again :( /
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top