1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. The Lich King demands your service! We've reached the 19th edition of the Icon Contest. Come along and make some chilling servants for the one true king.
    Dismiss Notice
  4. The 4th SFX Contest has started. Be sure to participate and have a fun factor in it.
    Dismiss Notice
  5. The poll for the 21st Terraining Contest is LIVE. Be sure to check out the entries and vote for one.
    Dismiss Notice
  6. The results are out! Check them out.
    Dismiss Notice
  7. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  8. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    Dismiss Notice
  9. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[Trigger] Getting a unit inside a trap

Discussion in 'Triggers & Scripts' started by Saishy, Feb 4, 2009.

  1. Saishy

    Saishy

    Joined:
    Mar 23, 2008
    Messages:
    947
    Resources:
    0
    Resources:
    0
    Hey, its me again!

    Sorry for the tons of questions but I'm trying to finish my map before the vacation's end and I'm rushing it xD

    I'm trying to do a trap-spell that places some wards in the floor, once you active the trap a lighting line connect each piece with the center, if there is a unit in the center of the trap (50 radius circle in the middle) the unit is stunned and then the whole thing explodes dealing area damage to everyone.

    [​IMG]

    All the 5 traps are in the same group, but I can't figure how I can detect a unit in the middle of the trap.
    Any idea? Better than mine?*

    Thanks in advance!

    *My idea was using a global location or real array to point to the middle...
     

    Attached Files:

  2. Avator

    Avator

    Joined:
    Aug 23, 2008
    Messages:
    2,309
    Resources:
    1
    Tutorials:
    1
    Resources:
    1
    Place a dummy unit in the center of the trap. If a unit comes in range of the dummy: Activate the trap.

    To get the center of the trap, make:
    • Set TempPoint[1] = Position of Ward1 - (any ward you want)
    • Set TempPoint[2] = Position of Ward2 - (a ward standing next to Ward1)
    • Set TempPoint[3] = Position of Ward3 - (the ward on the oppisite side of the circle of Ward1 and Ward2)
    • Set TempPoint[4] = TempPoint[1] offset by ((Distance between TempPoint[1] and TempPoint[2]) / 2) towards (Angle from TempPoint[1] towards TempPoint[2])
    • Set TempPoint[5] = TempPoint[3] offset by ((Distance between TempPoint[3] and TempPoint[4]) / w) towards (Angle from TempPoint[3] towards TempPoint[4])

    TempPoint[5] is the center (or as close as you can get without too much trouble) of the trap.
     
  3. Saishy

    Saishy

    Joined:
    Mar 23, 2008
    Messages:
    947
    Resources:
    0
    Resources:
    0
    The user needs to use an ability of the hero to active the trap.

    Edit:
    Its not like I can pick the ward I wanna.
     
  4. Avator

    Avator

    Joined:
    Aug 23, 2008
    Messages:
    2,309
    Resources:
    1
    Tutorials:
    1
    Resources:
    1
    How about making the trap a dummy building? Then you can still check if a unit comes in range, you can (if you want) make the building model, those 5 wards, and the center of the trap is already set!
     
  5. Vegavak

    Vegavak

    Joined:
    Mar 16, 2006
    Messages:
    1,010
    Resources:
    0
    Resources:
    0
    What I would do:

    Have a script that checks when a trap is made: If there are any unit-type traps nearby.

    For every other trap within range, create invisible units every X meters towards that target until it reaches. Expiration time on those units = trap duration. Then a trigger that checks for overlapping invisible units. So in your case, if you NEED 5 traps to encircle, you would look for 5 invisible units within X range of each other. When each invisible unit is created, you would be checking for overlaps, and when there are 5 invisible units within X range of each other, you would be doing whatever the trap did and removing the traps/invisible units within range.

    That's how I would get it done for now. Think of it like drawing a dotted line between every trap, and finding points where those dotted lines overlap. It becomes much easier when you visualize it this way.
     
  6. Saishy

    Saishy

    Joined:
    Mar 23, 2008
    Messages:
    947
    Resources:
    0
    Resources:
    0
    lol o.o
    I still think its better to use x,y array o.o
     
  7. Vegavak

    Vegavak

    Joined:
    Mar 16, 2006
    Messages:
    1,010
    Resources:
    0
    Resources:
    0
    The choice is yours to make. I looked at your picture, saw dotted lines in my head, and thought of how I would create those dotted lines, while checking for overlapping, but what do I know?
     
  8. Soga-

    Soga-

    Joined:
    Jul 20, 2008
    Messages:
    374
    Resources:
    0
    Resources:
    0
    I assume the center of the traps is where the hero that laid the traps originally was. So you can just save to a variable the position of the casting unit as the center point, and then when the traps are activated, pick all units within say, 200 of that center point (I suggest 200 because 50 is waaay too tiny, that's way smaller than even the visible radius of most units) and then depending on if you want the traps to hit multiple units clumped up in the center or just one, do an unit group loop OR pick a random unit from that group. For that unit group loop or random unit, create a dummy unit that casts a stunning spell on the target(s). Then have the traps explode (may want to trigger this as well using an unit group loop and a "Make Unit Damage Target" action for each unit caught in the range of explosion).

    Alternatively, the traps exploding could be based on the kaboom ability, and just have them kaboom on themselves.
     
  9. Saishy

    Saishy

    Joined:
    Mar 23, 2008
    Messages:
    947
    Resources:
    0
    Resources:
    0
    Lol assumed correctly.
    That is exactly what I'm doing, but I thought it was a best way :(
    Seems so... unprofessional xD
     
  10. Soga-

    Soga-

    Joined:
    Jul 20, 2008
    Messages:
    374
    Resources:
    0
    Resources:
    0
    Nah, it's the way a pro would do it. :p

    It's the most efficient thing I can think of, it beats the other solutions on here by a long shot. You don't have to do any complicated calculations - it's this easy.
     
  11. Saishy

    Saishy

    Joined:
    Mar 23, 2008
    Messages:
    947
    Resources:
    0
    Resources:
    0
    Oh, and the kaboom was a great idea!

    But, isn't kaboom blocked by both armor and spell damage reduction, and distance? So I think it might not be that good :(
    Or maybe I can move the unit to the center and explode them...
     
  12. Ciebron

    Ciebron

    Joined:
    Apr 6, 2008
    Messages:
    760
    Resources:
    2
    Spells:
    2
    Resources:
    2
    check a point constantly if there is a unit in it. damage them and stuff

    better to have the dummys in an array if u wanna connect them with lightnings later

    Code (vJASS):
    struct Data
    unit caster
    unit array Dummy [5]

    lightning array Light [5]

    real x
    real y

    static group SpellGroup = CreateGroup()
    static unit tempu
    static integer array Ar
    static integer Total = 0
    static timer Time = CreateTimer()

        static method create takes unit u, real x,real y return Data
            local Data Dat = Data.allocate()
            local integer i = 0
         
            set Dat.caster = u
            set Dat.x = x
            set Dat.y = y
           
            loop
                exitwhen i >= 5
                set Dat.Dummy[i] = CreateUnit("PLAYER","unitID","x","y","face")
                set i = i + 1
            endloop

            if Dat.Total == 0 then
                call TimerStart(Dat.Time,0.05,true,function Dat.Loop)
           endif

           set Dat.Ar[Dat.Total] = Dat
           set Dat.Total = Dat.Total + 1

            return Data
        endmethod

        static method Loop takes nothing returns nothing
            local Data Dat
            local integer i = 0
            local integer index = 0      
     
            loop
                exitwhen i >= Dat.Total
                set Dat = Dat.Ar[i]
             


                if Dat.duration <= 0. then
                    set Dat.Total = Dat.Total - 1
                    set Dat.Ar[i] = Dat.Ar[Dat.Total]
                    set i = i - 1
                    call Dat.destroy()
                else //to avoid dubble free of the struct
                    call GroupEnumUnitInRange(SpellGroup,Dat.x,Dat.y,"Aoe","Boolexpr")
                    set tempu = FirstOfGroup(SpellGroup)
                endif

                if tempu != null then
                    loop
                        //dmg and other stuff
                        call GroupRemoveUnit(SpellGroup,tempu)
                        set tempu = FirstOfGroup(SpellGroup)
                        exitwhen tempu == null
                    endloop
                   
                    loop
                        exitwhen index >= 5
                        set Dat.Light[i] = addLightningEx("LIGHTNINGTYPE","BOOLEAN",GetUnitX(Dat.Dummy[i]),GetUnitY(Dat.Dummy[i]),"Height",Dat.x,Dat.y,"Height")
                        //start some timer of something that will remove the lightnings after a while
                    endloop
                endif

                set i = i + 1
            endloop

            if Dat.Total == 0 then
                call PauseTimer(Dat.Time)
            endif
        endmethod
    endstruct


    this works fine unless u wanna pick them in a pentagon which should be a bit harder (there is a system in wc3c for that) :p
     
  13. Saishy

    Saishy

    Joined:
    Mar 23, 2008
    Messages:
    947
    Resources:
    0
    Resources:
    0
    Ciebron, the trap is not actived by entering it xD

    I finished it, can't make it look cool on war3 but its working...
    Thanks everyone

    Code (vJASS):
    scope Sprenger initializer in_Sprenger

    globals
        private group array sgroup[10]
        private integer array dmg[10]
        private real array sx[10]
        private real array sy[10]
        private player tplayer
        private unit sunit
    endglobals

    //===========================================================================

    private function Sprenger_Conditions takes nothing returns boolean
        return (GetSpellAbilityId() == 'A043')
    endfunction

    //===========================================================================

    private function Sprenger_Group_Cond takes nothing returns boolean
        return ( (IsUnitEnemy(GetFilterUnit(), tplayer)) and GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0.449 )
    endfunction

    //===========================================================================

    function Sprenger_Destroy_Group takes integer i returns nothing
        local unit u
            loop
                set u = FirstOfGroup(sgroup[i])
                call GroupRemoveUnit(sgroup[i], u)
                call RemoveUnit(u)
                exitwhen u == null
            endloop
        call DestroyGroup(sgroup[i])
        set sgroup[i] = null
        set dmg[i] = 0
        set sx[i] = 0
        set sy[i] = 0
    endfunction

    //===========================================================================

    function Sprenger_Effects takes nothing returns nothing
        local unit trap = GetEnumUnit()
        local real x = GetUnitX(trap)
        local real y = GetUnitY(trap)
        call UnitApplyTimedLife(CreateUnit(GetOwningPlayer(trap), 'h014', x, y, 0), 'BTLF', 2.00)
        call UnitAddAbility(trap, 'A04F')
        call IssueTargetOrderById(trap, 852487, sunit)
        call UnitAddAbility(trap, 'Aloc')
    endfunction

    //===========================================================================

    function Sprenger_Working takes integer i returns nothing
        local group targetgroup = CreateGroup()
        local unit dummy
        local unit target
        local player tp

        set tplayer = GetOwningPlayer(FirstOfGroup(sgroup[i]))
        set tp = tplayer
        call GroupEnumUnitsInRange(targetgroup, sx[i], sy[i], 100, Condition(function Sprenger_Group_Cond))
        set sunit = GroupPickRandomUnit(targetgroup)
        set target = sunit
        call GroupClear(targetgroup)
        call ForGroup(sgroup[i], function Sprenger_Effects)
        call SetUnitX(target, sx[i])
        call SetUnitY(target, sy[i])
        call PauseUnit(target, true)
        set dummy = CreateUnit(tplayer, 'h00E', sx[i], sy[i], 0)
        call UnitApplyTimedLife(dummy, 'BTLF', 5.00)
        call UnitAddAbility(dummy, 'A04E')
        call SetUnitAbilityLevel(dummy, 'A04E', dmg[i])
       
        call DestroyGroup(targetgroup)
        set targetgroup = null
        set sunit = null
        call PolledWait2(2)
        call IssuePointOrder(dummy, "blizzard", sx[i], sy[i])
        call PolledWait2(1)
        call UnitApplyTimedLife(CreateUnit(tp, 'h015', sx[i], sy[i], 0), 'BTLF', 3.00)
        call UnitApplyTimedLife(CreateUnit(tp, 'h016', sx[i], sy[i], 0), 'BTLF', 2.00)
        call PauseUnit(target, false)
        set tp = null
        set target = null
        set dummy = null
        call Sprenger_Destroy_Group(i)
    endfunction

    //===========================================================================

    private function Sprenger_Group takes nothing returns integer
        local integer i = 0
       
        loop
            if sgroup[i] == null then
                set sgroup[i] = CreateGroup()
                return i
                set i = 9
            endif
            set i = i + 1
            exitwhen i >= 9
        endloop
       
        return -1
    endfunction

    //===========================================================================

    private function Sprenger_Actions takes nothing returns nothing
        local unit u
        local unit caster = GetTriggerUnit()
        local location temppoint = GetUnitLoc(caster)
        local location array sp[5]
        local integer a = 0
        local integer i
        local player p = GetOwningPlayer(caster)
        local integer ts = GetPlayerId(p)+1
       
        set i = Sprenger_Group()
        if i >= 0 then
            set dmg[i] = GetUnitAbilityLevel(caster, 'A043')
            set sx[i] = GetUnitX(caster)
            set sy[i] = GetUnitY(caster)
            loop
                exitwhen a > 4
                set sp[a] = PolarProjectionBJ(temppoint, 250.00, ( 90.00 + ( I2R(a) * 72.00 ) ))
                set u = CreateUnitAtLoc(p, 'h012', sp[a], 0 )
                call SetUnitUserData(u, i)
                call GroupAddUnit(sgroup[i], u)
                set a = a + 1
                call RemoveLocation(sp[a])
                set sp[a] = null
            endloop
        endif

        set u = null
        set p = null
        call RemoveLocation(temppoint)
        set temppoint = null
    endfunction

    //===========================================================================
    private function in_Sprenger takes nothing returns nothing
        local trigger t_Sprenger = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( t_Sprenger, EVENT_PLAYER_UNIT_SPELL_FINISH )
        call TriggerAddCondition( t_Sprenger, Condition( function Sprenger_Conditions ) )
        call TriggerAddAction( t_Sprenger, function Sprenger_Actions )
        set t_Sprenger = null
    endfunction

    endscope
     
  14. Ciebron

    Ciebron

    Joined:
    Apr 6, 2008
    Messages:
    760
    Resources:
    2
    Spells:
    2
    Resources:
    2
    so how do it work? actived by an ability?
     
  15. Saishy

    Saishy

    Joined:
    Mar 23, 2008
    Messages:
    947
    Resources:
    0
    Resources:
    0
    Yep, basically this:

    Code (vJASS):
        elseif (GetUnitTypeId(target) == 'h012') then
            call Sprenger_Working(GetUnitUserData(target))
        endif



    (I can't give reputation until I get another point, sry guys)
     
  16. Zack1996

    Zack1996

    Joined:
    Dec 18, 2007
    Messages:
    1,088
    Resources:
    3
    Models:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    3
    Lets be lame and stupid. Get a model with 5 attachment points and attach the obelisks on those attachment points.
    Then, base the skill off Goblin Land Mine and set the limit to one. Say in the tooltip that casting it again will trigger the Previous Trap :p
    Then the thing will natrually die and you just create obelisks there if you want and connect them etc.etc.

    Another way would be to a make the obelisks face the centre of the AoE/Trap so you can calculate the centre as Position of Obelisks offset by Whatever towards Facing Angle of Obelisks. Then just do the actions and there you have it XD