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

[System] Unit Indexer

Level 31
Joined
Jul 10, 2007
Messages
6,306
The easiest way to install this is to open the map up, go to objects, then units, copy the unit in there, go to your map, paste it, go back to this map, go to triggers, copy the JASS trigger, go to your map, paste it, go to the top of the script, change that variable's value to the object id you assigned to the unit you pasted into the map, done.


If you have all of the required Lua and what not, the Lua can be faster, but that's if you are experienced.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Bribe, I have been unable to reproduce the default autocast bug >.>. The unit gets indexed before the ability is ever used.


Which event does it bug on? I tried using priest with heal and was unable to reproduce the bug.


All display the proper index
JASS:
struct tester extends array
    private static method abil takes nothing returns boolean
        call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,I2S(GetUnitUserData(GetTriggerUnit())))
        return false
    endmethod
    private static method init takes nothing returns nothing
        local unit u = CreateUnit(Player(0), 'hpea', WorldBounds.centerX, WorldBounds.centerY, 0)
        local unit u2
        
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CHANNEL, function thistype.abil)
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST, function thistype.abil)
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, function thistype.abil)
        
        call SetWidgetLife(u, GetWidgetLife(u)/2)
        set u2 = CreateUnit(Player(0), 'hmpr', WorldBounds.centerX, WorldBounds.centerY, 0)
        
        set u = null
        set u2 = null
        
        call DestroyTimer(GetExpiredTimer())
    endmethod
    private static method onInit takes nothing returns nothing
        call TimerStart(CreateTimer(),0.1,false,function thistype.init)
    endmethod
endstruct
 
Level 16
Joined
Oct 12, 2008
Messages
1,570
It is not a bug with UnitIndexer.. When you add the ability to the footman in the Object editor, and then set the Upgrade to 3 with the initializer, it already bugs.
(BTW, no need to disable the Spellbook ability.. it also bugs without.. )

It is a bug with the ability and the upgrade.. Not sure what makes it bug though.. didn't look into it that deep..
 
Level 3
Joined
Nov 30, 2012
Messages
30
Because many websites are timely unaccessable in China.

By the way,I opened the website later,but I didn't find the LUA script that create the dummy ability in early vision.

And I'm curious why you choose defend except for some item abilities.
 
Level 6
Joined
Oct 23, 2011
Messages
182
JASS:
        static method operator enabled= takes boolean b returns nothing
            if (b) then
                call DisableTrigger(q)
                call DisableTrigger(l)
            else
                call EnableTrigger(q)
                call EnableTrigger(l)
            endif
        endmethod

