• 🏆 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!
IcemanBo
Reaction score
627

Profile posts Latest activity Postings Experience Media Albums Resources About Medals

  • Hey, Icamen, I have changed everything you have mentioned. But some constanted functions cause syntax error. And I keep some of my way because I think it's uneccessary to be changed.
    Thanks man, it means a lot!

    BTW, I thought you are in my friendlist already :/
    I want to know which one is better, smoother

    I want to use this on my SPELL
    :( I dont wanna use Move Action (cuz laggy)

    EDIT:
    Maybe Knockback 3d lot of features hehehe

    Btw Thanks for reply :)
    Ich hab keine Zeit mehr dafür bzw ich verbringe sie andersweitig.
    Es war einfach an der Zeit aufzuhören :)
    ----------
    If you want to loop through all units go with a unit indexer. So you will just be able to loop through all existing indices and make your checks.
    ----------
    Alright! If that's a good solution for the whole map & several different iterations, I'll give it a try & let you know! Thanks.


    ----------
    But frankly, you want add a temp ability? Much easier is just to run a timer, and then to remove the ability when the timer expires. Use hashtable to attach unit/abilityId to the timer.
    ----------
    Eeesh... Not sure I/you wanna open that particular can of worms. I've heard of 'hashtables' (both online & in my programming classes @ college) & get the general idea of 'multidimensional arrays with keys'... But no clue how to use them. Not sure I wanna bug you, since I'm sure there are tutorials on the subject.
    First of all, just want to apologize that it took me so long to respond; I wasn't ignoring you or ungrateful, but I had to think about what you said & that took time (time which, unfortunately, is in very short supply nowadays :<...). That being said:


    ----------
    Why not make these actiosn to target unit directly after casting? So you have to do checks/actions once, and then completly forget about this unit.


    ----------
    Hmm... So it sounds that the "Pick All Units" is too 'costly' (in terms of what, ping? Or computational/processing speed?), but using a global "UnitGroup" variable would be a decent alternative that would allow it?
    (But whether I "pick all units matching X, Y, Z..." or create a UnitGroup variable which does the same thing (having to check the map to add/remove the necessary units from the Group), it seems like that's the same amount of work. Maybe I don't understand)
    ----------
    I make an example. I will show 2 methods to get all units in Region1.

    1. One global UnitGroup, that never gets destroyed. (good)
    2. Creating/destroying a UnitGroup each time.
    Method 1

    Method 2

    I hope you can see the difference. Method 1 needs 3 triggers but is more efficient.
    ----------
    Ok, so you're telling me it's not always the number of triggers that = more/less efficient, but what happens in them? Because yeah, I would've said "3>1!! Less efficient".


    ----------
    In my example I only pick units in Region1, and now imagine you pick every single unit in whole map. If map is very big / or you have many units it is just an enmormous operation, that should be avoided.
    ----------
    Alright, so in order to help you see what I'm trying to accomplish, full disclosure: mainly what I do is work on custom heroes & factions for what is essentially "altered melee"; 5th-race-addition, tavern-addition/replacement, 4-race-replacement, etc.

    That being the setting, the "thing" I'm trying to accomplish is (probably 90% of the time) simple trigger-enhanced abilities. Specifically I was using things like "periodic timers" to detect the presence of certain buffs on units & add/remove certain abilities because of it, dynamically.

    (example being: "Vicious Roar: a roar that increases allied attack damage & gives them Lifesteal for 30 seconds" (i.e. modified Roar ability, then a periodic trigger that, detecting the presence/absence of the "roar" buff, adds/removes a hidden "lifesteal" ability to the affected unit))

    That all being said, it should be clear that this will be cycling through every possible unit on the map (except, perhaps, buildings & trees & such), and should be updating reasonably fast (at least as fast as an Aura; hence .3/.5 seconds...). The map size, of course, may be as small as 1v1 or as large as 6v6. The actual "triggers" are quite 'lite' I would think ("add/remove ability" is pretty much it, so far).

    I realized early on, though, that having a whole bunch of triggers like that would (probably) be a problem. Hence my question.


    ----------
    Now I should method 3, without UnitGroup. Units will be indexed and I will use loop to catch them:
    Method 3

    You see in this method exists no UnitGroup. The reason is, because it's a lot faster.
    In the 'Else - Actions' part the unit has left the region, so we have to deindex properly.
    The method I used is called dynamic indexing because it avoids letting an empty index in my unit[array] variable. (once a unit leaves, it would be null)

    For GUI and looping each 0.50 secnds metho 1 would absolutly do the job without any problem. For bigger situations and/or more complex systems indexing is definitly faster and more efficient.

    EDIT:

    Added "maxIndex = maxIndex - 1" in the deindex part in method 3!
    ----------
    <span style="font-size: 9px">(So wait, "Method 3 doesn't use Unit Group because Method 3 is faster"? Or "Method 3 is faster because it doesn't use Unit Group"?)</span>

    Alright, so I'm trying to understand the coding here... So I think I finally understand the "indexing" bit (you're not using Custom Value, you're just creating a massive array with (potentially) each unit on the map on it, that fits my criteria (in this case, "(T/F) Has this Buff")).

    But given what I have said above about what my needs are (variable (often large) map-size, picking every map unit, reasonable updating frequency, simple triggers, etc), are you suggesting that Method 3 is usable for this/these tasks? And if so, how many can I use before it too becomes a problem (i.e. 1-5, 5-10, 10-20, etc)?

    Thanks again for your thoughts. Sorry it took me so long.

    Respectfully,

    Kyrbi0
    Right, that was simple enough.

    I kinda copied your trigger from my old thread. However I don't get how to loop through it. If possible please show me how to do it from another trigger/function, I didn't really like the timer solution you used before.
    struct patrol
    static integer arraySize = 10

    private thistype prev // these are that you don't let a gap in your periodic loop
    private thistype next
    static thistype first = 0

    integer locCount
    real array x [10]
    real array y [10]
    unit u
    public static method create takes unit u returns thistype
    local thistype this = allocate()
    local integer i = 1
    set this.u = u
    set this.locCount = udg_patrolCount
    loop
    exitwhen i > udg_patrolCount
    set x = GetLocationX(udg_patrolPoint)
    set y = GetLocationY(udg_patrolPoint)
    set i = i + 1
    endloop
    set next = first
    set first.prev = this
    set first = this
    set prev = 0
    return this
    endmethod

    method update takes nothing returns nothing
    local location array loc
    local integer i = 1
    loop
    exitwhen i > this.locCount
    set loc = Location(this.x, this.y)
    if DistanceBetweenPoints(loc,GetUnitLoc(this.u)) < 50 then
    if i >= this.locCount then
    call IssuePointOrder(u, "attack", this.x[1], this.y[1])
    else
    call IssuePointOrder(u, "attack", this.x[i + 1], this.y[i + 1])
    endif

    endif
    set i = i + 1
    endloop
    endmethod

    method destroy takes nothing returns nothing
    call deallocate()
    if this == first then
    set first = next
    endif
    set next.prev = prev
    set prev.next = next
    endmethod
    endstruct
    I wanted to avoid that :p then I am stuck with the indexing problem again, if you recall.

    *cough* #chaosysolutions *cough*
    function patrol takes unit u, integer locCount returns nothing
    local integer id = GetHandleId(u)
    local integer i = 1
    call GroupAddUnit(patrolUnits, u)
    loop
    exitwhen i > locCount
    call SaveReal(hash, id, i, GetLocationX(udg_patrolPoint))
    call SaveReal(hash, id, -i, GetLocationY(udg_patrolPoint))
    set i = i + 1
    endloop
    call SaveInteger(hash, id, 0, locCount)

    call IssuePointOrder(u, "attack", LoadReal(hash, id, 1), LoadReal(hash, id, -1))
    endfunction

    because of the event.
    event
    Events
    Game - patrol_event becomes Equal to 1.00
    Conditions
    Actions
    Game - Display to (All players) the text: ((Name of patrolUnit) + has reached an waypoint!)


    I know that. I attempted to null it instead, but it didn't work. It gave errors.

    Isn't that almost the exact method linked list uses? I never truly understood the logic.
    Yeah I knew it was something along those lines.

    Anyway, I tried to add.
    function RemoveWaypoint takes integer id, unit u returns nothing
    local integer i = GetHandleId(u)
    call SaveReal(hash, i, id, 0)
    call SaveReal(hash, i, -id, 0)
    endfunction

    if xNew != 0 and yNew != 0 then

    but it doesn't work.. I try to remove waypoint 1, and once he reaches waypoint 1 he runs to the middle which means he is moving to the 0,0 coordinates.

    the whole thing..
    function Group takes nothing returns nothing
    local unit u = GetEnumUnit()
    local integer id = GetHandleId(u)
    local real xUnit = GetUnitX(u)
    local real yUnit = GetUnitY(u)
    local real xNew
    local real yNew
    local integer i = 1
    local integer maxCount = LoadInteger(hash, id, 0)

    loop
    exitwhen i > maxCount

    set xNew = LoadReal(hash, id, i)
    set yNew = LoadReal(hash, id, -i)

    if xNew != 0 and yNew != 0 then
    if SquareRoot((xNew - xUnit)*(xNew - xUnit) + (yNew - yUnit)*(yNew - yUnit)) < 50 then
    set udg_patrol_event = 1
    set udg_patrol_event = 0
    set udg_patrolUnit = u
    if i == maxCount then
    call IssuePointOrder(u, "attack", LoadReal(hash, id, 1), LoadReal(hash, id, -1))
    else
    call IssuePointOrder(u, "attack", LoadReal(hash, id, i+1), LoadReal(hash, id, -i-1))
    endif
    endif
    endif
    set i = i + 1
    endloop
    set u = null
    endfunction

    I am very sorry for being an annoyance for you btw.
    Yes I want to remove a certain patrol point / way point.

    If I flat out remove the location there will be bugs since the unit will try to move to location that doesn't exist.

    You mean that one should check if the location isn't null when ordering the unit to move?
    hm...
    function RemoveWaypoint takes integer id, unit u returns nothing
    local integer i = GetHandleId(u)
    local integer count = LoadInteger(hash, i, 0)
    local integer loopCount = id + 1
    loop
    exitwhen loopCount > LoadInteger(hash, id, 0)
    call SaveReal(hash, i, loopCount, LoadReal(hash, i, loopCount - 1))
    call SaveReal(hash, i, -loopCount, LoadReal(hash, i, -loopCount + 1))
    set loopCount = loopCount + 1
    endloop
    call SaveInteger(hash, i, 0, count - 1)
    endfunction

    any clue on why this wont work?
    What about a real event that you can use to see when a unit reaches one way point? I think it could have a few uses.
    Thanks! Come at me vjass pros.

    I am thinking of adding the following functions:

    RemoveWaypoint(integer id) or RemoveWaypoint(location loc)
    AddWaypoint(location loc, integer position)
    StopPatrol(unit u)

    Anything else you can come up with?

    Anyway, for a DEMO I plan to use an patrol ability. The best would be to replace the original patrol to be honest, I think I can manage to do that as well. I might do both actually.
    -i is such a cheat solution xD
    I am glad you kept the current method I used though. I was planning to upload it to the spell section in due time so it wouldn't be nice if you remade everything x)
    I will check.

    edit: seems to work fine indeed. Did you find out what the original mistake was? I don't want to repeat it.
    I think it's rather short. It is supposed to make a unit patrol between a few way points. This is WIP and not working so I replaced a few variables with RAW values to prevent bugs just in case.
    globals
    group patrolUnits = CreateGroup()
    hashtable patrolHash = InitHashtable()
    endglobals

    function patrol takes unit u, integer locationCount returns nothing
    local integer i = GetHandleId(u)
    local integer loopCount = 0
    local real array x
    local real array y
    call GroupAddUnit(patrolUnits, u)
    loop
    exitwhen loopCount > locationCount
    set loopCount = loopCount + 1
    set x[loopCount] = GetLocationX(udg_patrol_points[loopCount])
    set y[loopCount] = GetLocationY(udg_patrol_points[loopCount])
    endloop
    call SaveInteger(patrolHash, i, 0, locationCount)

    call SaveReal(patrolHash, i, 1, x[1])
    call SaveReal(patrolHash, i, 3, x[2])
    call SaveReal(patrolHash, i, 5, x[3])
    call SaveReal(patrolHash, i, 7, x[4])

    call SaveReal(patrolHash, i, 2, y[1])
    call SaveReal(patrolHash, i, 4, y[2])
    call SaveReal(patrolHash, i, 6, y[3])
    call SaveReal(patrolHash, i, 8, y[4])

    call IssuePointOrderLocBJ(u, "attack", Location(LoadReal(patrolHash, i, 3), LoadReal(patrolHash, i, 4)))
    endfunction

    function Group takes nothing returns nothing
    local unit u = GetEnumUnit()
    local integer h = GetHandleId(u)
    local location array locs
    local location uLoc = GetUnitLoc(u)
    local integer i = -1
    local integer i2 = 0
    loop
    exitwhen i2 > LoadInteger(patrolHash, h, 0)
    call BJDebugMsg(R2S(DistanceBetweenPoints(uLoc, locs)))
    set i = i + 2
    set i2 = i2 + 2
    set locs[i2] = Location(LoadReal(patrolHash, h, i), LoadReal(patrolHash, h, i2))
    if DistanceBetweenPoints(uLoc, locs[i2]) < 50 then
    if i2 >= 5 then
    call IssuePointOrderLocBJ(u, "attack", locs[1])
    call BJDebugMsg("new order 1")
    else
    call IssuePointOrderLocBJ(u, "attack", locs[i2 + 1])
    call BJDebugMsg("new order + 1")
    endif

    endif
    endloop
    endfunction

    function patrolUpdate takes nothing returns nothing
    call ForGroup(patrolUnits, function Group)
    endfunction

    //===========================================================================
    function InitTrig_Patrol_System takes nothing returns nothing
    set gg_trg_Patrol_System = CreateTrigger( )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Patrol_System, 0.03 )
    call TriggerAddAction( gg_trg_Patrol_System, function patrolUpdate )
    endfunction

    Patrol Demo
    Events
    Time - Elapsed game time is 1.00 seconds
    Conditions
    Actions
    Set patrol_points[1] = (Center of Region 003 <gen>)
    Set patrol_points[2] = (Center of Region 002 <gen>)
    Set patrol_points[3] = (Center of Region 001 <gen>)
    Set patrol_points[4] = (Center of Region 000 <gen>)
    Set patrol_count = 4
    Set patrol_unit = Marine 0004 <gen>
    Custom script: call patrol(udg_patrol_unit, 4)
    well I can see why thistype is better, easier to keep in mind, in most cases. It was just an example, someone suggestesd to replace SetUnitState to SetWidgetState, it's kinda the same thing :p

    Well most of you more experienced users are!

    edit:

    Mind taking a look on another code of mine? it isn't working as I want it x)
    The global block ruins it a little indeed, so if I make a variable inside the struct static it will still be global?

    And well, I know how fussy you jass experts are. "OMFG if you use bullshit.create instead create.bullshit you will actually save 1 microbyte ram which is very important since you only got 8 gig RAM."

    "And if you replace <struct name> with thistype your processor actually needs to work 0.001% less!"

    If you ask me, my solution is good but not optimal. Sadly that's not good enough for the spell section when the speed lovers comment.

    edit: no offense meant, I just love to over do it.
    What do you have against my solutions? D: It works fine!

    Well your solution is better for sure, but I prefer easier and less complicated solutions. (the exact reason I use hashtables instead of indexing in GUI)
    IcemanBo

    Its allowed here in hive If I create How to create Aghanims's Scepter Tutorial?
    I search in Google and nothing ^.^
  • Loading…
  • Loading…
  • Loading…
  • Loading…
  • Loading…
  • Loading…
  • Loading…
  • Loading…
Top