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
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +1
  • V-SNES V-SNES:
    Happy Friday!
    +1

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top