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

[JASS] [Solved] How to calculate coordinates and distances according to Facing of units?

Status
Not open for further replies.
Level 8
Joined
May 12, 2018
Messages
106
I want to create a ability that fires a missile in the point of the Caster or front of the its face, and the missile reaches a certain maximum distance unconditionally (like Carrion Swarm).
And it has to generate pools periodically until the missile reaches its maximum distance.
Actually, I don't know how to calculate angles, distances, and coordinates exactly in programming...

I am using SpellEffectEvent, RegisterPlayerUnitEvent, RelativisticMissiles, TimerUtils, Utilities...
8999ef8bac36bb4a5c7bad299417866c.jpg
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,558

Here's some Lua code I wrote for making a Shockwave-like missile:
Lua:
function CreateMissile(caster, distance, duration, minHeight, model, scale)
 
    -- Set Timer Interval / Missile Speed
    local timerInterval = 0.02
    local speed = distance / (duration / timerInterval)

    -- Get Coordinates
    local x1 = GetUnitX(caster)
    local y1 = GetUnitY(caster)
    local x2 = GetSpellTargetX()
    local y2 = GetSpellTargetY()

    -- Create Missile
    local missile = AddSpecialEffect(model, x1, y1)
    BlzSetSpecialEffectScale(missile, scale)

    -- Get Starting Z Height
    local loc = Location(x1, y1)
    local z = GetLocationZ(loc)

    -- Set Starting Position
    BlzSetSpecialEffectPosition(missile, x1, y1, z + minHeight)

    -- Set Angle
    local angle = Atan2(y2 - y1, x2 - x1)
    BlzSetSpecialEffectYaw(missile, angle)

    -- Set X/Y Offset Per Interval
    local xOffset = speed * Cos(angle)
    local yOffset = speed * Sin(angle)

    -- Start Timer
    local missileTimer = CreateTimer()
    TimerStart(missileTimer, timerInterval, true, function()
  
        -- Get Current Position
       x1 = BlzGetLocalSpecialEffectX(missile)
       y1 = BlzGetLocalSpecialEffectY(missile)

        -- Get Next Position
        x2 = x1 + xOffset
        y2 = y1 + yOffset

        -- Get Z Height
        MoveLocation(loc, x2, y2)
        z = GetLocationZ(loc)

        -- Set Next Position
        BlzSetSpecialEffectPosition(missile, x2, y2, z + minHeight)

        -- Check If Finished
        duration = duration - timerInterval
        if duration <= 0.01 then
            -- Do stuff

            -- Clean up
            DestroyEffect(missile)
            RemoveLocation(loc)
            PauseTimer(missileTimer)
            DestroyTimer(missileTimer)
        end
    end)
end

Here you can see angle and offset being calculated:
Lua:
    -- Get Coordinates
    local x1 = GetUnitX(caster)
    local y1 = GetUnitY(caster)
    local x2 = GetSpellTargetX()
    local y2 = GetSpellTargetY()

    -- Set Angle
    local angle = Atan2(y2 - y1, x2 - x1)

    -- Set X/Y Offset
    local xOffset = speed * Cos(angle)
    local yOffset = speed * Sin(angle)

To calculate the periodic pools you could use another variable inside of the timer like so:
Lua:
poolDuration = poolDuration - timerInterval
if poolDuration <= 0.01 then
    -- Create a pool
    poolDuration = 0.20
end
This will create a pool once every 0.20 seconds.
 
Last edited:
Level 8
Joined
May 12, 2018
Messages
106

