Spell FarSightBJ

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
FarSightBJ aka "dynamic revealing" reveals a circular area and the invisible units inside to
a player and his allies for a given duration.

Requires:
xecast library by Vexorian
ScannerSweep found here​
Optional:
GroupUtils by Rising_Dusk​
TimerUtils by Vexorian​


How to "install"/import this spell to your map:

1. "install"/import the xecast library.
2. go to it's configuration area and be sure to set FORCE_INVISIBLE_CAST = true
3. make an ability "extending/copying" from the Dust of Appearance ability and change it's AoE to 32.0, you need to modify the Dust of Appearance's buff if you want to change the buff's tooltip etc. for the ability. I think this is because DoA has it's buff hardcoded.
4. copy the script for ScannerSweep to a trigger
5. set the ability's id and the buff's id you made from step 3 in the configuration of ScannerSweep
6. copy the script for FarSighBJ to a trigger
7. make a point target ability and configure it's id in the FarSightBJ configuration area
0. optionally you can also "install"/import the GroupUtils and TimerUtils libraries which will save unnecessary destruction of groups and timers (will recycle groups and timers).
x. it is really that hard unfortunately =)​



This is a continuation of a thread I started roughly an year ago, which can be found here.
Back then I was thinking of using the Faerie Fire for revealing but didn't have a
method to detect when a unit was crossing a certain distance from a point.
So few days ago, basically I came across this native function called UnitShareVision(unit u, player p, bool share)
and figured that it could be used for revealing invisible units + using the 17 rect method for the
distance detection. So I tried but it turned out that the revealing part didn't quite work as I was thinking it would so
I went back to using the Faerie Fire for the revealing of invisible units.


The ScannerSweep library, it exports the scanner_sweep function:

JASS:
//! zinc









