HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Movement of Projectiles and Custom Coding in Jass, Help!

05-29-2006, 02:31 PM#1
The)TideHunter(
Sorry for this heap of code, but its confusing me, i have posted a problem like this before, but i decided to completly remake my code.

Its the projectiles im having problems with, (again), i dont understand whats going wrong, when i launch a projectile, it just hurts the person thats launching it.

Its mainly the 3rd and 4th function from the bottom, i havent tested the bottom 2 yet, the bottom 2 are collision missles, while the 3rd and the 4th from bottom are target missiles.

Thanks in advance (if you can read the heap of code) and for help :)

Here it is (Its my personal little system, im calling it Casual Functions, or CF)

Collapse JASS:
// Globals (Mainly for Jass Editing Programs)
globals
    gamecache udg_GC = null
endglobals

// Casual Functions Engine
// Created and Updated by The)TideHunter(
// Creation Began: 28/05/06
// Last Updated: 29/05/06

// Game Cache Return Function
function CF_GC takes nothing returns gamecache
    if(udg_GC == null) then
        call FlushGameCache(InitGameCache("GC"))
        set udg_GC = InitGameCache("GC")
    endif
    return udg_GC
endfunction

// Constants
constant function CF_MaxProjectileCollisionRange takes nothing returns real
    return 5.
endfunction

// Rawcodes
constant function CF_DummyRawcode takes nothing returns integer
    return 'hpea'
endfunction

// Handle Variables
function CF_H2I takes handle H returns integer
    return H
    return 0
endfunction

function CF_I2Unit takes integer I returns unit
    return I
    return null
endfunction

function CF_I2Effect takes integer I returns effect
    return I
    return null
endfunction

function CF_I2Group takes integer I returns group
    return I
    return null
endfunction

// Attach Variables
function CF_StoreHandle takes handle whichHandle, string label, string handleType returns nothing
    call StoreInteger(CF_GC(), handleType, label, CF_H2I(whichHandle))
endfunction

function CF_AttachInt takes integer whichInt, string label, handle attachToWhichHandle returns nothing
    call StoreInteger(CF_GC(), I2S(CF_H2I(attachToWhichHandle)), label, whichInt)
endfunction

function CF_AttachString takes string whichString, string label, handle attachToWhichHandle returns nothing
    call StoreString(CF_GC(), I2S(CF_H2I(attachToWhichHandle)), label, whichString)
endfunction

function CF_AttachReal takes real whichReal, string label, handle attachToWhichHandle returns nothing
    call StoreReal(CF_GC(), I2S(CF_H2I(attachToWhichHandle)), label, whichReal)
endfunction

function CF_AttachBoolean takes boolean whichBoolean, string label, handle attachToWhichHandle returns nothing
    call StoreBoolean(CF_GC(), I2S(CF_H2I(attachToWhichHandle)), label, whichBoolean)
endfunction

function CF_AttachHandle takes handle whichHandle, string label, handle attachToWhichHandle returns nothing
    call StoreInteger(CF_GC(), I2S(CF_H2I(attachToWhichHandle)), label, CF_H2I(whichHandle))
endfunction

function CF_GetStoredEffect takes string label returns handle
    return CF_I2Effect(GetStoredInteger(CF_GC(), "Effect", label))
endfunction

function CF_GetAttachedInt takes string label, handle attachedHandle returns integer
    return GetStoredInteger(CF_GC(), I2S(CF_H2I(attachedHandle)), label)
endfunction

function CF_GetAttachedString takes string label, handle attachedHandle returns string
    return GetStoredString(CF_GC(), I2S(CF_H2I(attachedHandle)), label)
endfunction

function CF_GetAttachedReal takes string label, handle attachedHandle returns real
    return GetStoredReal(CF_GC(), I2S(CF_H2I(attachedHandle)), label)
endfunction

function CF_GetAttachedBoolean takes string label, handle attachedHandle returns boolean
    return GetStoredBoolean(CF_GC(), I2S(CF_H2I(attachedHandle)), label)
endfunction

function CF_GetAttachedUnit takes string label, handle attachedHandle returns unit
    return CF_I2Unit(GetStoredInteger(CF_GC(), I2S(CF_H2I(attachedHandle)), label))
endfunction

function CF_GetAttachedEffect takes string label, handle attachedHandle returns effect
    return CF_I2Effect(GetStoredInteger(CF_GC(), I2S(CF_H2I(attachedHandle)), label))
endfunction

function CF_GetAttachedGroup takes string label, handle attachedHandle returns group
    return CF_I2Group(GetStoredInteger(CF_GC(), I2S(CF_H2I(attachedHandle)), label))
endfunction

function CF_RemoveAttachments takes handle attachedHandle returns nothing
    call FlushStoredMission(CF_GC(), I2S(CF_H2I(attachedHandle)))
endfunction

// Common Functions
function CF_IsXSafe takes real X returns boolean
    local rect SafeRect = bj_mapInitialPlayableArea
    local real MinSafeX = GetRectMinX(SafeRect)
    local real MaxSafeX = GetRectMaxX(SafeRect)
    if(MinSafeX < X) and (MaxSafeX > X) then
        return true
    endif
    call RemoveRect(SafeRect)
    set SafeRect = null
    return false
endfunction

function CF_IsYSafe takes real Y returns boolean
    local rect SafeRect = bj_mapInitialPlayableArea
    local real MinSafeY = GetRectMinY(SafeRect)
    local real MaxSafeY = GetRectMaxY(SafeRect)
    if(MinSafeY < Y) and (MaxSafeY > Y) then
        return true
    endif
    call RemoveRect(SafeRect)
    set SafeRect = null
    return false
endfunction

function CF_IsLocSafe takes real X, real Y returns boolean
    if(CF_IsXSafe(X) == true) and (CF_IsYSafe(Y) == true) then
        return true
    endif
    return false
endfunction

function CF_IsLocSafeEx takes location whichLocation returns boolean
    return CF_IsLocSafe(GetLocationX(whichLocation), GetLocationY(whichLocation))
endfunction

function CF_DestroyTimer takes timer whichTimer returns nothing
    call CF_RemoveAttachments(whichTimer)
    call DestroyTimer(whichTimer)
endfunction

function CF_UnitDamageUnit takes unit credit, unit target, real amount, integer attackIndex, integer damageIndex returns nothing
    call UnitDamageTarget(credit, target, amount, true, false, ConvertAttackType(attackIndex), ConvertDamageType(damageIndex), ConvertWeaponType(0))
endfunction

function CF_UnitSpellDamageUnit takes unit credit, unit target, real amount returns nothing
    if(IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) == false) then
        call CF_UnitDamageUnit(credit, target, amount, 4, 26)  
    endif
endfunction 

