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

Smoke of deceit

Status
Not open for further replies.
Level 11
Joined
Sep 11, 2013
Messages
324
Hello guys!
Can someone help me with this item which was made in dota 1 (smoke of deceit)
I really want to put this item into my map, but i don't know how to make a trigger that complex..
It is possible?

Upon activation, the user and all nearby allies and player controlled units gain smoked invisibility and bonus movement speed for a brief time. Minimap icons will also be hidden. Upon moving within range of an enemy hero or tower, the invisibility is lost.
Duration35
Smoke Radius1200
Break Radius1025
Charges1


*very important
  • Smoked units are not revealed by true sight.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
You could rip the system from DotA.

If that is not possible it sounds like the ability would be implemented using the target invisibility spell of the sorceress along with some sort of movement speed buff (item ability, or triggered system). The reveal would be done by periodically polling affected units for the reveal condition.

Not sure how to prevent the units being revealed by true sight. I recall that Warcraft III has different kinds of invisibility such as burrow, ability, e.t.c. As such it might be possible to select a specific kind of invisibility and set true sight to not reveal that kind.
 
Level 11
Joined
Sep 11, 2013
Messages
324
I don't know how to rip the system from dota and sadly i don't know to do such a trigger.
Where i can found dota open map?
The best part that i really want to make is to make an invisible unit who is not visible for true sight, but who become visible when a specific enemy unit is close to him.
 
I'm unsure how to handle the true-sight part, that sounds impossible to me, but you'd have to research all different invisibility and true-sight abilities to be sure.
Actually making the system is fairly complicated, but if you know vjass, I made a "CamouflageSystem" (based on League of Legends "Camouflage" mechanic) a while ago that could be tweaked to work for your needs. Note that this is something I developed for a specific map etc. and is currently not in a state where I would upload it to the "Spells" section of this website, but maybe can be useful, if you know vjass...

JASS:
/*
* System for League of Legends-style camouflage. 
* https://leagueoflegends.fandom.com/wiki/Stealth#Camouflage
* Basically, you are invisible while X range away from enemies.
* UPDATES_PER_TICK constant is used to control how many units the system processes per tick, meaning some control over performance impact of system, if many units are registered.
* 
* setSystemOn is used to globally turn this system on/off. Turning it off reveals any unit that was invisible (removing the "Undead - Ghost" ability, if they had it). 
*/
library CamouflageSystem
    globals
        private constant integer CAMOUFLAGE_INVIS_ABILITY = 'Agho' //"Undead - Ghost"-based ability for being able to cast while invis
        private constant real BASE_RANGE = 500.0
        private constant integer UPDATES_PER_TICK = 8   //If less that this many units have this ability, it does not matter. If more than this many units have this ability, only so many will be updated per tick.
        private constant real TICK_RATE = 0.03125000
    endglobals
    struct Camouflage
        private static thistype array camouflagedUnits
        private static boolean turnedOn = true
        private static integer k = -1
        private static integer loopIndex = 0
        private static timer t = CreateTimer()
        private unit source
        private real range
        method makeVisible takes nothing returns nothing
            call UnitRemoveAbility(source, CAMOUFLAGE_INVIS_ABILITY)
        endmethod
        method makeInvis takes nothing returns nothing
            call UnitAddAbility(source, CAMOUFLAGE_INVIS_ABILITY)
        endmethod
        method isInvis takes nothing returns boolean
            return GetUnitAbilityLevel(source, CAMOUFLAGE_INVIS_ABILITY) > 0
        endmethod
        method toggleInvis takes nothing returns nothing
            if isInvis() then
                call makeVisible()
            else
                call makeInvis()
            endif
        endmethod
        public static method setInvisibleForAll takes boolean invis returns nothing
            local integer i = 0
            if invis then
                loop
                    exitwhen i > k
                    call camouflagedUnits[i].makeInvis()
                    set i = i + 1
                endloop
            else
                loop
                    exitwhen i > k
                    call camouflagedUnits[i].makeVisible()
                    set i = i + 1
                endloop
            endif
        endmethod
        public method getRange takes nothing returns real
            return range
        endmethod
        public method setRange takes real newRange returns nothing
            set range = newRange
        endmethod
        method update takes nothing returns nothing
            local group unitsInRange = CreateGroup()
            local player owner = GetOwningPlayer(source)
            local unit u
            local real x = GetUnitX(source)
            local real y = GetUnitY(source)
            local boolean hasEnemiesInRange = false
            local boolean isInvis = isInvis()
            call GroupEnumUnitsInRange(unitsInRange, x, y, range, null)
            loop
                set u = FirstOfGroup(unitsInRange)
                exitwhen u == null
                if UnitAlive(u) and not IsUnitAlly(u, owner) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
                    set hasEnemiesInRange = true
                    exitwhen true
                endif
                call GroupRemoveUnit(unitsInRange,u)
            endloop
            call DestroyGroup (unitsInRange)
            set u = null
            set owner = null
            set unitsInRange = null
            if hasEnemiesInRange and isInvis then
                //call BJDebugMsg("invis Unit turned visible")
                call makeVisible()
            elseif not isInvis and not hasEnemiesInRange then
                //call BJDebugMsg("Visible Unit turned invis")
                call makeInvis()
            endif
        endmethod
        static method onPeriod takes nothing returns nothing
            local thistype this
            local integer processed = 0
            if loopIndex > k then
                if k == -1 then
                    call PauseTimer(t) //Nothing to update!
                endif
                set loopIndex = 0
            else
                loop
                    exitwhen processed == UPDATES_PER_TICK or loopIndex > k
                    set processed = processed + 1
                    set this = camouflagedUnits[loopIndex]
                    if UnitAlive(source) then
                        call update()
                    else
                        set loopIndex = remove(loopIndex)
                    endif
                    set loopIndex = loopIndex + 1
                endloop
            endif
        endmethod
        public static method setSystemOn takes boolean newTurnedOn returns nothing
            if not (turnedOn == newTurnedOn) then
                if turnedOn and not newTurnedOn then
                    set turnedOn = false
                    call PauseTimer(t)
                    call setInvisibleForAll(false)
                else
                    set turnedOn = true
                    if k > -1 then
                        call TimerStart(t, TICK_RATE, true, function thistype.onPeriod)
                    endif
                endif
            endif
        endmethod
        static method register takes unit u returns nothing
            local thistype this = allocate()
            set .source = u
            set .range = BASE_RANGE
            set k = k + 1
            set camouflagedUnits[k] = this
            if turnedOn and k == 0 then
                call TimerStart(t, TICK_RATE, true, function thistype.onPeriod)
            endif
        endmethod
        static method remove takes integer i returns integer
            local thistype this = camouflagedUnits[i]
            set camouflagedUnits[i] = camouflagedUnits[k]
            set k = k - 1
            set source = null
            call .deallocate()
            if k == -1 then
                call PauseTimer(t)
            endif
            return i - 1
        endmethod
    endstruct
endlibrary
 
Status
Not open for further replies.
Top