library ScannerSweep requires xecast, optional GroupUtils, optional TimerUtils
{
    // Notes: 
    //        1. The trigger code must use TriggerAddAction not TriggerAddCondition
    //           because the scanner_sweep function uses TriggerSleepAction
    //           which doesn't work within a TriggerAddCondition.
    //
    //        2. The native UnitShareVision(unit u, player p, bool share) doesn't
    //           reveal invisible units, only gives vision of them... that is why
    //           the xe library by Vexorian is required. The way it works is that
    //           to reveal a given unit a dummy unit casts a Dust of Appearance (without other
    //           side effects) which does the revealing for both the owner of the dummy
    //           caster and his allies. The funny thing is that althogh UnitShareVision
    //           doesn't reveal invisible units, it reveals the area that their vision
    //           reveals but the IsUnitInvisible(u, p) returns false for them =)...
    //
    //        3. The FORCE_INVISIBLE_CAST flag in the xecast configuration must be set
    //           to true.


    constant integer REVEALER_ID      = 'A001';
    constant integer REVEALER_BUFF_ID = 'Bdet';

    // criteria which determine which units should be ignored
    function is_unit_dummy(unit u) -> boolean { return GetUnitTypeId(u) == XE_DUMMY_UNITID; }


    hashtable HT   = InitHashtable();
    group     tmpg = CreateGroup();
    xecast    xc   = 0;
    rect      R    = null;
    boolexpr  cond_on_enter;
    boolexpr  cond_on_leave;
    constant  integer DUST_OF_APPEARANCE_ORDER_ID = 852625;

    // because Blizzard forgot to make UnitShareVision take into account invisible units
    // the way I would've wanted it to do =)
    //
    function reveal_unit_for_player_and_his_allies(unit u, player p)
    {
        xc.owningplayer = p;
        xc.castInPoint(GetUnitX(u), GetUnitY(u));
    }

    // this is because TSA is way too cool to wait for the game to be paused (multiplayer)
    function TSA(real dur)
    {
        timer t             = null;
        real  timeRemaining = 0;

        if (dur > 0)
        {
            static if (LIBRARY_TimerUtils) { t = NewTimer(); }
            else                           { t = CreateTimer(); }
            
            TimerStart(t, dur, false, null);
            timeRemaining = TimerGetRemaining(t);
            while (timeRemaining > 0)
            {
                if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) { TriggerSleepAction(0.1 * timeRemaining); }
                else { TriggerSleepAction(bj_POLLED_WAIT_INTERVAL); }

                timeRemaining = TimerGetRemaining(t);
            }
            
            static if (LIBRARY_TimerUtils) { ReleaseTimer(t); }
            else                           { DestroyTimer(t); }
        }

        t = null;
    }

    struct data
    {
        player           p;
        trigger          leave;
        trigger          enter;
        region           invis_detector;
        group            invis_units;
        triggercondition on_enter_cond;
        triggercondition on_leave_cond;

        method stop_revealing_invisible_units()
        {
            TriggerRemoveCondition(enter, on_enter_cond);
            DestroyTrigger(enter);
            TriggerRemoveCondition(leave, on_leave_cond);
            DestroyTrigger(leave);
 
            RemoveRegion(invis_detector);

            static if (LIBRARY_GroupUtils) { ReleaseGroup(invis_units); }
            else                           { DestroyGroup(invis_units); }

            destroy();
        }

        static method on_enter() -> boolean
        {
            integer i = 0;
            unit    u = null;
            data    d = 0;

            u = GetTriggerUnit();
            if (is_unit_dummy(u)) { u = null; return false; }

            d = LoadInteger(HT, GetHandleId(GetTriggeringTrigger()), 'entr');

            if (IsUnitEnemy(u, d.p) && IsUnitInvisible(u, d.p))
            {
                GroupAddUnit(d.invis_units, u);
                reveal_unit_for_player_and_his_allies(u, d.p);
                // for (0 <= i < bj_MAX_PLAYERS)
                // {
                //     if (IsPlayerAlly(Player(i), d.p))
                //     {
                //         UnitShareVision(u, Player(i), true);
                //     }
                // }
            }
        
            u = null;

            return false;
        }

        static method on_leave() -> boolean
        {
            integer i = 0;
            unit    u = null;
            data    d = 0; 

            u = GetTriggerUnit();
            if (is_unit_dummy(u)) { u = null; return false; }

            d = LoadInteger(HT, GetHandleId(GetTriggeringTrigger()), 'leav');

            if (IsUnitEnemy(u, d.p))
            {
                GroupRemoveUnit(d.invis_units, u);
                UnitRemoveAbility(u, REVEALER_BUFF_ID);
                // for (0 <= i < bj_MAX_PLAYERS)
                // {
                //     if (IsPlayerAlly(Player(i), d.p))
                //     {
                //         BJDebugMsg("removing vision");
                //         UnitShareVision(u, Player(i), false);
                //     }
                // }
            }
        
            u = null;
            
            return false;
        }

        static method create(player p, real x, real y, real radius) -> data
        {
            real width  = radius * 4.0 / 3.0;
            real hw     = width / 2.0;
            real cx     = x;
            real cy     = y;

            real r0_minx = cx - hw;
            real r0_miny = cy - hw;
            real r0_maxx = cx + hw;
            real r0_maxy = cy + hw;

            real r1_minx = r0_minx + width * 0.15;
            real r1_miny = r0_miny - width * 0.15;
            real r1_maxx = r0_maxx - width * 0.15;
            real r1_maxy = r0_miny;

            real r2_minx = r1_minx;
            real r2_miny = r0_maxy;
            real r2_maxx = r1_maxx;
            real r2_maxy = r0_maxy + width * 0.15;

            real r3_minx = r0_minx - width * 0.15;
            real r3_miny = r0_miny + width * 0.15;
            real r3_maxx = r0_minx;
            real r3_maxy = r0_maxy - width * 0.15;

            real r4_minx = r0_maxx;
            real r4_miny = r3_miny;
            real r4_maxx = r4_minx + width * 0.15;
            real r4_maxy = r3_maxy;

            real r5_minx = r0_minx + width * 0.3;
            real r5_miny = r0_miny - width * 0.225;
            real r5_maxx = r0_maxx - width * 0.3;
            real r5_maxy = r1_miny;

            real r6_minx = r5_minx;
            real r6_miny = r2_maxy;
            real r6_maxx = r5_maxx;
            real r6_maxy = r0_maxy + width * 0.225;

            real r7_minx = r0_minx - width * 0.225;
            real r7_miny = r0_miny + width * 0.3;
            real r7_maxx = r3_minx;
            real r7_maxy = r0_maxy - width * 0.3;

            real r8_minx = r4_maxx;
            real r8_miny = r7_miny;
            real r8_maxx = r0_maxx + width * 0.225;
            real r8_maxy = r7_maxy;

            real r9_minx = r1_minx - width * 0.10;
            real r9_miny = r0_miny - width * 0.10;
            real r9_maxx = r1_minx;
            real r9_maxy = r0_miny;

            real r10_minx = r0_minx - width * 0.10;
            real r10_miny = r3_miny - width * 0.10;
            real r10_maxx = r0_minx;
            real r10_maxy = r3_miny;

            real r11_minx = r1_maxx;
            real r11_miny = r9_miny;
            real r11_maxx = r11_minx + width * 0.10;
            real r11_maxy = r9_maxy;

            real r12_minx = r0_maxx;
            real r12_miny = r10_miny;
            real r12_maxx = r12_minx + width * 0.10;
            real r12_maxy = r10_maxy;

            real r13_minx = r10_minx;
            real r13_miny = r3_maxy;
            real r13_maxx = r10_maxx;
            real r13_maxy = r13_miny + width * 0.10;

            real r14_minx = r9_minx;
            real r14_miny = r0_maxy;
            real r14_maxx = r9_maxx;
            real r14_maxy = r14_miny + width * 0.10;

            real r15_minx = r12_minx;
            real r15_miny = r13_miny;
            real r15_maxx = r12_maxx;
            real r15_maxy = r13_maxy;

            real r16_minx = r11_minx;
            real r16_miny = r14_miny;
            real r16_maxx = r11_maxx;
            real r16_maxy = r14_maxy;

            data    d    = data.allocate();
            unit    u    = null;
            integer i    = 0;

            d.invis_detector = CreateRegion();

            SetRect(R, r0_minx, r0_miny,  r0_maxx,  r0_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r1_minx, r1_miny,  r1_maxx,  r1_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r2_minx, r2_miny,  r2_maxx,  r2_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r3_minx, r3_miny,  r3_maxx,  r3_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r4_minx, r4_miny,  r4_maxx,  r4_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r5_minx, r5_miny,  r5_maxx,  r5_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r6_minx, r6_miny,  r6_maxx,  r6_maxy);
            RegionAddRect(d.invis_detector, R);

            RegionAddRect(d.invis_detector, R);
            SetRect(R, r7_minx, r7_miny,  r7_maxx,  r7_maxy);

            SetRect(R, r8_minx, r8_miny,  r8_maxx,  r8_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r9_minx, r9_miny,  r9_maxx,  r9_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r10_minx, r10_miny, r10_maxx, r10_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r11_minx, r11_miny, r11_maxx, r11_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r12_minx, r12_miny, r12_maxx, r12_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r13_minx, r13_miny, r13_maxx, r13_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r14_minx, r14_miny, r14_maxx, r14_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r15_minx, r15_miny, r15_maxx, r15_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, r16_minx, r16_miny, r16_maxx, r16_maxy);
            RegionAddRect(d.invis_detector, R);

            SetRect(R, 0, 0, 0, 0);

            d.p = p;
            d.enter  = CreateTrigger();
            d.leave  = CreateTrigger();

            TriggerRegisterEnterRegion(d.enter, d.invis_detector, null);
            d.on_enter_cond = TriggerAddCondition(d.enter, cond_on_enter);

            TriggerRegisterLeaveRegion(d.leave, d.invis_detector, null);
            d.on_leave_cond = TriggerAddCondition(d.leave, cond_on_leave);

            SaveInteger(HT, GetHandleId(d.enter), 'entr', d);
            SaveInteger(HT, GetHandleId(d.leave), 'leav', d);

            // reveal invisible units that are present at the circular area
            // immediately after the call
            // 
            // note that there is no IsUnitInvisible check because
            // if the units were revelead by other means when the call was made
            // and shortyle after that it is gone, then the units will not be reveal properly
            //
            static if (LIBRARY_GroupUtils) 
            { 
                d.invis_units = NewGroup();     
                GroupUnitsInArea(tmpg, x, y, radius);
            }
            else
            { 
                d.invis_units = CreateGroup(); 
                GroupEnumUnitsInRange(tmpg, x, y, radius, null);
            }

            u = FirstOfGroup(tmpg);
            while (u != null)
            {
                if (!is_unit_dummy(u))
                {
                    if (IsUnitEnemy(u, d.p)) // && IsUnitInvisible(u, d.p)
                    {
                        reveal_unit_for_player_and_his_allies(u, d.p);
                    }
                    GroupAddUnit(d.invis_units, u);
                }
                // for (0 <= i < bj_MAX_PLAYERS)
                // {
                //     if (IsPlayerAlly(Player(i), d.p))
                //     {
                //         UnitShareVision(u, Player(i), true);
                //     }
                // }           
                GroupRemoveUnit(tmpg, u);
                u = FirstOfGroup(tmpg);
            }

            u = null;

            return d;
        }
    }

    public function scanner_sweep(player p, real x, real y, real radius, real dur, string effect_location)
    {
        fogmodifier fms[];
        unit        u = null;
        integer     i = 0;
        data        d = 0 ;
        effect      e = null;

        if (effect_location != "" || effect_location == null) { e = AddSpecialEffect(effect_location, x, y); }

        // when invisible enemy units enter the circular area
        // reveal them
        // when they leave, stop revealing them
        d = data.create(p, x, y, radius);

        // gotta admit that zinc loops are awesome
        for (0 <= i < bj_MAX_PLAYERS)
        {
            // reveal the circular area for the player and his allies
            // note that each player is considered an ally to himself
            if (IsPlayerAlly(Player(i), p))
            {
                fms<i> = CreateFogModifierRadius(Player(i), FOG_OF_WAR_VISIBLE, x, y, radius, true, false);
                FogModifierStart(fms<i>);
            }
        }

        // using a sleep because durations of &lt; 0.1 would
        // be senseless, note how the code is much &quot;saner&quot; this way
        // without timer attaching thingies; if only sleeps were accurate =)...
        
        // if the effect location is &quot;Abilities\\Spells\\Other\\Andt\\Andt.mdl&quot;, i.e
        // the default for the revealing abilities then the effect
        // has to be destroyed ~4 seconds before the end of the duration
        // to match the end of the revealing
        if (effect_location == &quot;Abilities\\Spells\\Other\\Andt\\Andt.mdl&quot;)
        {
            TSA(dur - 4);
            DestroyEffect(e);
            e = null;
            TSA(4);
        }
        else { TriggerSleepAction(dur); }

        // maybe an invisible unit entered the area but became visible before leaving
        // or it never left the area
        // 
        DisableTrigger(d.enter);
        DisableTrigger(d.leave);
        u = FirstOfGroup(d.invis_units);
        while (u != null)
        {
            UnitRemoveAbility(u, REVEALER_BUFF_ID);
            // for (0 &lt;= i &lt;= bj_MAX_PLAYERS)
            // {
            //     if (IsPlayerAlly(Player(i), d.p))
            //     {
            //         UnitShareVision(u, Player(i), false);
            //     }
            // }
            GroupRemoveUnit(d.invis_units, u);
            u = FirstOfGroup(d.invis_units);
        }

        d.stop_revealing_invisible_units();

        // stop revealing the circular area
        for(0 &lt;= i &lt; bj_MAX_PLAYERS)
        {
            if (fms<i> != null) { DestroyFogModifier(fms<i>); }
        }


        if (e != null) { DestroyEffect(e); }

        u = null;
        e = null;
    }

    function onInit()
    {
        xc              = xecast.createBasic(REVEALER_ID, DUST_OF_APPEARANCE_ORDER_ID, Player(15));
        R               = Rect(0, 0, 0, 0);
        cond_on_enter   = Condition(function data.on_enter);
        cond_on_leave   = Condition(function data.on_leave);
    }       

}