// Extended Creation Functions
// Effect
function CF_CreateEffect takes real X, real Y, string modelPath returns effect
    local unit CarryingUnit
    local effect NewEffect
    if(CF_IsLocSafe(X, Y) == true) then
        set CarryingUnit = CreateUnit(Player(15), CF_DummyRawcode(), X, Y, 0.)
        set NewEffect = AddSpecialEffectTarget(modelPath, CarryingUnit, "origin")
        call CF_AttachHandle(CarryingUnit, "Effect_CarryingUnit", NewEffect)
        call CF_AttachReal(X, "Effect_CoordX", NewEffect)
        call CF_AttachReal(Y, "Effect_CoordY", NewEffect)
        call CF_AttachString(modelPath, "Effect_ModelPath", NewEffect)
        call CF_StoreHandle(NewEffect, "LastCreatedEffect", "Effect")
        return NewEffect
    endif
    return null
endfunction

function CF_GetEffectCarryingUnit takes effect whichEffect returns unit
    return CF_I2Unit(CF_GetAttachedInt("Effect_CarryingUnit", whichEffect))
endfunction

function CF_GetEffectX takes effect whichEffect returns real
    return CF_GetAttachedReal("Effect_CoordX", whichEffect)
endfunction

function CF_GetEffectY takes effect whichEffect returns real
    return CF_GetAttachedReal("Effect_CoordY", whichEffect)
endfunction

function CF_GetEffectLoc takes effect whichEffect returns location
    return Location(CF_GetEffectX(whichEffect), CF_GetEffectY(whichEffect))
endfunction

function CF_GetEffectModelPath takes effect whichEffect returns string
    return CF_GetAttachedString("Effect_ModelPath", whichEffect)
endfunction

function CF_GetLastCreatedEffect takes nothing returns effect
    return CF_GetStoredEffect("LastCreatedEffect")
endfunction

function CF_SetEffectX takes effect whichEffect, real X returns nothing
    if(CF_IsXSafe(X) == true) then
        call SetUnitX(CF_GetEffectCarryingUnit(whichEffect), X)
        call CF_AttachReal(X, "Effect_CoordX", whichEffect)
    endif
endfunction

function CF_SetEffectY takes effect whichEffect, real Y returns nothing
    if(CF_IsYSafe(Y) == true) then
        call SetUnitY(CF_GetEffectCarryingUnit(whichEffect), Y)
        call CF_AttachReal(Y, "Effect_CoordY", whichEffect)
    endif
endfunction

function CF_SetEffectLoc takes effect whichEffect, real X, real Y returns nothing
    if(CF_IsLocSafe(X, Y) == true) then
        call CF_SetEffectX(whichEffect, X)
        call CF_SetEffectY(whichEffect, Y)
    endif
endfunction

function CF_SetEffectLocEx takes effect whichEffect, location whichLoc returns nothing
    call CF_SetEffectLoc(whichEffect, GetLocationX(whichLoc), GetLocationY(whichLoc))
endfunction

function CF_CopyEffect takes effect whichEffect returns effect
    return CF_CreateEffect(CF_GetEffectX(whichEffect), CF_GetEffectY(whichEffect), CF_GetEffectModelPath(whichEffect))
endfunction

function CF_CopyEffectNewLoc takes effect whichEffect, real X, real Y returns effect
    local effect NewEffect = CF_CopyEffect(whichEffect)
    call CF_SetEffectLoc(NewEffect, X, Y)
    return NewEffect
endfunction

function CF_CopyEffectNewLocEx takes effect whichEffect, location whichLoc returns effect
    return CF_CopyEffectNewLoc(whichEffect, GetLocationX(whichLoc), GetLocationY(whichLoc))
endfunction

function CF_DestroyEffect takes effect whichEffect returns nothing
    local unit CarryingUnit = CF_GetEffectCarryingUnit(whichEffect)
    call CF_RemoveAttachments(whichEffect)
    call DestroyEffect(whichEffect)
    call RemoveUnit(CarryingUnit)
    set CarryingUnit = null
endfunction

function CF_DestroyTempEffect takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local effect DestroyingEffect = CF_GetAttachedEffect("Timer_TempEffect", t)
    call CF_DestroyEffect(DestroyingEffect)
    call CF_DestroyTimer(t)
    set t = null
    set DestroyingEffect = null
endfunction

function CF_CreateTempEffect takes real X, real Y, string modelPath, real duration returns effect
    local timer t = CreateTimer()
    local effect NewEffect = CF_CreateEffect(X, Y, modelPath)
    call CF_AttachHandle(NewEffect, "Timer_TempEffect", t)
    call TimerStart(t, duration, false, function CF_DestroyTempEffect)
    return NewEffect
endfunction

function CF_CreateTempEffectLoc takes location whichLoc, string modelPath, real duration returns effect
    return CF_CreateTempEffect(GetLocationX(whichLoc), GetLocationY(whichLoc), modelPath, duration)
endfunction
     
function CF_CopyTempEffect takes effect whichEffect, real duration returns effect
    local timer t = CreateTimer()
    local effect NewEffect = CF_CopyEffect(whichEffect)
    call CF_AttachHandle(NewEffect, "Timer_TempEffect", t)
    call TimerStart(t, duration, false, function CF_DestroyTempEffect)
    return NewEffect
endfunction

function CF_CopyTempEffectLoc takes effect whichEffect, real X, real Y, real duration returns effect
    local timer t = CreateTimer()
    local effect NewEffect = CF_CopyEffectNewLoc(whichEffect, X, Y)
    call CF_AttachHandle(NewEffect, "Timer_TempEffect", t)
    call TimerStart(t, duration, false, function CF_DestroyTempEffect)
    return NewEffect
endfunction

function CF_CopyTempEffectLocEx takes effect whichEffect, location whichLoc, real duration returns effect
    local timer t = CreateTimer()
    local effect NewEffect = CF_CopyEffectNewLocEx(whichEffect, whichLoc)
    call CF_AttachHandle(NewEffect, "Timer_TempEffect", t)
    call TimerStart(t, duration, false, function CF_DestroyTempEffect)
    return NewEffect
endfunction

// Main Functions
// Target Projectile
function CF_LaunchTargetProjectile_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local effect Projectile = CF_GetAttachedEffect("Projectile_Effect", t)
    local unit credit = CF_GetAttachedUnit("Projectile_Credit", t)
    local unit target = CF_GetAttachedUnit("Projectile_Target", t)
    local real DamageAmount = CF_GetAttachedReal("Projectile_Damage", t)
    local real CurrentX = CF_GetEffectX(Projectile)
    local real CurrentY = CF_GetEffectY(Projectile)
    local real TargetX = GetUnitX(target)               
    local real TargetY = GetUnitY(target)
    local real angle = bj_DEGTORAD * Atan2(TargetY - CurrentY, TargetX - CurrentX)
    local real speed = CF_GetAttachedReal("Projectile_Speed", t)
    local real distance = SquareRoot((TargetX - CurrentX) * (TargetX - CurrentX) + (TargetY - CurrentY) * (TargetY - CurrentY))
    local real time = distance / speed
    local real MovingDistance = distance / (time / 0.01)
    local real NewX = CurrentX + MovingDistance * Cos(angle * bj_DEGTORAD)
    local real NewY = CurrentY + MovingDistance * Sin(angle * bj_DEGTORAD)
    if(distance < CF_MaxProjectileCollisionRange()) then
        call CF_UnitDamageUnit(credit, target, DamageAmount, 0, 4)
        call CF_DestroyEffect(Projectile)
        call CF_DestroyTimer(t)
        set t = null
        set Projectile = null
    else
        call CF_SetEffectLoc(Projectile, NewX, NewY)
        call TimerStart(t, 0.01, false, function CF_LaunchTargetProjectile_Update)
    endif         
