Unit Illusion System

Dirac

22710180
Reaction score
147
Provides the UnitCreateIllusion function (takes unit whichUnit, boolexpr action)
JASS:
library Illusion initializer onInit
    // external ObjectMerger w3a AIil UIEa anam "Illusion Create" atar 1 "notself" atat "" aart "" ahdu 1 0 adur 1 0 aran 1 100000
    globals
        private constant integer DUMMY='e000'
        
        private constant integer OFFSET=0x100000
        private trigger array callback
        public unit Get
    endglobals
    function UnitCreateIllusion takes unit whichUnit,boolexpr action returns nothing
        local unit u=CreateUnit(GetOwningPlayer(whichUnit),DUMMY,GetUnitX(whichUnit),GetUnitY(whichUnit),0)
        local integer id=GetHandleId(u)-OFFSET
        set callback[id]=CreateTrigger()
        call UnitAddAbility(u,'UIEa')
        call IssueTargetOrderById(u,852274,whichUnit)
        call TriggerAddCondition(callback[id],action)
        set u=null
    endfunction
    private function onCreate takes nothing returns boolean
        local unit c=GetSummoningUnit()
        local unit t=GetSummonedUnit()
        local integer id
        if GetUnitTypeId(c)==DUMMY then
            set id=GetHandleId(c)-OFFSET
            set Get=t
            call TriggerEvaluate(callback[id])
            call DestroyTrigger(callback[id])
        endif
        return false
    endfunction
    
    private function onInit takes nothing returns nothing
        local trigger trig=CreateTrigger()
        local integer i=0
        call TriggerAddCondition(trig,Condition(function onCreate))
        loop
            call TriggerRegisterPlayerUnitEvent(trig,Player(i),EVENT_PLAYER_UNIT_SUMMON,null)
            set i=i+1
            exitwhen i==bj_MAX_PLAYER_SLOTS
        endloop
        set trig=null
    endfunction
endlibrary