//! endzinc

</i></i></i></i>



The spell, FarSightBJ:

JASS:
scope FarSightBJ initializer init // requires xebasic, ScannerSweep, optional GroupUtils, optional TimerUtils
    
    globals
        constant integer ABIL_ID = &#039;A000&#039;
        constant string  EFFECT  = &quot;Abilities\\Spells\\Other\\Andt\\Andt.mdl&quot;
    endglobals
    
    function AoE takes integer lvl returns real
        // hm... should use the formula finder
        local real result = 0
        if 1 == lvl then
            set result = 600
        elseif 2 == lvl then
            set result = 1800
        else
            set result = 4000
        endif
        
        return result
    endfunction
    
    function duration takes integer lvl returns real
        return 0.0 * lvl + 8.0
    endfunction
    
    function FarSightBJ takes player p, real x, real y, real radius, real dur, string effect_location returns nothing
        call scanner_sweep(p, x, y, radius, dur, effect_location)
    endfunction
    
    function action takes nothing returns nothing
        local integer lvl = 0
        
        if ABIL_ID != GetSpellAbilityId() then
            return
        endif
        
        set lvl = GetUnitAbilityLevel(GetTriggerUnit(), ABIL_ID)
        call FarSightBJ(GetOwningPlayer(GetTriggerUnit()), GetSpellTargetX(), GetSpellTargetY(), AoE(lvl), duration(lvl), EFFECT)
    endfunction
    
    function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddAction(t, function action)
    endfunction
    
