# [Trigger] Getting a unit inside a trap

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

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

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?*

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

File size:
188.9 KB
Views:
219
2. ### 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

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

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

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

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

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-

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

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-

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

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

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

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
//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)

13. ### 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 IssueTargetOrderById(trap, 852487, sunit)
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 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)
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

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

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

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