endfunction

function CF_LaunchTargetProjectile_Begin takes unit credit, unit target, real startX, real startY, real damage, string modelPath, real speed returns nothing
    local timer t = CreateTimer()
    local effect ProjectileEffect = CF_CreateEffect(startX, startY, modelPath)
    call CF_AttachHandle(credit, "Projectile_Credit", t)
    call CF_AttachHandle(target, "Projectile_Target", t)
    call CF_AttachHandle(ProjectileEffect, "Projectile_Effect", t)
    call CF_AttachReal(damage, "Projectile_Damage", t)
    call CF_AttachReal(speed, "Projectile_Speed", t)
    call TimerStart(t, 0.01, false, function CF_LaunchTargetProjectile_Update)
endfunction

// Location Projectile
function CF_LaunchLocationProjectile_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local effect Projectile = CF_GetAttachedEffect("Projectile_Effect", t)
    local unit Credit = CF_GetAttachedUnit("Projectile_Credit", t)
    local real DamageAmount = CF_GetAttachedReal("Projectile_Damage", t)
    local real CurrentX = CF_GetEffectX(Projectile)
    local real CurrentY = CF_GetEffectY(Projectile)
    local real TargetX = CF_GetAttachedReal("Projectile_TargetX", t)
    local real TargetY = CF_GetAttachedReal("Projectile_TargetY", t)
    local real angle = bj_DEGTORAD * Atan2(TargetY - CurrentY, TargetX - CurrentX)
    local real distance = SquareRoot((TargetX - CurrentX) * (TargetX - CurrentX) + (TargetY - CurrentY) * (TargetY - CurrentY))
    local real speed = CF_GetAttachedReal("Projectile_Speed", t)
    local real time = distance / speed
    local real MovingDistance = distance / (time / 0.01)
    local real NewX = CurrentX + MovingDistance * Cos(angle * bj_DEGTORAD)
    local real NewY = CurrentY + MovingDistance * Sin(angle * bj_DEGTORAD)
    local boolean EffectAllies = CF_GetAttachedBoolean("Projectile_FriendlyFire", t)
    local group DamagedTargets = CF_GetAttachedGroup("Projectile_DamagedEnemies", t)
    local group PotentialTargets = CreateGroup()
    local group DamagingTargetsThisPush = CreateGroup()
    local unit PickedUnit
    local boolean AllowPickedUnitToBeDamaged = true
    call GroupEnumUnitsInRange(PotentialTargets, CurrentX, CurrentY, CF_MaxProjectileCollisionRange(), null)
    loop
        set PickedUnit = FirstOfGroup(PotentialTargets)
        exitwhen (PickedUnit == null)
        set AllowPickedUnitToBeDamaged = true
        if(IsUnitInGroup(PickedUnit, DamagedTargets) == true) then
            set AllowPickedUnitToBeDamaged = false
        endif
        if(IsPlayerEnemy(GetOwningPlayer(Credit), GetOwningPlayer(PickedUnit)) == false) and (EffectAllies == false) then
            set AllowPickedUnitToBeDamaged = false
        endif
        if(AllowPickedUnitToBeDamaged == true) then
            call GroupAddUnit(DamagingTargetsThisPush, PickedUnit)
        endif
        call GroupRemoveUnit(PotentialTargets, PickedUnit)
    endloop
    loop
        set PickedUnit = FirstOfGroup(DamagingTargetsThisPush)
        exitwhen(PickedUnit == null)
        call CF_UnitDamageUnit(Credit, PickedUnit, DamageAmount, 0, 4)
        call GroupAddUnit(DamagedTargets, PickedUnit)
        call GroupRemoveUnit(DamagingTargetsThisPush, PickedUnit)
    endloop
    if(distance > CF_MaxProjectileCollisionRange()) then
        call CF_DestroyTimer(t)
        call CF_DestroyEffect(Projectile)
        set t = null
        set Projectile = null
        set DamagedTargets = null
        set PotentialTargets = null
        set DamagingTargetsThisPush = null
    else
        call CF_SetEffectLoc(Projectile, NewX, NewY)
        call CF_AttachHandle(DamagedTargets, "Projectile_DamagedEnemies", t)
        call TimerStart(t, 0.01, false, function CF_LaunchLocationProjectile_Update)
    endif
    call DestroyGroup(PotentialTargets)
    call DestroyGroup(DamagingTargetsThisPush)     
endfunction

function CF_LaunchLocationProjectile_Begin takes unit credit, real startX, real startY, real endX, real endY, real damage, string modelPath, real speed, boolean effectAllies returns nothing
    local timer t = CreateTimer()
    local effect ProjectileEffect = CF_CreateEffect(startX, startY, modelPath)
    call CF_AttachHandle(credit, "Projectile_Credit", t)
    call CF_AttachHandle(ProjectileEffect, "Projectile_Effect", t)
    call CF_AttachHandle(CreateGroup(), "Projectile_DamagedEnemies", t) 
    call CF_AttachReal(endX, "Projectile_TargetX", t)
    call CF_AttachReal(endY, "Projectile_TargetY", t)
    call CF_AttachReal(damage, "Projectile_Damage", t)
    call CF_AttachReal(speed, "Projectile_Speed", t)
    call CF_AttachBoolean(effectAllies, "Projectile_FriendlyFire", t)
    call TimerStart(t, 0.01, false, function CF_LaunchLocationProjectile_Update)
endfunction

Also, if you could point out leaks/problems in other parts of the code, that would be great and well appreiciated.

EDIT: Oops, the dummy rawcode is slightly abilitized instead of a unit. Il fix it

EDIT2: I changed the rawcode, and now it does something atleast, but not the right thing, it fires the projectile all the way down the x line to the right, at 1000 speed (as i set it to be). When its just about to go out of the map, it stops(because of the IsLocSafe), then about 10 seconds later, it very slowly returns to the firing location.

This is really strange behavior, is their an explanation for this?