Here's some Lua code I wrote for making a Shockwave-like missile:
Lua:
function CreateMissile(caster, distance, duration, minHeight, model, scale)
 
    -- Set Timer Interval / Missile Speed
    local timerInterval = 0.02
    local speed = distance / (duration / timerInterval)

    -- Get Coordinates
    local x1 = GetUnitX(caster)
    local y1 = GetUnitY(caster)
    local x2 = GetSpellTargetX()
    local y2 = GetSpellTargetY()

    -- Create Missile
    local missile = AddSpecialEffect(model, x1, y1)
    BlzSetSpecialEffectScale(missile, scale)

    -- Get Starting Z Height
    local loc = Location(x1, y1)
    local z = GetLocationZ(loc)

    -- Set Starting Position
    BlzSetSpecialEffectPosition(missile, x1, y1, z + minHeight)

    -- Set Angle
    local angle = Atan2(y2 - y1, x2 - x1)
    BlzSetSpecialEffectYaw(missile, angle)

    -- Set X/Y Offset Per Interval
    local xOffset = speed * Cos(angle)
    local yOffset = speed * Sin(angle)

    -- Start Timer
    local missileTimer = CreateTimer()
    TimerStart(missileTimer, timerInterval, true, function()
 
        -- Get Current Position
       x1 = BlzGetLocalSpecialEffectX(missile)
       y1 = BlzGetLocalSpecialEffectY(missile)

        -- Get Next Position
        x2 = x1 + xOffset
        y2 = y1 + yOffset

        -- Get Z Height
        MoveLocation(loc, x2, y2)
        z = GetLocationZ(loc)

        -- Set Next Position
        BlzSetSpecialEffectPosition(missile, x2, y2, z + minHeight)

        -- Check If Finished
        duration = duration - timerInterval
        if duration <= 0.01 then
            -- Do stuff

            -- Clean up
            DestroyEffect(missile)
            RemoveLocation(loc)
            PauseTimer(missileTimer)
            DestroyTimer(missileTimer)
        end
    end)
end

Here you can see angle and offset being calculated:
Lua:
    -- Get Coordinates
    local x1 = GetUnitX(caster)
    local y1 = GetUnitY(caster)
    local x2 = GetSpellTargetX()
    local y2 = GetSpellTargetY()

    -- Set Angle
    local angle = Atan2(y2 - y1, x2 - x1)

    -- Set X/Y Offset
    local xOffset = speed * Cos(angle)
    local yOffset = speed * Sin(angle)

To calculate the periodic pools you could use another variable inside of the timer like so:
Lua:
poolDuration = poolDuration - timerInterval
if poolDuration <= 0.01 then
    -- Create a pool
    poolDuration = 0.20
end
This will create a pool once every 0.20 seconds.
I succeeded in making the missile fly to the maximum distance unconditionally using the Atan2 and Offset calculation formula you gave to me.

JASS:
library FelLordFelFissure requires RegisterPlayerUnitEvent, SpellEffectEvent, PluginSpellEffect, Missiles, TimerUtils
 
    globals
        private constant integer AID = 'A03W'
        private constant real HEIGHTCASTER = 50
        private constant real MAXDISTANCE = 1500
        private constant string MISSILEMODEL = "Abilities\\Spells\\Orc\\Shockwave\\ShockwaveMissile.mdl"
        private constant real MISSILESCALE = 3
        private constant real MISSILESPEED = 700
    endglobals

    private struct FelFissure extends Missiles
     
        integer level

        private method onFinish takes nothing returns boolean
     
        return true
        endmethod
     
     
        static method onCast takes nothing returns nothing
            local thistype this

            local real x0 = Spell.source.x
            local real y0 = Spell.source.y
            local real x1 = Spell.x
            local real y1 = Spell.y
            local real angle = Atan2(y1 - y0, x1 - x0)
            local real xOffset = x0 + MAXDISTANCE * Cos(angle)
            local real yOffset = y0 + MAXDISTANCE * Sin(angle)
         
            set this = thistype.create(x0, y0, HEIGHTCASTER, xOffset, yOffset, HEIGHTCASTER)
         
            set level = Spell.level
            set model = MISSILEMODEL
            set scale = MISSILESCALE
            set speed = MISSILESPEED
            set source = Spell.source.unit
            set owner = Spell.source.player
            set vision = 160

            call launch()
         
        endmethod
     
        private static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(AID, function thistype.onCast)
        endmethod
     
    endstruct
 
endlibrary

aaaaaa.gif

I used Chopinski's Relativistic Missile System. But I still face the problem of not knowing how to create dummy units(and some linked effects and timer?) in the current position of the missile every set period.
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,558
I've never used his system before but a quick glance over the API shows all of the functions you can use with it. The one you're looking for appears to be this:
vJASS:
event onPeriod takes nothing returns boolean
    -> if declared will run whenever every missile period
If I were you I would read up on the system and how it's used. It's very well documented and you can direct your questions to the creator himself.
 
Last edited:
Level 8
Joined
May 12, 2018
Messages
106
I've never used his system before but a quick glance over the API shows all of the functions you can use with it. The one you're looking for appears to be this:
vJASS:
event onPeriod takes nothing returns boolean
    -> if declared will run whenever every missile period
If I were you I would read up on the system and how it's used. It's very well documented and you can direct your questions to the creator himself.
Its onPeriod method works fine.
Thank you always.
 
Status
Not open for further replies.
Top