1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Dismiss Notice
  3. After a long wait, the results for Terraining Contest #18 are finally out! Drop by and congratulate the winners!
    Dismiss Notice
  4. The poll for Concept Art Contest #9 is up! Cast your vote for your favourite entry!
    Dismiss Notice
  5. Hero Contest #8 is up and running! This time it's a joint contest between artists and coders. Go here for team matchmaking.
    Dismiss Notice
  6. Our first StarCraft contest, The Galaxy Terraining Contest #1 - World Wonders has started. Enter to show off your Galaxy Editor skills and win a custom rank icon among other things.
    Dismiss Notice
  7. Ever wanted to get your sets ready for fast texturing while still having fun? Now it is possible with our newest Mini-Texturing Contest.
    The Skeleton Units need your dire help!
    Dismiss Notice
  8. The poll for Techtree Contest #11 is up! Cast your vote for your favorite entry.
    Dismiss Notice
  9. Take part in a Futuristic musical experience with our very own Music Contest. The 5th edition has finally arrived after a long time.
    Dismiss Notice
  10. Dismiss Notice

[Snippet] MUI DummyCasters

Discussion in 'Graveyard' started by mckill2009, Feb 11, 2012.

  1. mckill2009

    mckill2009
    Joined:
    Mar 10, 2009
    Messages:
    4,681
    MUIDummyCasters


    • - You may find the GUI version of this in >>> [thread=235236]MUI DummyCaster[GUI] [/thread]
      - Creates only 1 dummy for instant spells like firebolt, carrion swarm, banish, etc
      - Supports channel spells by creating another dummy to channel the spell like flamestrike, starfall, blizzard, etc
      - You may control the point where the dummy is created and cast to a target or location where you can see the projectile is traveling

    • Code (vJASS):

      library MUIDummyCasters /* v4.4a */ initializer Init /*
      *************************************************************************************
      *
      *   by mckill2009
      *
      *************************************************************************************
      *
      *   Creates only 1 dummy for instant spells like firebolt, carrion swarm, banish, etc
      *   Supports channel spells by creating another dummy to channel the spell like flamestrike, starfall, blizzard, etc
      *   You may control the point where the dummy is created and cast to a target or location where you can see the projectile is traveling
      *
      *************************************************************************************
      *
      *   Credits
      *
      *       Bribe
      *       -----------------------
      *           For info about the 'Amov' ability remove
      *
      *       Nesthaurus
      *       -----------------------
      *           For his Comment header
      *
      *************************************************************************************
      *
      *   */
      uses /*
      *  
      *       */
      Table        /* [url]http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/[/url]
      *
      ************************************************************************************
      *  
      *   Installation
      *       - Copy ALL that is in the "MUIDummyCasters" folder to your map.
      *       - Copy the Table library to your map.
      *       - Replace the rawID of the DUMMY_CASTER if needed, you may view it via pressing CTRL+D in the object editor.  
      *
      ************************************************************************************
      *
      *   GLOBALS
      *
      */

      globals
          /*
          *   Change the DUMMY_CASTER raw code if needed
          */

          private constant integer     DUMMY_CASTER = 'h000'
          /*
          *   Constant globals, never touch these!
          */

          private Table c
          private constant player             OWNER = Player(15)
          private group                   DummyTake = CreateGroup()
          private unit                        Dummy = null  
          /*
          *   TEST is for testing duh!, set to true to display how many
          *   dummies are created, set to false to disable it
          */

          private constant boolean TEST = true
          private integer DummyCount = 0
      endglobals

      /*
      ************************************************************************************
      *
      *   Functions
      *  
      *       function MDCCast takes player owningPlayer, real xDummy, real yDummy, integer abilityID, integer orderID, integer level returns nothing
      *       function MDCCastToPoint takes player owningPlayer, real xDummy, real yDummy, real xTarget, real yTarget, integer abilityID, integer orderID, integer level returns nothing
      *       function MDCCastToTarget takes  player owningPlayer, unit target, real xDummy, real yDummy, integer abilityID, integer orderID, integer level returns nothing
      *
      *   Function Parameter Description
      *       player owningPlayer
      *           - the owner of the casting unit
      *
      *       unit target (unit)
      *           - the spelltarget, used only by MDCCastToTarget
      *
      *       real xDummy and yDummy
      *           - the point/coordinate where the dummy will be placed
      *
      *       real xTarget and yTarget
      *           - the point/coordinate where the dummy cast the spell
      *           - used only by MDCCastToPoint
      *
      *       integer abilityID
      *           - the raw code of of the ability being cast by the dummt caster
      *
      *       integer orderID
      *           - the orderID of the abilityID
      *
      *       integer level
      *           - the level of the abilityID
      *
      *
      */

      //! textmacro ISSUE takes order
          local unit dum = GetDummyUnit()
          call UnitAddAbility(dum, abilityID)
          call SetUnitAbilityLevel(dum, abilityID, level)
          call SetUnitOwner(dum, owningPlayer, false)
          call SetUnitX(dum, xDummy)
          call SetUnitY(dum, yDummy)
          call Issue$order$
          set c[GetHandleId(dum)] = abilityID
          /*
          *   This is just a fail safe, in case the target is invulnerable, invisible or cannot be casted
          */

          if GetUnitCurrentOrder(dum)==0 then  
              call RefreshDummyUnit(dum)
          endif
          set dum = null
      //! endtextmacro

      private function RefreshDummyUnit takes unit d returns nothing        
          call SetUnitOwner(d, OWNER, false)
          call UnitRemoveAbility(d, c[GetHandleId(d)])
          call GroupAddUnit(DummyTake, d)
      endfunction
         
      private function GetDummyUnit takes nothing returns unit
          if FirstOfGroup(DummyTake)==null then
              set Dummy = CreateUnit(OWNER, DUMMY_CASTER, 0, 0, 0)
              call UnitRemoveAbility(Dummy,'Amov')
              static if TEST then
                  set DummyCount = DummyCount + 1
                  call BJDebugMsg("Dummies Created = "+I2S(DummyCount))
              endif
          else
              /*
              *   if group is not empty then it will pick the first dummy in the group
              *   I've used this above indexing to be.....different XD...
              */

              set Dummy = FirstOfGroup(DummyTake)
              call GroupRemoveUnit(DummyTake, Dummy)    
          endif
          return Dummy
      endfunction
         
      private function CastEnd takes nothing returns boolean
          /*
          *   Checks the caster if he belongs in this system instead of
          *   checking the unit type (which bugs)
          */

          if c.has(GetHandleId(GetTriggerUnit())) then
              call RefreshDummyUnit(GetTriggerUnit())
          endif
          return false
      endfunction
             
      private function Init takes nothing returns nothing
          local trigger t = CreateTrigger()
          /*
          *   Preloading only to avoid first time lag
          */

          local unit u = CreateUnit(OWNER, DUMMY_CASTER, 0, 0, 0)
          call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_ENDCAST)
          call TriggerAddCondition(t, Condition(function CastEnd))    
          set c = Table.create()
          call KillUnit(u)
          call RemoveUnit(u)
          set t = null
          set u = null
      endfunction

      /*
      *   This the main core system, 3 API you may use
      */

      function MDCCast takes player owningPlayer, real xDummy, real yDummy, integer abilityID, integer orderID, integer level returns nothing
          //! runtextmacro ISSUE("ImmediateOrderById(dum, orderID)")
      endfunction

      function MDCCastToPoint takes player owningPlayer, real xDummy, real yDummy, real xTarget, real yTarget, integer abilityID, integer orderID, integer level returns nothing
          //! runtextmacro ISSUE("PointOrderById(dum, orderID, xTarget, yTarget)")
      endfunction

      function MDCCastToTarget takes  player owningPlayer, unit target, real xDummy, real yDummy, integer abilityID, integer orderID, integer level returns nothing
          //! runtextmacro ISSUE("TargetOrderById(dum, orderID, target)")
      endfunction

      endlibrary
       


      • MDCCast
        • Events
          • Time - Every 0.10 seconds of game time
        • Conditions
        • Actions
          • Custom script: set udg_a = udg_a + 1.04
          • Custom script: call MDCCast(Player(1), 0+300*Cos(udg_a), 0+300*Sin(udg_a), 'AHtc', 852096, 1)

      • MDCCastToPoint CHANNEL
        • Events
          • Time - Every 1.00 seconds of game time
        • Conditions
        • Actions
          • Custom script: set bj_wantDestroyGroup=true
          • Unit Group - Pick every unit in (Units within 2000.00 of loc1 matching ((Unit-type of (Matching unit)) Equal to Peasant)) and do (Actions)
            • Loop - Actions
              • Custom script: call MDCCastToPoint(Player(0), 0,0, GetUnitX(GetEnumUnit()), GetUnitY(GetEnumUnit()), 'ACfs', 852488, 1)


      Code (vJASS):

      scope LTest initializer init

      private function Actions takes nothing returns nothing
          local player p = Player(0)
          local unit target
          local group g = CreateGroup()
          call GroupEnumUnitsInRange(g, 0,0, 2500, null)    
          loop
              set target=FirstOfGroup(g)
              exitwhen target==null
              if IsUnitEnemy(target,p)then
                  call MDCCastToTarget(p, target, 0,0,'ACfb',852231,1)  
              endif
              call GroupRemoveUnit(g,target)
          endloop
          call DestroyGroup(g)
          set g = null
      endfunction

      private function init takes nothing returns nothing
          local trigger t = CreateTrigger()
          call TriggerRegisterTimerEvent(t, 1.00, true)
          call TriggerAddAction(t, function Actions)
          set t = null
      endfunction

      endscope
       


    • v4.4a
      - Fixed a bug when checking the unit type if spell is finished.

      v4.4
      - LUA object merger removed
      - Struct API's replaed by functions
      - RegisterPlayerPlayerUnit requirement removed
      - Readable functions
      - Preloading dummy added

      v4.3
      - Fixed a very large bug that everytime the spell ends, ALL casters will be Player(15)
      - Lua object name changed from 'dumy' to 'xcvb' and has a warning message inside the code only

      v4.2
      - Changed to struct syntax
      - Added LUA object creator for dummy
      - Added a fail safe cast in case the target is not targetable
      - Codes and varibales reduced

      v4.1
      - Added ForGroup looper instead of Timer

      v4.0
      - Removed TimerUtils and IsUnitChanneling
      - Added Hashtable to save the ability of the dummy then remove it
      - Added END CAST code

      v3.0a
      - Fixed unithandle leak
      - API explanations added

    • - Bugs if the MDCCastToPoint and MDCCastToTarget is unreachable.
      - Bugs when checking the unit type if spell is finished (fixed).
     

    Attached Files:

    Last edited: Jul 6, 2013
  2. jim7777

    jim7777
    Joined:
    May 27, 2009
    Messages:
    481
    add
    debug
    before
    call BJDebugMsg
    if you want that function to be for debugging purposes only.

    This can be useful for multiple usage of a dummy ability (like for a group) since not all abilities are instant cast (no animation wait)
     
  3. Alain.Mark

    Alain.Mark
    Joined:
    Apr 27, 2011
    Messages:
    185
  4. mckill2009

    mckill2009
    Joined:
    Mar 10, 2009
    Messages:
    4,681
    @jim
    no, I want the text to be displayed in debug mode or not, so that the user can see it 100%
    if he made the input wrong...

    @Alain
    as you have said "for instant spells", well this is not ONLY for instant spells but for
    multiple instant and non-instant spells, the thing is there are some spells which is not
    instant like FlameStrike which has a delay, and btw your looping code doesnt work coz
    even though the casting time is 0, loops are faster to execute, not to mention the
    turning around of the dummy which takes time...

    but I may however put this in 3 API's coz right now I dont like the long code parameters...
     
  5. Alain.Mark

    Alain.Mark
    Joined:
    Apr 27, 2011
    Messages:
    185
    my looping code is only for multicasting instant spells. (it works)

    btw what i meant earlier was my code only uses one dummy caster when casting MULTIPLE times (for instant spells) and recycles dummy casters when casting MULTIPLE times (for channeled/timed spells). try it. it is faster and more efficient since it doesn't use timers and attaching. i meant my post earlier specifically for my libs "CastOnAreaLvl" function.
     
  6. mckill2009

    mckill2009
    Joined:
    Mar 10, 2009
    Messages:
    4,681
    already OffTopic

    I dont think so, the 'w' is always 0 at first so if multiple times at first then it will create also multiple times...
    The caster also is at the location of the target, what if the user wants it as a missile unit-target-spell, from angle of
    caster and target, surely the system doesnt support that...

    and again, my system supports instant and non-instant spells alike :)...

    anyway v2.0 is out, the thing is, this system is very simple to use with only 3 API's and doesnt use indexing...
     
  7. Alain.Mark

    Alain.Mark
    Joined:
    Apr 27, 2011
    Messages:
    185
    you're cutting my quote (ur like the media) >.< it only uses one dummy caster FOR INSTANT SPELLS (because they get recycled and retrieved again instantly when the spell finishes)
     
  8. mckill2009

    mckill2009
    Joined:
    Mar 10, 2009
    Messages:
    4,681
    as I said this is already off topic so let me respond to your thread with the FULL quote...
     
  9. Bribe

    Bribe

    Code Moderator

    Joined:
    Sep 26, 2009
    Messages:
    7,339
  10. mckill2009

    mckill2009
    Joined:
    Mar 10, 2009
    Messages:
    4,681
    casting only requires 3 (target, point and none) not 8, plus you can see that this has a
    very simple and short code...
     
  11. Bribe

    Bribe

    Code Moderator

    Joined:
    Sep 26, 2009
    Messages:
    7,339
    His uses way fewer dummy units to achieve the same thing. Code size is important but his code is pretty compressed and does way more.
     
  12. mckill2009

    mckill2009
    Joined:
    Mar 10, 2009
    Messages:
    4,681
    but it doesnt support missile-like target, from source to destination...

    some, yes but not all the time...

    sample, Blizzard...
    • Channeled
      • Events
        • Time - Every 1.00 seconds of game time
      • Conditions
      • Actions
        • Custom script: set bj_wantDestroyGroup=true
        • Unit Group - Pick every unit in (Units within 2000.00 of loc1 matching ((Unit-type of (Matching unit)) Equal to Peasant)) and do (Actions)
          • Loop - Actions


    this creates only 16 units with a 1 sec delay...
    • Custom script: call HitPoint(Player(0), 0,0, GetUnitX(GetEnumUnit()), GetUnitY(GetEnumUnit()), 'AHbz', 852089, 1)


    this creates 56 units...
    • call CastOnArea(AllocateCaster(Player(0)), GetUnitX(GetEnumUnit()), GetUnitY(GetEnumUnit()), 10, 'AHbz', 852089, false)
     
  13. Bribe

    Bribe

    Code Moderator

    Joined:
    Sep 26, 2009
    Messages:
    7,339
    I'll add this to my list of things to test out, I guess. I'd rather have one system for this stuff because it's bad enough having to require a casting system in the first place.

    Having support for instant abilities is the main thing, because you add the ability, issue the order, remove the ability, that way the ability will fire from the current thread allowing you to issue multiple casts from a single dummy within one thread.
     
  14. mckill2009

    mckill2009
    Joined:
    Mar 10, 2009
    Messages:
    4,681
    having ONE dummy for all instant spell isnt gonna work, I've tested it like this,
    and the dummy unit wont fire, even if the cooldown is negative, the spell
    will take time to fire, not to mention the 'turning' around of the dummy unit,
    loops to remove the spell takes almost instant, unless the spell is faster than loops to cast...
    Code (vJASS):

    function ActionsL takes nothing returns nothing
        local unit dummy = CreateUnit(Player(0), 'h000', 0,0,0)
        local unit target
        local group g = CreateGroup()
        call GroupEnumUnitsInRange(g, 0,0, 2500, null)    
        loop
            set target=FirstOfGroup(g)
            exitwhen target==null
            call GroupRemoveUnit(g,target)
            if IsUnitEnemy(target,Player(0))then
                call BJDebugMsg("not working!")
                call UnitAddAbility(dummy,'ACfb')
                call IssueTargetOrderById(dummy,OrderId("Firebolt"),target)
                call UnitRemoveAbility(dummy,'ACfb')
            endif
        endloop
        call DestroyGroup(g)
        set g = null
        set dummy = null
    endfunction

    function InitTrig_LoopTestFAIL takes nothing returns nothing
        set gg_trg_LoopTestFAIL = CreateTrigger()
        call TriggerRegisterTimerEvent(gg_trg_LoopTestFAIL, 1.00, false)
        call TriggerAddAction( gg_trg_LoopTestFAIL, function ActionsL)
    endfunction
     
     
  15. Bribe

    Bribe

    Code Moderator

    Joined:
    Sep 26, 2009
    Messages:
    7,339
    The dummy unit must have the 'Amov' ability removed, as well. Its cast point/backswing must be 0, and the spell's cast time must be 0.
     
  16. mckill2009

    mckill2009
    Joined:
    Mar 10, 2009
    Messages:
    4,681
    OK I didnt know about the 'Amov', but even so, many spells are not instant...
     
  17. Adiktuz

    Adiktuz
    Joined:
    Oct 16, 2008
    Messages:
    9,700
    so far on all spells I've tried, this method makes them instant cast...
     
  18. Bribe

    Bribe

    Code Moderator

    Joined:
    Sep 26, 2009
    Messages:
    7,339
    For non-instant spells, just allocate a new caster.
     
  19. mckill2009

    mckill2009
    Joined:
    Mar 10, 2009
    Messages:
    4,681
    Update v3.0
    - Added IsUnitChanneling by Magtheridon96
    - Delay is now periodic to check IsUnitChanneling

    now it can create only 8 units instead of 16 based on post #16...
     
  20. Laiev

    Laiev
    Joined:
    Oct 11, 2008
    Messages:
    265
    Code (vJASS):

    API:
    call HitTarget(.........
    call HitPoint(.........
    call HitNone(.........
    - Really self explanatory, see the code below.
     


    Really?

    '.........' is not a 'self explanatory', also, people will not read your code just to know the API, this is just stupid when I just want to know what is the arguments of your functions.