endscope
 

Attachments

  • FarSightBJ.w3x
    49.8 KB · Views: 398

Bribe

vJass errors are legion
Reaction score
67
TriggerSleepAction, onDestroy, what's with the region spamming?

Why suffix it with BJ?
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
Bribe:
1. TriggerSleepAction, onDestroy, what's with the region spamming?

2. Why suffix it with BJ?

1. TriggerSleepAction because a timer is not necessary in this case.
onDestroy becuase it will be called by the destroy method right?
And I really don't know where you found "region spamming".
Only 17 rects and 1 region are created for the duration of the spell.

2. Well... I've used this naming convention for spells replicating the functionality of spells
that can be found in the OE.
 

Laiev

Hey Listen!!
Reaction score
188
>>TriggerSleepAction because a timer is not necessary in this case.
Timer is always better then TSA.

>>onDestroy becuase it will be called by the destroy method right?
JASS:
method onDestroy takes nothing returns nothing
endmethod
/* &gt;&gt; */
method destroy takes nothing returns nothing
    call this.deallocate()
endmethod


>>Only 17 rects and 1 region are created for the duration of the spell.
Only? Are you serious?
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
Laiev:
1. Timer is always better then TSA.
2. Only? Are you serious?

1. Always... my a$$, a timer is only better for durations <= 0.1 because TriggerSleepActions becomes inaccurate.
For durations 0.1 >= it's much "saner"/simple to use the locals/arguments of the functions instead of the attaching...