EDIT3: I decided to attach a test map, with the dummy.mdx and the code set up, all you have to do is type "-launch" ingame and it will do it.
For some reason you can only launch it once (dont ask me why i dont know either)
Attached Files
File type: w3xTest Projectile Code.w3x (25.0 KB)
05-29-2006, 07:38 PM#2
The)TideHunter(
Yes i posted not long ago, but i need this asap lol sorry.
*Bump*
05-29-2006, 07:42 PM#3
blu_da_noob
You are breaking the rules in bumping like that. Please observe them in future (especially considering that this is a rather large thing you are expecting people to check for you).

Edit: Think I found a (major) problem which could be the cause.
In functions CF_LaunchTargetProjectile_Update and CF_LaunchLocationProjectile_Update:
Collapse JASS:
    local real angle = bj_DEGTORAD * Atan2(TargetY - CurrentY, TargetX - CurrentX)

Should be:
Collapse JASS:
    local real angle = bj_RADTODEG * Atan2(TargetY - CurrentY, TargetX - CurrentX)

Also:
Collapse JASS:
    local real speed = CF_GetAttachedReal("Projectile_Speed", t)
    local real distance = SquareRoot((TargetX - CurrentX) * (TargetX - CurrentX) + (TargetY - CurrentY) * (TargetY - CurrentY))
    local real time = distance / speed
    local real MovingDistance = distance / (time / 0.01)
Is it intended for the missile to speed up as it gets closer to the target?
05-29-2006, 07:47 PM#4
The)TideHunter(
Yea im sorry, this is really just getting at me, iv been trying to fix it all day and still not found out why.

It wont happen again.

EDIT: Your right, i checked the AngleBetweenPoints and it uses it, i did the wrong 1.
Good spotting. Il go test it
05-29-2006, 07:50 PM#5
Rising_Dusk
Ok, after testing and checking that code you have posted for awhile, I've come to the conclusion that might lead to the error.

Collapse JASS:
// Main Functions
// Target Projectile
function CF_LaunchTargetProjectile_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local effect Projectile = CF_GetAttachedEffect("Projectile_Effect", t)
    local unit credit = CF_GetAttachedUnit("Projectile_Credit", t)
    local unit target = CF_GetAttachedUnit("Projectile_Target", t)
    local real DamageAmount = CF_GetAttachedReal("Projectile_Damage", t)
    local real CurrentX = CF_GetEffectX(Projectile)
    local real CurrentY = CF_GetEffectY(Projectile)
    local real TargetX = GetUnitX(target)               
    local real TargetY = GetUnitY(target)
    local real angle = bj_RADTODEG * Atan2(TargetY - CurrentY, TargetX - CurrentX)
    local real speed = CF_GetAttachedReal("Projectile_Speed", t)
    local real distance = SquareRoot((TargetX - CurrentX) * (TargetX - CurrentX) + (TargetY - CurrentY) * (TargetY - CurrentY))
    local real time = distance / speed
    local real MovingDistance = distance / (time / 0.01)
    local real NewX = CurrentX + MovingDistance * Cos(angle * bj_DEGTORAD)
    local real NewY = CurrentY + MovingDistance * Sin(angle * bj_DEGTORAD)
    if(distance < CF_MaxProjectileCollisionRange()) then
        call CF_UnitDamageUnit(credit, target, DamageAmount, 0, 4)
        call CF_DestroyEffect(Projectile)
        call CF_DestroyTimer(t)
        set t = null
        set Projectile = null
    else
        call CF_SetEffectLoc(Projectile, NewX, NewY)
        call TimerStart(t, 0.01, false, function CF_LaunchTargetProjectile_Update)
    endif         
endfunction

function CF_LaunchTargetProjectile_Begin takes unit credit, unit target, real startX, real startY, real damage, string modelPath, real speed returns nothing
    local timer t = CreateTimer()
    local effect ProjectileEffect = CF_CreateEffect(startX, startY, modelPath)
    call CF_AttachHandle(credit, "Projectile_Credit", t)
    call CF_AttachHandle(target, "Projectile_Target", t)
    call CF_AttachHandle(ProjectileEffect, "Projectile_Effect", t)
    call CF_AttachReal(damage, "Projectile_Damage", t)
    call CF_AttachReal(speed, "Projectile_Speed", t)
    call TimerStart(t, 0.01, false, function CF_LaunchTargetProjectile_Update)
endfunction

You're creating dozens of instances of that timer that are totally unnecessary.
Try this...

Collapse JASS:
// Main Functions
// Target Projectile
function CF_LaunchTargetProjectile_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local effect Projectile = CF_GetAttachedEffect("Projectile_Effect", t)
    local unit credit = CF_GetAttachedUnit("Projectile_Credit", t)
    local unit target = CF_GetAttachedUnit("Projectile_Target", t)
    local real DamageAmount = CF_GetAttachedReal("Projectile_Damage", t)
    local real CurrentX = CF_GetEffectX(Projectile)
    local real CurrentY = CF_GetEffectY(Projectile)
    local real TargetX = GetUnitX(target)               
    local real TargetY = GetUnitY(target)
    local real angle = bj_RADTODEG * Atan2(TargetY - CurrentY, TargetX - CurrentX)
    local real speed = CF_GetAttachedReal("Projectile_Speed", t)
    local real distance = SquareRoot((TargetX - CurrentX) * (TargetX - CurrentX) + (TargetY - CurrentY) * (TargetY - CurrentY))
    local real time = distance / speed
    local real MovingDistance = distance / (time / 0.01)
    local real NewX = CurrentX + MovingDistance * Cos(angle * bj_DEGTORAD)
    local real NewY = CurrentY + MovingDistance * Sin(angle * bj_DEGTORAD)
    if(distance < CF_MaxProjectileCollisionRange()) then
        call CF_UnitDamageUnit(credit, target, DamageAmount, 0, 4)
        call CF_DestroyEffect(Projectile)
        call CF_DestroyTimer(t)
    else
        call CF_SetEffectLoc(Projectile, NewX, NewY)
    endif         
    set credit = null
    set target = null
    set Projectile = null
    set t = null
endfunction

function CF_LaunchTargetProjectile_Begin takes unit credit, unit target, real startX, real startY, real damage, string modelPath, real speed returns nothing
    local timer t = CreateTimer()
    local effect ProjectileEffect = CF_CreateEffect(startX, startY, modelPath)
    call CF_AttachHandle(credit, "Projectile_Credit", t)
    call CF_AttachHandle(target, "Projectile_Target", t)
    call CF_AttachHandle(ProjectileEffect, "Projectile_Effect", t)
    call CF_AttachReal(damage, "Projectile_Damage", t)
    call CF_AttachReal(speed, "Projectile_Speed", t)
    call TimerStart(t, 0.01, true, function CF_LaunchTargetProjectile_Update)
    set ProjectileEffect = null
endfunction


I also nulled a few things you forgot to take care of.
Also, in the test map, what you said happened did not actually happen at all.

Quote:
when i launch a projectile, it just hurts the person thats launching it
That didn't happen to the Paladin, looked to me it fired neatly in some random direction.
05-29-2006, 07:54 PM#6
The)TideHunter(
Yes, it works fine now, the bj_RADTODEG fixed it totally.

Before the first Edit, my dummy rawcode was 'A000', i dident change it but i used to (not knowing it wasent the actual rawcode)
And i dident actually have the dummy imported into my map, it just hurt the paladin and dident do anything else.

Anyway, it works great now, thanks for spotting that :)
05-29-2006, 07:56 PM#7
blu_da_noob
Quote:
Originally Posted by blu_da_noob
Is it intended for the missile to speed up as it gets closer to the target?

