Semi circular collision spell

shiFt

Member
Reaction score
8
____a__X__b
___a_______b
___a_______b
____a__c__b


c = Caster
X = Where two projectiles meet( get destroyed)
a = Projectile 1
b = Projectile 2

How would I code the above described movement, It is basically a circle with the caster and collision points being at polar opposites of the path, and the center lying in between them (duh). Two projectiles are made on either side of the caster and follow the circular path to the collision point, "a" moving clockwise to the point and "b" moving counter clockwise towards it.

Any help is greatly appreciated, +reps appropriate.
:)
 

Ayanami

칼리
Reaction score
288
Hmm, well do you know how to code a circular movement? I could write a quick one in vJASS if you want. Basically, you'd have to move 2 projectiles in a semi-circle manner via polar offsets. Just calculate the center point and play around with the angles from that center point with a fixed radius.
 

shiFt

Member
Reaction score
8
How do I increment it into a periodic function? This is where I am uncertain
 

Dirac

22710180
Reaction score
147
Well if you use my system all you have to do is type circlestruct.polarXY(distance howMuch,clockwise boolean) the "move" picture in the post i made explains it.

If you're NOT gonna use my snippet and use polar projection instead, then you increase the angle.

Set Xo and Yo as the point between the caster and the target (distance/2) and rotate the projectile around it. With my snippet is a lot easier
 

shiFt

Member
Reaction score
8
Yes im toying with your snippet at the moment, how would I detect when the distance is reached and the dummies collide? And what function do I use to make the dummies follow the path? I have this, it creates a memory crash.
 

Dirac

22710180
Reaction score
147
it creates a memory crash because of this
JASS:
call .o.moveVector(.distance,false)
the dummy moves the ENTIRE distance per period, it should be
JASS:
call .o.moveVector(.speed.,false)
Also set .distance to this
JASS:
set .distance=(SquareRoot(d.dx * d.dx + d.dy * d.dy)*bj_PI)/2
it should work fine now

EDIT: removed an unnecessary correction
 

shiFt

Member
Reaction score
8
Added changes.

It still does not work, merely appears at the end distance then disappears.
 

Dirac

22710180
Reaction score
147
Your spell is a mess now that i see the coding, you're using arrays for the dummy unit when you don't need to since you're creating 2 structs, one per dummy, but assing them to different values in the same struct. I'll just rewrite your spell and paste it here, it's no longer a problem with the circle anyways lol

EDIT: finished the code
JASS:
scope Rotate initializer start
    private struct data
        unit caster
        unit dummy
        real duration
        real distance
        boolean clockwise
        real tx
        real ty
        real dx
        real dy
        real x
        real y
        real speed
        real tick
        circle o
        real angle
        
        private method periodic takes nothing returns nothing
              
            set .o.x=.x+ (.distance/2.)*Cos(.angle)
            set .o.y=.y+ (.distance/2.)*Sin(.angle)
           
           
            call .o.moveVector(.speed,.clockwise)
            call SetUnitX(.dummy,.o.offsetX)
            call SetUnitY(.dummy,.o.offsetY)
            

            if .tick == T32_Tick then
                call RemoveUnit(.dummy)
                call .stopPeriodic()
                call .destroy()
            endif
        endmethod
        
        implement T32x
        
    endstruct

    private function mainAction takes nothing returns boolean
        local integer i=0
        local data d
        loop
            exitwhen i>=2
            set d=data.create()
            set d.caster=GetTriggerUnit()
            set d.x = GetUnitX(d.caster)
            set d.y = GetUnitY(d.caster)
            set d.tx = GetSpellTargetX()
            set d.ty = GetSpellTargetY()
            set d.dx = d.tx - d.x
            set d.dy = d.ty - d.y
            set d.angle = Atan2(d.dy,d.dx)
            set d.distance=SquareRoot(d.dx * d.dx + d.dy * d.dy)
            if i==0 then
                set d.clockwise=true
            else
                set d.clockwise=false
            endif
            set d.speed = (200. * T32_PERIOD)
            set d.tick = T32_Tick + R2I(((d.distance*bj_PI)/2) / d.speed)
            set d.o=circle.create((d.x+ (d.distance/2.)*Cos(d.angle)),(d.y+ (d.distance/2.)*Sin(d.angle)),d.distance/2)
            set d.o.xyangle=Atan2(d.y-d.o.y,d.x-d.o.x)
            set d.dummy=CreateUnit(Player(0),'h000',d.o.offsetX,d.o.offsetY,d.o.offsetX)
            set i=i+1
            call d.startPeriodic()
        endloop
        return false
    endfunction
    
    private function start takes nothing returns nothing
        call TriggerAddCondition(GT_RegisterStartsEffectEvent(CreateTrigger(),'A000'),Condition(function mainAction))
    endfunction
