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

[Trigger] Getting a unit inside a trap

Status
Not open for further replies.
Level 12
Joined
Mar 23, 2008
Messages
942
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.

attachment.php


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...
 

Attachments

  • sprenger.JPG
    sprenger.JPG
    188.9 KB · Views: 305
Level 18
Joined
Aug 23, 2008
Messages
2,319
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.
 
Level 12
Joined
Mar 23, 2008
Messages
942
Place a dummy unit in the center of the trap. If a unit comes in range of the dummy: Activate the trap.

The user needs to use an ability of the hero to active the trap.

Edit:
Avator said:
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.
Its not like I can pick the ward I wanna.
 
Level 12
Joined
Mar 16, 2006
Messages
992
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.
 
Level 12
Joined
Mar 23, 2008
Messages
942
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.

lol o.o
I still think its better to use x,y array o.o
 
Level 12
Joined
Mar 16, 2006
Messages
992
lol o.o
I still think its better to use x,y array o.o

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?
 
Level 7
Joined
Jul 20, 2008
Messages
377
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.
 
Level 12
Joined
Mar 23, 2008
Messages
942
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.

Lol assumed correctly.
That is exactly what I'm doing, but I thought it was a best way :(
Seems so... unprofessional xD
 
Level 7
Joined
Jul 20, 2008
Messages
377
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.
 
Level 12
Joined
Mar 23, 2008
Messages
942
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.

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...
 
Level 11
Joined
Apr 6, 2008
Messages
760
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

JASS:
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
 
Level 12
Joined
Mar 23, 2008
Messages
942
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

JASS:
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
 
Level 15
Joined
Dec 18, 2007
Messages
1,098
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
 
Status
Not open for further replies.
Top