Because with your current working out, that would be happening.
05-29-2006, 07:58 PM#8
The)TideHunter(
Yea it would, it shouldent but it would.
This was just for testing and not actual calculation.
I'l see what i can do now to change this
Does anybody have a working way to not increase the speed?
Would be much appreicated

EDIT:
Quote:
Originally Posted by Rising_Dusk
Ok, after testing and checking that code you have posted for awhile, I've come to the conclusion that might lead to the error.

Collapse JASS:
// Main Functions
// Target Projectile
function CF_LaunchTargetProjectile_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local effect Projectile = CF_GetAttachedEffect("Projectile_Effect", t)
    local unit credit = CF_GetAttachedUnit("Projectile_Credit", t)
    local unit target = CF_GetAttachedUnit("Projectile_Target", t)
    local real DamageAmount = CF_GetAttachedReal("Projectile_Damage", t)
    local real CurrentX = CF_GetEffectX(Projectile)
    local real CurrentY = CF_GetEffectY(Projectile)
    local real TargetX = GetUnitX(target)               
    local real TargetY = GetUnitY(target)
    local real angle = bj_RADTODEG * Atan2(TargetY - CurrentY, TargetX - CurrentX)
    local real speed = CF_GetAttachedReal("Projectile_Speed", t)
    local real distance = SquareRoot((TargetX - CurrentX) * (TargetX - CurrentX) + (TargetY - CurrentY) * (TargetY - CurrentY))
    local real time = distance / speed
    local real MovingDistance = distance / (time / 0.01)
    local real NewX = CurrentX + MovingDistance * Cos(angle * bj_DEGTORAD)
    local real NewY = CurrentY + MovingDistance * Sin(angle * bj_DEGTORAD)
    if(distance < CF_MaxProjectileCollisionRange()) then
        call CF_UnitDamageUnit(credit, target, DamageAmount, 0, 4)
        call CF_DestroyEffect(Projectile)
        call CF_DestroyTimer(t)
        set t = null
        set Projectile = null
    else
        call CF_SetEffectLoc(Projectile, NewX, NewY)
        call TimerStart(t, 0.01, false, function CF_LaunchTargetProjectile_Update)
    endif         
endfunction

function CF_LaunchTargetProjectile_Begin takes unit credit, unit target, real startX, real startY, real damage, string modelPath, real speed returns nothing
    local timer t = CreateTimer()
    local effect ProjectileEffect = CF_CreateEffect(startX, startY, modelPath)
    call CF_AttachHandle(credit, "Projectile_Credit", t)
    call CF_AttachHandle(target, "Projectile_Target", t)
    call CF_AttachHandle(ProjectileEffect, "Projectile_Effect", t)
    call CF_AttachReal(damage, "Projectile_Damage", t)
    call CF_AttachReal(speed, "Projectile_Speed", t)
    call TimerStart(t, 0.01, false, function CF_LaunchTargetProjectile_Update)
endfunction

You're creating dozens of instances of that timer that are totally unnecessary.
Try this...

Collapse JASS:
// Main Functions
// Target Projectile
function CF_LaunchTargetProjectile_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local effect Projectile = CF_GetAttachedEffect("Projectile_Effect", t)
    local unit credit = CF_GetAttachedUnit("Projectile_Credit", t)
    local unit target = CF_GetAttachedUnit("Projectile_Target", t)
    local real DamageAmount = CF_GetAttachedReal("Projectile_Damage", t)
    local real CurrentX = CF_GetEffectX(Projectile)
    local real CurrentY = CF_GetEffectY(Projectile)
    local real TargetX = GetUnitX(target)               
    local real TargetY = GetUnitY(target)
    local real angle = bj_RADTODEG * Atan2(TargetY - CurrentY, TargetX - CurrentX)
    local real speed = CF_GetAttachedReal("Projectile_Speed", t)
    local real distance = SquareRoot((TargetX - CurrentX) * (TargetX - CurrentX) + (TargetY - CurrentY) * (TargetY - CurrentY))
    local real time = distance / speed
    local real MovingDistance = distance / (time / 0.01)
    local real NewX = CurrentX + MovingDistance * Cos(angle * bj_DEGTORAD)
    local real NewY = CurrentY + MovingDistance * Sin(angle * bj_DEGTORAD)
    if(distance < CF_MaxProjectileCollisionRange()) then
        call CF_UnitDamageUnit(credit, target, DamageAmount, 0, 4)
        call CF_DestroyEffect(Projectile)
        call CF_DestroyTimer(t)
    else
        call CF_SetEffectLoc(Projectile, NewX, NewY)
    endif         
    set credit = null
    set target = null
    set Projectile = null
    set t = null
endfunction

function CF_LaunchTargetProjectile_Begin takes unit credit, unit target, real startX, real startY, real damage, string modelPath, real speed returns nothing
    local timer t = CreateTimer()
    local effect ProjectileEffect = CF_CreateEffect(startX, startY, modelPath)
    call CF_AttachHandle(credit, "Projectile_Credit", t)
    call CF_AttachHandle(target, "Projectile_Target", t)
    call CF_AttachHandle(ProjectileEffect, "Projectile_Effect", t)
    call CF_AttachReal(damage, "Projectile_Damage", t)
    call CF_AttachReal(speed, "Projectile_Speed", t)
    call TimerStart(t, 0.01, true, function CF_LaunchTargetProjectile_Update)
    set ProjectileEffect = null
endfunction


I also nulled a few things you forgot to take care of.
Also, in the test map, what you said happened did not actually happen at all.


That didn't happen to the Paladin, looked to me it fired neatly in some random direction.

I was wondering, you nulled the timer, iv been wondering this for a while, you cant null things you are still going to use can you? im not sure.
I thought i cant null the units, projectile and timer because im still using them, like the expression: "Your cant null a timer if its still working, you have to pause it first".

This has really confused me in the past, so i have avioded nulling them until i found the answer.
Thanks for that il change my code

Btw, how am i creating more timers?
05-29-2006, 08:06 PM#9
blu_da_noob
I also see nothing about additional timer creation.

This should tell you what you need to know about nulling variables.
05-29-2006, 08:47 PM#10
The)TideHunter(
Any ideas on how to stop it getting faster when getting nearer?

EDIT: I think i will just attach the original speed to the timer and get it back again.

EDIT2: I added a effect face function to make it look realistic, and added a boolean to check if its the first time calculating the speed or not, so it should work quite well now, im going to test.
Heres the updated code:

Collapse JASS:
// Globals (Mainly for Jass Editing Programs)
globals
    gamecache udg_GC = null
endglobals

// Casual Functions Engine
// Created and Updated by The)TideHunter(
// Creation Began: 28/05/06
// Last Updated: 29/05/06

// Game Cache Return Function
function CF_GC takes nothing returns gamecache
    if(udg_GC == null) then
        call FlushGameCache(InitGameCache("GC"))
        set udg_GC = InitGameCache("GC")
    endif
    return udg_GC
endfunction

// Constants
constant function CF_MaxProjectileCollisionRange takes nothing returns real
    return 5.
endfunction

// Rawcodes
constant function CF_DummyRawcode takes nothing returns integer
    return 'hpea'
endfunction

// Handle Variables
function CF_H2I takes handle H returns integer
    return H
    return 0
endfunction

function CF_I2Unit takes integer I returns unit
    return I
    return null
endfunction

function CF_I2Effect takes integer I returns effect
    return I
    return null
endfunction

function CF_I2Group takes integer I returns group
    return I
    return null
endfunction

// Attach Variables
function CF_StoreHandle takes handle whichHandle, string label, string handleType returns nothing
    call StoreInteger(CF_GC(), handleType, label, CF_H2I(whichHandle))
endfunction

function CF_AttachInt takes integer whichInt, string label, handle attachToWhichHandle returns nothing
    call StoreInteger(CF_GC(), I2S(CF_H2I(attachToWhichHandle)), label, whichInt)
endfunction

function CF_AttachString takes string whichString, string label, handle attachToWhichHandle returns nothing
    call StoreString(CF_GC(), I2S(CF_H2I(attachToWhichHandle)), label, whichString)
endfunction

function CF_AttachReal takes real whichReal, string label, handle attachToWhichHandle returns nothing
    call StoreReal(CF_GC(), I2S(CF_H2I(attachToWhichHandle)), label, whichReal)
endfunction

function CF_AttachBoolean takes boolean whichBoolean, string label, handle attachToWhichHandle returns nothing
    call StoreBoolean(CF_GC(), I2S(CF_H2I(attachToWhichHandle)), label, whichBoolean)
endfunction

function CF_AttachHandle takes handle whichHandle, string label, handle attachToWhichHandle returns nothing
    call StoreInteger(CF_GC(), I2S(CF_H2I(attachToWhichHandle)), label, CF_H2I(whichHandle))
endfunction

function CF_GetStoredEffect takes string label returns handle
    return CF_I2Effect(GetStoredInteger(CF_GC(), "Effect", label))
endfunction

function CF_GetAttachedInt takes string label, handle attachedHandle returns integer
    return GetStoredInteger(CF_GC(), I2S(CF_H2I(attachedHandle)), label)
endfunction

function CF_GetAttachedString takes string label, handle attachedHandle returns string
    return GetStoredString(CF_GC(), I2S(CF_H2I(attachedHandle)), label)
endfunction

function CF_GetAttachedReal takes string label, handle attachedHandle returns real
    return GetStoredReal(CF_GC(), I2S(CF_H2I(attachedHandle)), label)
endfunction

function CF_GetAttachedBoolean takes string label, handle attachedHandle returns boolean
    return GetStoredBoolean(CF_GC(), I2S(CF_H2I(attachedHandle)), label)
endfunction

function CF_GetAttachedUnit takes string label, handle attachedHandle returns unit
    return CF_I2Unit(GetStoredInteger(CF_GC(), I2S(CF_H2I(attachedHandle)), label))
endfunction

function CF_GetAttachedEffect takes string label, handle attachedHandle returns effect
    return CF_I2Effect(GetStoredInteger(CF_GC(), I2S(CF_H2I(attachedHandle)), label))
endfunction

function CF_GetAttachedGroup takes string label, handle attachedHandle returns group
    return CF_I2Group(GetStoredInteger(CF_GC(), I2S(CF_H2I(attachedHandle)), label))
endfunction

function CF_RemoveAttachments takes handle attachedHandle returns nothing
    call FlushStoredMission(CF_GC(), I2S(CF_H2I(attachedHandle)))
endfunction

// Common Functions
function CF_IsXSafe takes real X returns boolean
    local rect SafeRect = bj_mapInitialPlayableArea
    local real MinSafeX = GetRectMinX(SafeRect)
    local real MaxSafeX = GetRectMaxX(SafeRect)
    if(MinSafeX < X) and (MaxSafeX > X) then
        return true
    endif
    call RemoveRect(SafeRect)
    set SafeRect = null
    return false
endfunction

function CF_IsYSafe takes real Y returns boolean
    local rect SafeRect = bj_mapInitialPlayableArea
    local real MinSafeY = GetRectMinY(SafeRect)
    local real MaxSafeY = GetRectMaxY(SafeRect)
    if(MinSafeY < Y) and (MaxSafeY > Y) then
        return true
    endif
    call RemoveRect(SafeRect)
    set SafeRect = null
    return false
endfunction

function CF_IsLocSafe takes real X, real Y returns boolean
    if(CF_IsXSafe(X) == true) and (CF_IsYSafe(Y) == true) then
        return true
    endif
    return false
endfunction

function CF_IsLocSafeEx takes location whichLocation returns boolean
    return CF_IsLocSafe(GetLocationX(whichLocation), GetLocationY(whichLocation))
endfunction

function CF_DestroyTimer takes timer whichTimer returns nothing
    call CF_RemoveAttachments(whichTimer)
    call DestroyTimer(whichTimer)
endfunction

function CF_UnitDamageUnit takes unit credit, unit target, real amount, integer attackIndex, integer damageIndex returns nothing
    call UnitDamageTarget(credit, target, amount, true, false, ConvertAttackType(attackIndex), ConvertDamageType(damageIndex), ConvertWeaponType(0))
endfunction

function CF_UnitSpellDamageUnit takes unit credit, unit target, real amount returns nothing
    if(IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) == false) then
        call CF_UnitDamageUnit(credit, target, amount, 4, 26)  
    endif