2. You are complaining for 17 lightweight rects (lightweight compared to units) that are created only once for the whole duration.
I suppose you haven't seen a spell creating 32 dummies per second and using gamecache then.
 

Bribe

vJass errors are legion
Reaction score
67
Why does it need so many rects? Why not use [ljass]RegionAddCell[/ljass]?

TSA needs to be replaced by a PolledWait, mostly because of paused game issues (if you pause the game, the TSA still runs, screwing up the synch). And then PolledWait is bad creating and destroying a timer but not nulling the variable, but I think someone on TheHelper made a different kind of polled wait which runs fine.
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
i dont understand why you made this ability.
I know what it does, but why?
Why shouldnt we just use the far sight ability of the object editor? Unless you show some really useful stuff this script can do better then farsight i dont see the point of it.
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
Bribe:

1. Why does it need so many rects? Why not use RegionAddCell?
2. TSA needs to be replaced by a PolledWait, mostly because of paused game issues (if you pause the game, the TSA still runs, screwing up the synch). And then PolledWait is bad creating and destroying a timer but not nulling the variable, but I think someone on TheHelper made a different kind of polled wait which runs fine.

1. [ljass]native RegionAddCell takes region whichRegion, real x, real y returns nothing[/ljass]
How many calls do you need with this to make a circle with radius R? Seams inefficient to me.
2. I'll look for it.