endscope
 

shiFt

Member
Reaction score
8
I have made this, howcome it does not work? I just want units that the dummies pass through to take damage.
 

Dirac

22710180
Reaction score
147
I think your problem lies in the thistype.cf variable. Instead of going
JASS:
call GroupEnumUnitsInRange(thistype.enumGroup,GetUnitX(.dummy),GetUnitY(.dummy),170.,thistype.cf)
do this
JASS:
call GroupEnumUnitsInRange(thistype.enumGroup,GetUnitX(.dummy),GetUnitY(.dummy),170.,function thistype.enumUnits)


Also i don't know that is this
JASS:
set .g = Group.get()


This is slowing down your spell too
JASS:
call GroupEnumUnitsInRange(thistype.enumGroup,GetUnitX(.dummy),GetUnitY(.dummy),170.,thistype.cf)
because you're making it call the unit's X and Y again when you already know em, they're .o.offsetX and .o.offsetY
 

NoobImbaPro

You can change this now in User CP.
Reaction score
60
I haven't paid to much attention on above posts (except first...) but I will give you an idea.
We have to init the variables.
Lets say first that C is caster and P is the meeting point, we first get the center O of our circle moving which is
O.x = (C.x + P.x)/2 and O.y = (C.y + P.y)/2, we need now the radius of the circle which is:
Radius = SquareRoot( (O.x - C.x)[SUP]2[/SUP] + (O.y - C.y)[SUP]2[/SUP] ) and its the same if we replace the C.x/y with P.x/y
Now you need these missiles to meet there within a duration, the duration that has to pass from the time the unit casted to the time they will meet, let's say it's 1.5 seconds.
We have now center's points and radius and wee need to get the angle change speed.
You must know that the angle they will do each is 180 degrees or Pi radians, from caster to target point.
So our angle speed is (3.14 / 1.5) * 1 (per second) or (3.14 / 1.5) * timerPeriod for every period seconds.
General: anglespeed = (3.14 / duration) * timerPeriod (3.14 I mean Pi)
And now you begin the task, you summon them at casters position witch is "Center offset by Radius towards base angle"
base_angle is the angle from center to caster and angle is the current one. angle is set 0 initially
x1 = C.x + radius * Cos(baseangle + angle)
y1 = C.x + radius * Sin(baseangle + angle)
set unit A position --> x1,y1
x2 = C.x + radius * Cos(baseangle-angle)
y2 = C.x + radius * Sin(baseangle-angle)
set unit A position --> x2,y2
set angle = angle + anglespeed
end when angle >= Pi (angle from caster to target point)
 

Dirac

22710180
Reaction score
147
I haven't paid to much attention on above posts (except first...) but I will give you an idea.
We have to init the variables.
Lets say first that C is caster and P is the meeting point, we first get the center O of our circle moving which is
O.x = (C.x + P.x)/2 and O.y = (C.y + P.y)/2, we need now the radius of the circle which is:
Radius = SquareRoot( (O.x - C.x)[SUP]2[/SUP] + (O.y - C.y)[SUP]2[/SUP] ) and its the same if we replace the C.x/y with P.x/y
Now you need these missiles to meet there within a duration, the duration that has to pass from the time the unit casted to the time they will meet, let's say it's 1.5 seconds.
We have now center's points and radius and wee need to get the angle change speed. (I will edit this a little later because I got some critical tasks to do (grandma calling :p)
This is why you always have to read the whole thread before you answer, this problem is long solved
 