endfunction

function CF_GetADummy takes real X, real Y returns unit
    local unit u = CreateUnit(Player(15), CF_DummyRawcode(), X, Y, 0.)
    call UnitAddAbility(u, 'Avul')
    call UnitAddAbility(u, 'Aloc')
    return u
endfunction 

// Extended Creation Functions
// Effect
function CF_CreateEffect takes real X, real Y, string modelPath returns effect
    local unit CarryingUnit
    local effect NewEffect
    if(CF_IsLocSafe(X, Y) == true) then
        set CarryingUnit = CF_GetADummy(X, Y)
        set NewEffect = AddSpecialEffectTarget(modelPath, CarryingUnit, "origin")
        call CF_AttachHandle(CarryingUnit, "Effect_CarryingUnit", NewEffect)
        call CF_AttachReal(X, "Effect_CoordX", NewEffect)
        call CF_AttachReal(Y, "Effect_CoordY", NewEffect)
        call CF_AttachString(modelPath, "Effect_ModelPath", NewEffect)
        call CF_StoreHandle(NewEffect, "LastCreatedEffect", "Effect")
        return NewEffect
    endif
    return null
endfunction

function CF_GetEffectCarryingUnit takes effect whichEffect returns unit
    return CF_I2Unit(CF_GetAttachedInt("Effect_CarryingUnit", whichEffect))