Example usage
JASS:
private function forIllusion takes nothing returns boolean
call DestroyEffect(AddSpecialEffect("boom",GetUnitX(Illusion_Get),GetUnitY(Illusion_Get))
return false
endfunction
private function create takes nothing returns nothing
call UnitCreateIllusion(someUnit,Filter(function forIllusion))
endfunction

Will display effect "boom" everytime an illusion is created.

Yes, it uses trigger evaluations, that's just awful
Yes, it's very inaccurate, not my fault, most likely the editor's fault for not having this as a native.
Yes, the action function fired when an illusion is created must return a boolean, any way to fix this without creating leaks.

PLEASE feedback
 

Jedi

New Member
Reaction score
63
I can get illusion next line with this.
JASS:
//No need to create dummy for each call, 1 dummy unit is enough.
globals
    unit lastCreatedIllusion = null
    
    constant integer ILLUSION_ABILITY_ID = 'AIil'
    constant integer DUMMY_ID = 'e000'
endglobals

function CatchIllusion takes nothing returns nothing
    call BJDebugMsg("Summon fired!")
    if GetUnitTypeId(GetSummoningUnit()) == DUMMY_ID then
        set lastCreatedIllusion = GetSummonedUnit()
    endif
endfunction

function Test takes nothing returns nothing
    local unit dummy
    set bj_lastCreatedUnit = CreateUnit(Player(0), 'hfoo', 0, 0, 270)
    set dummy = CreateUnit(Player(0),DUMMY_ID, 0, 0, 0)
    call UnitAddAbility(dummy, ILLUSION_ABILITY_ID)
    call SetUnitX(dummy, GetUnitX(bj_lastCreatedUnit))
    call SetUnitY(dummy, GetUnitY(bj_lastCreatedUnit))
    call IssueTargetOrderById(dummy, 852274, bj_lastCreatedUnit)
    call BJDebugMsg(GetUnitName(lastCreatedIllusion))
endfunction

//===========================================================================
function InitTrig_Melee_Initialization takes nothing returns nothing
    local trigger catch = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(catch, EVENT_PLAYER_UNIT_SUMMON)
    call TriggerAddAction(catch, function CatchIllusion)
    call TimerStart(CreateTimer(), 1.00, false, function Test)
endfunction


Edit:Wait... this only works if my footman has ghost(visible) ability lol.

Edit2:yeah yeah my mistake, updated code.
 

tooltiperror

Super Moderator
Reaction score
231
JASS:
function UnitCreateIllusion takes unit caster returns unit
    local unit hook  = CreateUnit(Player(0), 'hfoo', 0, 0, 270)  // Hook now points to the newest Handle Id, for example's sake 0x100A193
    call RemoveUnit(hook)                                        // Hook still points to 0x100A193, but 0x100A193 is now free

    call MakeUnitCastSummon(caster)                              // Blademaster casts illusion, the illusion gets next free Handle Id: 0x100A193
    
    return hook
endfunction

function IllusionTest_Actions takes nothing returns boolean
    local unit illusion  = CreateUnit(Player(0), 'Oblm', 0, 0, 270)  // Make a blademaster
    set illusion         = UnitCreateIllusion(blademaster)           // illusion is now its illusion

    // Do anything with "illusion"
    // hacking by handle Id is fun

    return false
endfunction

function InitTrig_IllusionTest takes nothing returns nothing
    local trigger trig = CreateTrigger()
    
    call TriggerAddCondition(trig, Condition(function IllusionTest_Actions))
    call TriggerEvaluate(trig)
endfunction


I've tested a similar concept with Images, only to find that a fellow from WC3C had discovered the hack before I did (damn TTE is always late) a friend of mine discovered a similar hack with lightning.

Untested, but I believe it would work. I may make this into my own system, that returns a dynamic array.
 

Nestharus

o-o
Reaction score
84
That would work if the handle id was recycled immediately, but it's recycled right after the JASS code, so you'd get an invalid handle id right there.


And to Dirac, don't use offsets.


This should also be using LUA_GET_VAR_OBJECT
-> [ljass]//! external ObjectMerger w3a AIil UIEa anam "Illusion Create" atar 1 "notself" atat "" aart "" ahdu 1 0 adur 1 0 aran 1 100000[/ljass]


Unless you like unsafe object generation
 

Jedi

New Member
Reaction score
63
^^How much time did you edit that :p

Final version
JASS:
library Illusion initializer Init

globals

    private constant integer DUMMY_ID = 'e000'

    private unit Dummy
    private unit lastCreatedIllusion

endglobals

function UnitCreateIllusion takes unit u, integer abilityId returns unit
    call UnitAddAbility(Dummy, abilityId)
    call SetUnitX(Dummy, GetUnitX(u))
    call SetUnitY(Dummy, GetUnitY(u))
    call SetUnitOwner(Dummy, GetOwningPlayer(u), false)
    call IssueTargetOrderById(Dummy, 852274, u)
    call UnitRemoveAbility(Dummy, abilityId)
    return lastCreatedIllusion
endfunction

private function DetectIllusion takes nothing returns boolean
    if GetUnitTypeId(GetSummoningUnit()) == DUMMY_ID then
        set lastCreatedIllusion = GetSummonedUnit()
    endif
    return false
endfunction

private function Init takes nothing returns nothing
    local trigger detect = CreateTrigger()
    set Dummy = CreateUnit(Player(15), DUMMY_ID, 0, 0, 0)
    call TriggerRegisterAnyUnitEventBJ(detect, EVENT_PLAYER_UNIT_SUMMON)
    call TriggerAddCondition(detect, Condition(function DetectIllusion))
endfunction

endlibrary

View attachment Illusion.w3x
 

Dirac

22710180
Reaction score
147
@Jedi, your code doesn't work, the illusion isn't created when you order the unit to cast it, it's created a few moments after that. That's why my code is like that, test it yourself

@tooltiperror if the handle of the illusion is used before the blademaster finishes casting the illusion it would bug the system. For this system instead of a blademaster should be used a item illusion ability i believe right?
the MakeUnitCastSummon is something you typed instead of actually ordering the unit to use the ability? or is that function supposed to do something lol.

@Nestharus not everyone uses LUA. Another option would be using Table to safely store unit's handles. On your comment to tooltiperror, the handle IS recycled since the illusion isn't casted along the code, it's casted shortly after that, so it returns the handle of a nonexistant unit for later use, would cause bugs if you intend to do actions to your illusions right after you created, this is the reason of why i'm using trigger evaluations, to actually wait for the illusion to be created.

Im sorry but all of the feedback posted above serves me no use, but Nes's suggestion to avoid unsafe handle offset.
 

Dirac

22710180
Reaction score
147
EDIT: hmm it seems to work fine.
Maybe creating the dummy everytime the illusion needs to be created slows down the whole "cast illusion on unit" action.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top