NoobImbaPro

You can change this now in User CP.
Reaction score
60
I offer a second solution, shorter and better than your snippet and how exactly he described it.
 

shiFt

Member
Reaction score
8
Added the corrections but still nothing happens when I cast the spell?
JASS:
library RO requires T32, GT, Recycle 
    private struct data
        private static group enumGroup = CreateGroup()
        private static thistype d
        private static conditionfunc cf
        unit caster
        unit dummy
        real duration
        real distance
        boolean clockwise
        real tx
        real ty
        real dx
        real dy
        real x
        real y
        real speed
        real tick
        circle o
        real angle
        group g
        player p
        
        private static method enumUnits takes nothing returns boolean
            local thistype this = thistype.d
            local unit u = GetFilterUnit()
            if IsUnitEnemy(u,.p) and GetWidgetLife(u) > .405 and not IsUnitType(u,UNIT_TYPE_STRUCTURE) and not IsUnitInGroup(u,.g) then
                call UnitDamageTargetEx(.caster,u, 50. , false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS )
                    call GroupAddUnit(.g,u)
            endif
                set u = null 
            return false
        endmethod
        
        private method periodic takes nothing returns nothing
              
            set .o.x=.x+ (.distance/2.)*Cos(.angle)
            set .o.y=.y+ (.distance/2.)*Sin(.angle)
           
           
            call .o.moveVector(.speed,.clockwise)
            call SetUnitX(.dummy,.o.offsetX)
            call SetUnitY(.dummy,.o.offsetY)
            
            set thistype.d = this
            call GroupEnumUnitsInRange(thistype.enumGroup,.o.offsetX,.o.offsetY,170.,function thistype.enumUnits)

            if .tick == T32_Tick then
                call KillUnit(.dummy)
                call Group.release(.g)
                call .stopPeriodic()
                call .destroy()
            endif
        endmethod
        
        implement T32x
    
     private static method mainAction takes nothing returns nothing
        local thistype this = thistype.allocate()
        local integer i=0
        loop
            exitwhen i>=2
            set .caster=GetTriggerUnit()
            set .x = GetUnitX(.caster)
            set .y = GetUnitY(.caster)
            set .tx = GetSpellTargetX()
            set .ty = GetSpellTargetY()
            set .dx = .tx - .x
            set .dy = .ty - .y
            set .angle = Atan2(.dy,.dx)
            set .distance=SquareRoot(.dx * .dx + .dy * .dy)
            if i==0 then
                set .clockwise=true
            else
                set .clockwise=false
            endif
            set .speed = (1100. * T32_PERIOD)
            set .tick = T32_Tick + R2I(((.distance*bj_PI)/1.22) / .speed)
            set .o=circle.create((.x+ (.distance/2.)*Cos(.angle)),(.y+ (.distance/2.)*Sin(.angle)),50., .distance/2.)
            set .o.xyangle=Atan2(.y-.o.y,.x-.o.x)
            set .p = GetOwningPlayer(.caster)
            set .dummy=CreateUnit(.p,'h000',.o.offsetX,.o.offsetY,.o.offsetX)
            set i=i+1
            set .g = Group.get()
            call .startPeriodic()
        endloop
        //return false
    endmethod
   
   private static method start takes nothing returns nothing
        call GT_AddStartsEffectAction(function thistype.mainAction,'A001')
        set thistype.cf = Condition(function thistype.enumUnits)
    endmethod
    endstruct
endlibrary