Accname:

1. i dont understand why you made this ability.
I know what it does, but why?
Why shouldnt we just use the far sight ability of the object editor? Unless you show some really useful stuff this script can do better then farsight i dont see the point of it.

1. If someone wants to make something similar to this he won't be able with the OE's Far Sight.

JASS:
scope Invision initializer init // can&#039;t think of a better name =)

    constant integer ABIL_ID = &#039;A000&#039;
    constant string  EFFECT  = &quot;Abilities\\Spells\\Human\\Flare\\FlareCaster.mdl&quot;

    function AoE takes unit c, integer lvl returns real
        local real    time                    = GetFloatGameState(GAME_STATE_TIME_OF_DAY)
        local boolean has_goblin_night_scope  = GetInventoryIndexOfItemTypeBJ(c, &#039;tels&#039;) &lt; 1
        local real    day_inc_night_dec       = 0

        if time &gt;= 8.0 and time &lt;= 20.0 then
            // day
            set day_inc_night_dec = lvl * 100.0
        else
            // night
            if has_goblin_night_scope then
                set day_inc_night_dec = lvl * 100.0
            else
                set day_inc_night_dec = -(lvl * 100.0)      
            endif
        endif

        return lvl * 500 + day_inc_night_dec
    endfunction

    function duration takes unit c, int lvl returns real
        return GetHeroInt(c, false) / 5.0
    endfunction

    function action takes nothing returns nothing
        local unit    c   = null
        local integer lvl = 0

        if GetSpellAbilityId() != ABIL_ID then
            return
        endif

        set c   = GetTriggerUnit()
        set lvl = GetUnitAbilityLevel(c, ABIL_ID)
        call FarSightBJ(GetOwningPlayer(c), GetSpellTargetX(), GetSpellTargetY(), AoE(c, u), duration(c, u), EFFECT)

        set c = null
    endfunction

    function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddAction(t, function action)
    endfunction

endscope
 

Dirac

22710180
Reaction score
147
I find it funny that you suffix this with BJ since it means "Blizzard Jass"

Yes, i can make that spell by using a dummy far sight ability and setting its level accordingly to the AoE i desire, i think even using fog modifiers would do the trick. Other than that you really didn't explain what your example does
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
Dirac:
1. Yes, i can make that spell by using a dummy far sight ability and setting its level accordingly to the AoE i desire, i think even using fog modifiers would do the trick.
2. i think even using fog modifiers would do the trick
3. Other than that you really didn't explain what your example does
4. I find it funny that you suffix this with BJ since it means "Blizzard Jass"

1. Go ahead and make as many Far Sight levels as you want... it's your map to bloat with unnecessary abilities that slow loading time.
2. yeah that would do the trick of revealing the area, but what about revealing invisible/burrowed units?
3. =)... it's pretty obvious.
4. I'm glad it did [make you find it funny].
 