endfunction

function CF_GetEffectX takes effect whichEffect returns real
    return CF_GetAttachedReal("Effect_CoordX", whichEffect)
endfunction

function CF_GetEffectY takes effect whichEffect returns real
    return CF_GetAttachedReal("Effect_CoordY", whichEffect)
endfunction

function CF_GetEffectLoc takes effect whichEffect returns location
    return Location(CF_GetEffectX(whichEffect), CF_GetEffectY(whichEffect))
endfunction

function CF_GetEffectModelPath takes effect whichEffect returns string
    return CF_GetAttachedString("Effect_ModelPath", whichEffect)
endfunction

function CF_GetLastCreatedEffect takes nothing returns effect
    return CF_GetStoredEffect("LastCreatedEffect")
endfunction

function CF_SetEffectX takes effect whichEffect, real X returns nothing
    if(CF_IsXSafe(X) == true) then
        call SetUnitX(CF_GetEffectCarryingUnit(whichEffect), X)
        call CF_AttachReal(X, "Effect_CoordX", whichEffect)
    endif
endfunction

function CF_SetEffectY takes effect whichEffect, real Y returns nothing
    if(CF_IsYSafe(Y) == true) then
        call SetUnitY(CF_GetEffectCarryingUnit(whichEffect), Y)
        call CF_AttachReal(Y, "Effect_CoordY", whichEffect)
    endif
endfunction

function CF_SetEffectLoc takes effect whichEffect, real X, real Y returns nothing
    if(CF_IsLocSafe(X, Y) == true) then
        call CF_SetEffectX(whichEffect, X)
        call CF_SetEffectY(whichEffect, Y)
    endif
endfunction

function CF_SetEffectLocEx takes effect whichEffect, location whichLoc returns nothing
    call CF_SetEffectLoc(whichEffect, GetLocationX(whichLoc), GetLocationY(whichLoc))
endfunction

function CF_MakeEffectFaceAngle takes effect whichEffect, real angle returns nothing
    call SetUnitFacing(CF_GetEffectCarryingUnit(whichEffect), angle)
endfunction

function CF_MakeEffectFaceAngleOverTime takes effect whichEffect, real angle, real duration returns nothing
    call SetUnitFacingTimed(CF_GetEffectCarryingUnit(whichEffect), angle, duration)
endfunction

function CF_MoveEffectFacingAngle takes effect whichEffect, real angle, real X, real Y returns nothing
    call CF_SetEffectLoc(whichEffect, X, Y)
    call CF_MakeEffectFaceAngle(whichEffect, angle)
endfunction

function CF_MoveEffectFacingAngleOverTime takes effect whichEffect, real angle, real X, real Y, real duration returns nothing
    call CF_SetEffectLoc(whichEffect, X, Y)
    call CF_MakeEffectFaceAngleOverTime(whichEffect, angle, duration)
endfunction     

function CF_CopyEffect takes effect whichEffect returns effect
    return CF_CreateEffect(CF_GetEffectX(whichEffect), CF_GetEffectY(whichEffect), CF_GetEffectModelPath(whichEffect))
endfunction

function CF_CopyEffectNewLoc takes effect whichEffect, real X, real Y returns effect
    local effect NewEffect = CF_CopyEffect(whichEffect)
    call CF_SetEffectLoc(NewEffect, X, Y)
    return NewEffect
endfunction

function CF_CopyEffectNewLocEx takes effect whichEffect, location whichLoc returns effect
    return CF_CopyEffectNewLoc(whichEffect, GetLocationX(whichLoc), GetLocationY(whichLoc))
endfunction

function CF_DestroyEffect takes effect whichEffect returns nothing
    local unit CarryingUnit = CF_GetEffectCarryingUnit(whichEffect)
    call CF_RemoveAttachments(whichEffect)
    call DestroyEffect(whichEffect)
    call RemoveUnit(CarryingUnit)
    set CarryingUnit = null
endfunction

function CF_DestroyTempEffect takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local effect DestroyingEffect = CF_GetAttachedEffect("Timer_TempEffect", t)
    call CF_DestroyEffect(DestroyingEffect)
    call CF_DestroyTimer(t)
    set t = null
    set DestroyingEffect = null
endfunction

function CF_CreateTempEffect takes real X, real Y, string modelPath, real duration returns effect
    local timer t = CreateTimer()
    local effect NewEffect = CF_CreateEffect(X, Y, modelPath)
    call CF_AttachHandle(NewEffect, "Timer_TempEffect", t)
    call TimerStart(t, duration, false, function CF_DestroyTempEffect)
    return NewEffect
endfunction

function CF_CreateTempEffectLoc takes location whichLoc, string modelPath, real duration returns effect
    return CF_CreateTempEffect(GetLocationX(whichLoc), GetLocationY(whichLoc), modelPath, duration)
endfunction
     
function CF_CopyTempEffect takes effect whichEffect, real duration returns effect
    local timer t = CreateTimer()
    local effect NewEffect = CF_CopyEffect(whichEffect)
    call CF_AttachHandle(NewEffect, "Timer_TempEffect", t)
    call TimerStart(t, duration, false, function CF_DestroyTempEffect)
    return NewEffect
endfunction

function CF_CopyTempEffectLoc takes effect whichEffect, real X, real Y, real duration returns effect
    local timer t = CreateTimer()
    local effect NewEffect = CF_CopyEffectNewLoc(whichEffect, X, Y)
    call CF_AttachHandle(NewEffect, "Timer_TempEffect", t)
    call TimerStart(t, duration, false, function CF_DestroyTempEffect)
    return NewEffect
endfunction

function CF_CopyTempEffectLocEx takes effect whichEffect, location whichLoc, real duration returns effect
    local timer t = CreateTimer()
    local effect NewEffect = CF_CopyEffectNewLocEx(whichEffect, whichLoc)
    call CF_AttachHandle(NewEffect, "Timer_TempEffect", t)
    call TimerStart(t, duration, false, function CF_DestroyTempEffect)
    return NewEffect
endfunction