I will also try NoobImbaPros suggestion to be fair, but my interpretation of it will mostlikely be inaccurate so standby :)
 

Dirac

22710180
Reaction score
147
I offer a second solution, shorter and better than your snippet and how exactly he described it.
If your solution was better than my snippet then i should just delete the damn thing, my snippet offers something nothing else can: move a point around a circle without measuring angles from the center, only distance, it's also faster and more efficient than polar offset

EDIT: shiFt you turned it into a library and forgot to add the initializer lol, plus you moved something i coded that would crash the spell anyways. heres your code once again
JASS:
library RO requires T32, GT, Recycle 
    private struct data
        private static group enumGroup = CreateGroup()
        private static thistype d
        private static conditionfunc cf
        unit caster
        unit dummy
        real duration
        real distance
        boolean clockwise
        real tx
        real ty
        real dx
        real dy
        real x
        real y
        real speed
        real tick
        circle o
        real angle
        group g
        player p
        
        private static method enumUnits takes nothing returns boolean
            local thistype this = thistype.d
            local unit u = GetFilterUnit()
            if IsUnitEnemy(u,.p) and GetWidgetLife(u) > .405 and not IsUnitType(u,UNIT_TYPE_STRUCTURE) and not IsUnitInGroup(u,.g) then
                call UnitDamageTargetEx(.caster,u, 50. , false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS )
                    call GroupAddUnit(.g,u)
            endif
                set u = null 
            return false
        endmethod
        
        private method periodic takes nothing returns nothing
              
            set .o.x=.x+ (.distance/2.)*Cos(.angle)
            set .o.y=.y+ (.distance/2.)*Sin(.angle)
           
           
            call .o.moveVector(.speed,.clockwise)
            call SetUnitX(.dummy,.o.offsetX)
            call SetUnitY(.dummy,.o.offsetY)
            
            set thistype.d = this
            call GroupEnumUnitsInRange(thistype.enumGroup,.o.offsetX,.o.offsetY,170.,function thistype.enumUnits)

            if .tick == T32_Tick then
                call KillUnit(.dummy)
                call Group.release(.g)
                call .stopPeriodic()
                call .destroy()
            endif
        endmethod
        
        implement T32x
    
         private static method mainAction takes nothing returns nothing
            local thistype this
            local integer i=0
            loop
                set this=thistype.allocate()// THIS IS VERY IMPORTANT DO NOT MOVE THIS OUTSIDE THE LOOP
                //why? because you have to create 2 structs per ability, every struct moves 1 dummy only
                exitwhen i>=2
                set .caster=GetTriggerUnit()
                set .x = GetUnitX(.caster)
                set .y = GetUnitY(.caster)
                set .tx = GetSpellTargetX()
                set .ty = GetSpellTargetY()
                set .dx = .tx - .x
                set .dy = .ty - .y
                set .angle = Atan2(.dy,.dx)
                set .distance=SquareRoot(.dx * .dx + .dy * .dy)
                if i==0 then
                    set .clockwise=true
                else
                    set .clockwise=false
                endif
                set .speed = (1100. * T32_PERIOD)
                set .tick = T32_Tick + R2I(((.distance*bj_PI)/1.22) / .speed)
                set .o=circle.create((.x+ (.distance/2.)*Cos(.angle)),(.y+ (.distance/2.)*Sin(.angle)),50., .distance/2.)
                set .o.xyangle=Atan2(.y-.o.y,.x-.o.x)
                set .p = GetOwningPlayer(.caster)
                set .dummy=CreateUnit(.p,'h000',.o.offsetX,.o.offsetY,.o.offsetX)
                set i=i+1
                set .g = Group.get()
                call .startPeriodic()
            endloop
            //return false
        endmethod
       
       private static method onInit takes nothing returns nothing
            call GT_AddStartsEffectAction(function thistype.mainAction,'A001')
            set thistype.cf = Condition(function thistype.enumUnits)
        endmethod
    endstruct
endlibrary
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top