Dirac

22710180
Reaction score
147
For invisible units i would create a dummy with truesight, problem solved.
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
Dirac:
1. For invisible units i would create a dummy with truesight, problem solved.

1. Great ... now for every far sight level you would need a corresponding truesight level, and this can't take into account items units may have, stats, etc...
 

Dirac

22710180
Reaction score
147
It's the only way around it, using faerie fire will cause to fully share vision of the unit, even when the reveal AoE is lesser than the unit's current visibility radius, or if the unit is standing close to the border of the radius it would reveal more area than expected.
 

Bribe

vJass errors are legion
Reaction score
67
Fog modifier + dummy unit that uses a Bonus system to dynamically increase its sight radius. And creating a dummy for this is way lighter than creating one million rects.

Also, instead of dynamic creation/removal, you could use one global rect, spam the [ljass]SetRect[/ljass] function, because if you remove all rects associated with a region the region still remembers those rects, until you use [ljass]RegionClearCell[/ljass]/[ljass]RegionClearRect[/ljass].
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
Dirac:

1. It's the only way around it, using faerie fire will cause to fully share vision of the unit, even when the reveal AoE is lesser than the unit's current visibility radius, or if the unit is standing close to the border of the radius it would reveal more area than expected.

1. That is true, but Faerie Fire is the only method I know which will reveal individually an invisible unit to a player.

Bribe:
1. Fog modifier + dummy unit that uses a Bonus system to dynamically increase its sight radius. And creating a dummy for this is way lighter than creating one million rects.
2. Also, instead of dynamic creation/removal, you could use one global rect, spam the SetRect function

1. 17 != 10^6. You don't need "a Bonus system to dynamically increase its sight radius", the fogmodifier takes care of the revealing of area part. And you are forgetting about the revealing of invisible units part.

2. So lets see:

The way it is now is: 1 CreateRgion, 17 Rect, 17 RegionAddRect, 17 RemoveRect, 1 RemoveRegion calls are used.
The way you propose: 1 CreateRegion, 0 Rect (technically 1 at onInit), 17 RegionAddRect, 17 SetRect, 1 RemoveRegion calls to use.

So yeah this could be an optimization, but an unnecessary one because this is not a performance critical script that is called 32+ times per second.
 

Bribe

vJass errors are legion
Reaction score
67
Let me change my words, forget the fog modifier, use the dummy unit with true sight plus the modified goblin night scope to increase his vision (the goblin night scope is set to something like -10 radius, so adding and removing it adds 10 radius).
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
Bribe:

1. Let me change my words, forget the fog modifier, use the dummy unit with true sight plus the modified goblin night scope to increase his vision (the goblin night scope is set to something like -10 radius, so adding and removing it adds 10 radius).

1. "use the dummy unit with true sight" with true sight of radius what?... True Sight does not take into account the vision of the unit. It just reveals
invisible units in a circle with radius you specify in the OE.
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
Bribe:

1. I said true sight AND goblin night scope.

1. First of all there is no ability called goblin night scope (goblin night scope is an item and it uses an ability called Ultravision). The ability I think you a referring to is called Item Sight Range Bonus. And what this does is it modifies the sight range of the unit NOT it's detection of invisible units radius. You can have a unit with 0 sight range and 9999 True Sight radius and this will detect every invisible unit on the map.
 

Dirac

22710180
Reaction score
147
Truesight is the only way to go, even if 100 levels are required. Faerie Fire is just no, as i said in the post before it would greatly increase the reveal AoE
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top