// Main Functions
// Target Projectile
function CF_LaunchTargetProjectile_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local effect Projectile = CF_GetAttachedEffect("Projectile_Effect", t)
    local unit credit = CF_GetAttachedUnit("Projectile_Credit", t)
    local unit target = CF_GetAttachedUnit("Projectile_Target", t)
    local real DamageAmount = CF_GetAttachedReal("Projectile_Damage", t)
    local real CurrentX = CF_GetEffectX(Projectile)
    local real CurrentY = CF_GetEffectY(Projectile)
    local real TargetX = GetUnitX(target)               
    local real TargetY = GetUnitY(target)
    local real angle = bj_RADTODEG * Atan2(TargetY - CurrentY, TargetX - CurrentX)
    local real speed = CF_GetAttachedReal("Projectile_Speed", t)
    local real distance = SquareRoot((TargetX - CurrentX) * (TargetX - CurrentX) + (TargetY - CurrentY) * (TargetY - CurrentY))
    local real time = distance / speed
    local real MovingDistance = CF_GetAttachedReal("Projectile_MovingDistance", t)
    local real NewX
    local real NewY
    local boolean FirstRun = CF_GetAttachedBoolean("Projectile_FirstRun", t)
    if(FirstRun == true) then
        set MovingDistance = distance / (time / 0.01)
        call CF_AttachReal(MovingDistance, "Projectile_MovingDistance", t)
        call CF_AttachBoolean(false, "Projectile_FirstRun", t)
    endif
    set NewX = CurrentX + MovingDistance * Cos(angle * bj_DEGTORAD)
    set NewY = CurrentY + MovingDistance * Sin(angle * bj_DEGTORAD) 
    if(distance < CF_MaxProjectileCollisionRange()) then
        call CF_UnitDamageUnit(credit, target, DamageAmount, 0, 4)
        call CF_DestroyEffect(Projectile)
        call CF_DestroyTimer(t)
        set t = null
        set Projectile = null
    else
        call CF_MoveEffectFacingAngle(Projectile, angle, NewX, NewY) 
        call TimerStart(t, 0.01, false, function CF_LaunchTargetProjectile_Update)
    endif         
endfunction

function CF_LaunchTargetProjectile_Begin takes unit credit, unit target, real startX, real startY, real damage, string modelPath, real speed returns nothing
    local timer t = CreateTimer()
    local effect ProjectileEffect = CF_CreateEffect(startX, startY, modelPath)
    call CF_AttachHandle(credit, "Projectile_Credit", t)
    call CF_AttachHandle(target, "Projectile_Target", t)
    call CF_AttachHandle(ProjectileEffect, "Projectile_Effect", t)
    call CF_AttachReal(damage, "Projectile_Damage", t)
    call CF_AttachReal(speed, "Projectile_Speed", t)
    call CF_AttachBoolean(true, "Projectile_FirstRun", t)
    call CF_AttachReal(0., "Projectile_MovingDistance", t)
    call TimerStart(t, 0.01, false, function CF_LaunchTargetProjectile_Update)
endfunction

// Location Projectile
function CF_LaunchLocationProjectile_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local effect Projectile = CF_GetAttachedEffect("Projectile_Effect", t)
    local unit Credit = CF_GetAttachedUnit("Projectile_Credit", t)
    local real DamageAmount = CF_GetAttachedReal("Projectile_Damage", t)
    local real CurrentX = CF_GetEffectX(Projectile)
    local real CurrentY = CF_GetEffectY(Projectile)
    local real TargetX = CF_GetAttachedReal("Projectile_TargetX", t)
    local real TargetY = CF_GetAttachedReal("Projectile_TargetY", t)
    local real angle = bj_RADTODEG * Atan2(TargetY - CurrentY, TargetX - CurrentX)
    local real distance = SquareRoot((TargetX - CurrentX) * (TargetX - CurrentX) + (TargetY - CurrentY) * (TargetY - CurrentY))
    local real speed = CF_GetAttachedReal("Projectile_Speed", t)
    local real time = distance / speed
    local real MovingDistance = distance / (time / 0.01)
    local real NewX = CurrentX + MovingDistance * Cos(angle * bj_DEGTORAD)
    local real NewY = CurrentY + MovingDistance * Sin(angle * bj_DEGTORAD)
    local boolean EffectAllies = CF_GetAttachedBoolean("Projectile_FriendlyFire", t)
    local group DamagedTargets = CF_GetAttachedGroup("Projectile_DamagedEnemies", t)
    local group PotentialTargets = CreateGroup()
    local group DamagingTargetsThisPush = CreateGroup()
    local unit PickedUnit
    local boolean AllowPickedUnitToBeDamaged = true
    call GroupEnumUnitsInRange(PotentialTargets, CurrentX, CurrentY, CF_MaxProjectileCollisionRange(), null)
    loop
        set PickedUnit = FirstOfGroup(PotentialTargets)
        exitwhen (PickedUnit == null)
        set AllowPickedUnitToBeDamaged = true
        if(IsUnitInGroup(PickedUnit, DamagedTargets) == true) then
            set AllowPickedUnitToBeDamaged = false
        endif
        if(IsPlayerEnemy(GetOwningPlayer(Credit), GetOwningPlayer(PickedUnit)) == false) and (EffectAllies == false) then
            set AllowPickedUnitToBeDamaged = false
        endif
        if(AllowPickedUnitToBeDamaged == true) then
            call GroupAddUnit(DamagingTargetsThisPush, PickedUnit)
        endif
        call GroupRemoveUnit(PotentialTargets, PickedUnit)
    endloop
    loop
        set PickedUnit = FirstOfGroup(DamagingTargetsThisPush)
        exitwhen(PickedUnit == null)
        call CF_UnitDamageUnit(Credit, PickedUnit, DamageAmount, 0, 4)
        call GroupAddUnit(DamagedTargets, PickedUnit)
        call GroupRemoveUnit(DamagingTargetsThisPush, PickedUnit)
    endloop
    if(distance > CF_MaxProjectileCollisionRange()) then
        call CF_DestroyTimer(t)
        call CF_DestroyEffect(Projectile)
        set t = null
        set Projectile = null
        set DamagedTargets = null
        set PotentialTargets = null
        set DamagingTargetsThisPush = null
    else
        call CF_SetEffectLoc(Projectile, NewX, NewY)
        call CF_AttachHandle(DamagedTargets, "Projectile_DamagedEnemies", t)
        call TimerStart(t, 0.01, false, function CF_LaunchLocationProjectile_Update)
    endif
    call DestroyGroup(PotentialTargets)
    call DestroyGroup(DamagingTargetsThisPush)     
endfunction

function CF_LaunchLocationProjectile_Begin takes unit credit, real startX, real startY, real endX, real endY, real damage, string modelPath, real speed, boolean effectAllies returns nothing
    local timer t = CreateTimer()
    local effect ProjectileEffect = CF_CreateEffect(startX, startY, modelPath)
    call CF_AttachHandle(credit, "Projectile_Credit", t)
    call CF_AttachHandle(ProjectileEffect, "Projectile_Effect", t)
    call CF_AttachHandle(CreateGroup(), "Projectile_DamagedEnemies", t) 
    call CF_AttachReal(endX, "Projectile_TargetX", t)
    call CF_AttachReal(endY, "Projectile_TargetY", t)
    call CF_AttachReal(damage, "Projectile_Damage", t)
    call CF_AttachReal(speed, "Projectile_Speed", t)
    call CF_AttachBoolean(effectAllies, "Projectile_FriendlyFire", t)
    call TimerStart(t, 0.01, false, function CF_LaunchLocationProjectile_Update)
endfunction

EDIT3: Everything works correctly now, its the same speed constantly, this thread is over! :)