how does this work? ive just added debug messages today and found out that enabled= doing absolutely nothing on dummies =(...

(am i supposed to disable it while removing dummies too?)
 
Level 6
Joined
Oct 23, 2011
Messages
182
JASS:
struct Test extends array
    private method index takes nothing returns nothing
        call BJDebugMsg(I2S(this) + " indexed")
    endmethod
    private static method periodic takes nothing returns nothing
        call CreateUnit(Player(0), 'hpea', 0, 0, 0)
    endmethod
    private static method onInit takes nothing returns nothing
        set UnitIndexer.enabled = false
        
        call TimerStart(CreateTimer(), 2, true, function thistype.periodic)
    endmethod
    implement UnitIndexStruct
endstruct

Bugs. This is with the fixed version.
So yeah, apparently disabling triggers do not stop them from firing -.-
probably because you used condition instead of action

unitindexer also seems to bug when indexing multiple units at once
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
That's not even possible for double index... lol

if (Q!=e[GetUnitUserData(Q)] and 0==GetUnitUserData(Q)) then

the only way it'd be possible is if you are using SetUnitUserData


as for triggers firing when they are disabled, that'd be a blizzard bug. I'd have to look into it.


This is trigger registration, and it shouldn't fire if the trigger is disabled
call TriggerRegisterEnterRegion(q,WorldBounds.worldRegion,bc2)

edit
right now it's 2 am and I'm completely busy until Friday, so I won't be able to even take a look until next week. Only free on Fridays and Saturdays right now, and this Saturday just ended ; o.

edit
see how it's all wrapped up in an if. The only way this could be happening is if you are using SetUnitUserData :\.

JASS:
            if (Q!=e[GetUnitUserData(Q)] and 0==GetUnitUserData(Q)) then
                if (0==y) then
                    set r=r+1
                    set i=r
                else
                    set i=y
                    set y=n[y]
                endif
                call UnitAddAbility(Q,ABILITIES_UNIT_INDEXER)
                call UnitMakeAbilityPermanent(Q,true,ABILITIES_UNIT_INDEXER)
                call SetUnitUserData(Q,i)
                set e[i]=Q
                static if not LIBRARY_UnitList then
                    if (not a)then
                        set p[i]=p[0]
                        set n[p[0]]=i
                        set n[i]=0
                        set p[0]=i
                    endif
                else
                    set p[i]=p[0]
                    set n[p[0]]=i
                    set n[i]=0
                    set p[0]=i
                    call GroupAddUnit(g,e[i])
                endif
                set o=i
                call FireEvent(INDEX)
                set o=d
            endif
 
Wow, you have the chance to improve your systems but you don't want to?
Right now I am thinking of replacing your systems with someone elses systems.
Because they care.

Situation: User needs Library A. Library A needs Library B, C and D. Library D needs Library E and F.

But the features of library D and F are not needed by the User. Wouldn't it be smart to make it optional?

That would be good architecture. That's one of the reasons why I try to make as much optional as possible. To stop this propagation of dependencies.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
But system D and F are needed by the user, because library A needs them...

cramming them all into 1 system is not what I would call good architecture.


I believe in lots and lots of dependencies. Modularity is what I call good coding. Anything that tries to put everything that it needs into itself is what I would call a bad system. Stuff that makes everything optional with lots of static ifs to me is pointless :\.

Go ahead and use another system then. Just keep in mind that AutoIndex hooks RemoveUnit and has tons of pointless code and that AIDS has a horrible API (textmacros) and uses timers to remove the unit (deindex won't allow you to retrieve the unit, it'll be null, and the units won't be deindexed as soon as they are removed).
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
UnitIndexer requires it, therefor you require it.

End of story, lol


Tons of other systems require it as well. Any system that I've made that has events in it requires it. None of them uses this as optional.


Anyways, I don't plan on ever making the requirement optional. #1, I don't want to do the work, and #2, I don't want to do the work. The reason I made Event in the first place was because I didn't want to do the work. Call me lazy, deal with it, lol.

If I seriously made an entire resource to avoid doing this work, do you really think that I'm going to be all cool and make it optional? I avoid work as much as I can ; ). Getting me to do this has a 0% chance of happening ^)^. I don't like doing work ^_^.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
I don't consider making resources optional as improvements ; )

I consider doing that to be a waste of time : P

I do not like wasting my time :eek:


W/e, a lot of people on THW would prefer resources to be packed all into one super pack =). However, the pro coders understand that doing that is a bad idea ; P, they believe in modularity. However, even they think that sometimes I go too far (I'm like the king of modularity >.<), specifically with WorldBounds (key case in point, and only case that has been brought up thus far). If you were arguing for WorldBounds to be optional, you'd have a 10% chance of convincing me of that =). For Event, 0% : P.

edit
If you want to release this as a single pack, not using Event or WorldBounds or anything else, then by all means do it. I support different distributions ; ). There are plenty of modular and all in one distributions across the net for a variety of systems. If you want to do that here, go for it =). I'm sure that mag would support that as well.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
You are the one causing the error then. I am unable to reproduce your error.

UnitInRangeEvent will throw that error if you attempt to pass in a unit that is not indexed. So if you try to use it with units that were created while UnitIndexer was disabled, it'll throw that error.

I have tested it with both preplaced units and units placed later.
 
Level 6
Joined
Oct 23, 2011
Messages
182
no, unit indexer is not disabled.
apparently unitindexer event fires way before unit itself is indexed
doesn't really make sense, but i've tested thoroughly with debug messages
(update to yours = map broken, revert = not broken)

JASS:
            if enabled then
                debug call BJDebugMsg("enabled")
            endif
            
            debug call BJDebugMsg(GetUnitName(Q))
            if (Q == null) then
                set Q = GetFilterUnit()
            endif
            debug call BJDebugMsg(GetUnitName(Q))
            if (Q!=e[GetUnitUserData(Q)] and 0==GetUnitUserData(Q)) then
                if (0==y) then
                    set r=r+1
                    set i=r
                else
                    set i=y
                    set y=n[y]
                endif
                debug call BJDebugMsg(GetUnitName(Q))
                call UnitAddAbility(Q,ABILITIES_UNIT_INDEXER)
                call UnitMakeAbilityPermanent(Q,true,ABILITIES_UNIT_INDEXER)
                call SetUnitUserData(Q,i)
                debug call BJDebugMsg(I2S(i))
                debug call BJDebugMsg(I2S(GetUnitUserData(Q)))

event fires before "enabled" shows up
like

"RANGE EVENT ERROR: ATTEMPT TO REGISTER NULL UNIT"
enabled
footman
footman
footman
3
3
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
so something like RegisterUnitInRangeEvent(CreateUnit(...))?

edit
yup, lol

interesting



this is because the enter region event is timed... hm

when it was on the filter before, I think it was instant

the filter means that you can't disable it via DisableTrigger... hmm

edit
putting up fixed version now

changed back to version with filter and enabled boolean :\

that's interesting that the trigger itself is on a timer whereas the filter for the trigger isn't
 
Top