HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Spell exiting instantly, help!

07-17-2006, 07:01 PM#1
The)TideHunter(
Hey guys, so i'v been making another spell.
But the spell i made, dosent work, it exits itself instantly.
It will auto-exit if the caster is within 12.5 yds of the target location, or if the casters order id isent "tornado".

I used debug messages, and they work, but it just shows that the spell dosent.

I used my CS functions and wrote the rest myself, il attach a test map, the CS functions and my spell.

Spell:

Collapse JASS:
// Spell
// Slash Strike
//============================================================
// Configuration
constant function BaB_Spell_SlashStrike_Rawcode takes nothing returns integer
    return '????'
endfunction
constant function BaB_Spell_SlashStrike_ChannelOrderString takes nothing returns string
    return "?????"
endfunction

constant function BaB_Spell_SlashStrike_Damage takes integer level returns real
    return (level * 100.) + 100.
endfunction
constant function BaB_Spell_SlashStrike_DamageRadius takes nothing returns real
    return 125.
endfunction
constant function BaB_Spell_SlashStrike_AttackTypeIndex takes nothing returns integer
    return 4
endfunction
constant function BaB_Spell_SlashStrike_DamageTypeIndex takes nothing returns integer
    return 4
endfunction
constant function BaB_Spell_SlashStrike_DamageInterval takes nothing returns real
    return 1.
endfunction

constant function BaB_Spell_SlashStrike_MoveSpeed takes nothing returns real
    return 700.
endfunction
constant function BaB_Spell_SlashStrike_AnimationSpeed takes nothing returns real
    return 300.
endfunction

constant function BaB_Spell_SlashStrike_NightChance takes integer level returns real
    return level * 5.
endfunction
constant function BaB_Spell_SlashStrike_NightChanceDamage takes nothing returns real
    return 100.
endfunction

//============================================================
// Slash Strike
function BaB_Spell_SlashStrike_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit Caster = CF_GetAttachedUnit(t, "Spell_SlashStrike_Caster")
    local integer AbilLevel = CF_GetAttachedInteger(t, "Spell_SlashStrike_AbilLevel")
    local real Progress = CF_GetAttachedReal(t, "Spell_SlashStrike_Progress")
    local real TargetX = CF_GetAttachedReal(t, "Spell_SlashStrike_TargetX")
    local real TargetY = CF_GetAttachedReal(t, "Spell_SlashStrike_TargetY")
    local real CasterX = GetUnitX(Caster)
    local real CasterY = GetUnitY(Caster)
    local real Angle = bj_RADTODEG * Atan2(TargetY - CasterY, TargetX - CasterX)
    local real StartingX = CF_GetAttachedReal(t, "Spell_SlashStrike_StartingX")
    local real StartingY = CF_GetAttachedReal(t, "Spell_SlashStrike_StartingY")
    local real MinTimerUpdate = CF_Constant_MinTimerUpdate()
    local real DistanceX = TargetX - CasterX
    local real DistanceY = TargetY - CasterY 
    local real Distance = SquareRoot((DistanceX * DistanceX) - (DistanceY * DistanceX))
    local real MoveSpeed = BaB_Spell_SlashStrike_MoveSpeed() 
    local real NewX = CasterX + (MoveSpeed / MinTimerUpdate) * Cos(Angle * bj_DEGTORAD)
    local real NewY = CasterY + (MoveSpeed / MinTimerUpdate) * Sin(Angle * bj_DEGTORAD)
    local group AoE
    local real Damage = BaB_Spell_SlashStrike_Damage(AbilLevel)
    local unit CurrentUnit
    local real Random = GetRandomReal(0., 100.)
    local integer AttackIndex = BaB_Spell_SlashStrike_AttackTypeIndex()
    local integer DamageIndex = BaB_Spell_SlashStrike_DamageTypeIndex()
    local real DamageInterval = BaB_Spell_SlashStrike_DamageInterval()
    if(Distance < CF_Constant_CollisionDetectionRange() or (GetUnitCurrentOrder(GetTriggerUnit()) != String2OrderIdBJ("monsoon"))) then
        call CF_DestroyTimer(t)
        set t = null
        call SetUnitTimeScale(Caster, 1.)
    else
        if(Progress >= DamageInterval) then
            set AoE = CreateGroup()
            call GroupEnumUnitsInRange(AoE, CasterX, CasterY, BaB_Spell_SlashStrike_DamageRadius(), null)
            if(BaB_Spell_SlashStrike_NightChance(AbilLevel) > Random) then
                set Damage = Damage + 100
            endif
            loop
                set CurrentUnit = FirstOfGroup(AoE)
                exitwhen CurrentUnit == null
                if(IsPlayerEnemy(GetOwningPlayer(Caster), GetOwningPlayer(CurrentUnit))) then
                    call CF_DamageWidget(Caster, CurrentUnit, Damage, AttackIndex, DamageIndex)
                endif
                call GroupRemoveUnit(AoE, CurrentUnit)
            endloop
            call DestroyGroup(AoE)
        endif
        call CF_SetUnitLoc(Caster, NewX, NewY)
        call TimerStart(t, MinTimerUpdate, false, function BaB_Spell_SlashStrike_Update)
    endif
endfunction

function BaB_Spell_SlashStrike takes nothing returns nothing
    local timer t = CreateTimer()
    local unit Caster = GetSpellAbilityUnit()
    local integer AbilLevel = CF_GetSpellLevel()
    local real CasterX = GetUnitX(Caster)
    local real CasterY = GetUnitY(Caster)
    local location TargetLoc = GetSpellTargetLoc()
    local real TargetX = GetLocationX(TargetLoc)
    local real TargetY = GetLocationY(TargetLoc)
    local real Damage = BaB_Spell_SlashStrike_Damage(AbilLevel)
    local group AoE = CreateGroup()
    local integer AttackIndex = BaB_Spell_SlashStrike_AttackTypeIndex()
    local integer DamageIndex = BaB_Spell_SlashStrike_DamageTypeIndex()
    local unit CurrentUnit
    local real Random = GetRandomReal(0., 100.)
    local real MinTimerUpdate = CF_Constant_MinTimerUpdate()
    call CF_AttachHandle(Caster, "Spell_SlashStrike_Caster", t)
    call CF_AttachInteger(AbilLevel, "Spell_SlashStrike_AbilLevel", t)
    call CF_AttachReal(TargetX, "Spell_SlashStrike_TargetX", t)
    call CF_AttachReal(TargetY, "Spell_SlashStrike_TargetY", t)
    call CF_AttachReal(MinTimerUpdate, "Spell_SlashStrike_Progress", t)
    call CF_AttachReal(CasterX, "Spell_SlashStrike_StartingX", t)
    call CF_AttachReal(CasterY, "Spell_SlashStrike_StartingY", t)
    call GroupEnumUnitsInRange(AoE, CasterX, CasterY, BaB_Spell_SlashStrike_DamageRadius(), null)
    loop
        set CurrentUnit = FirstOfGroup(AoE)
        exitwhen CurrentUnit == null
        if(IsPlayerEnemy(GetOwningPlayer(Caster), GetOwningPlayer(CurrentUnit))) then
            if(Random <= BaB_Spell_SlashStrike_NightChance(AbilLevel)) then
                set Damage = Damage + BaB_Spell_SlashStrike_NightChanceDamage()
            endif
            call CF_DamageWidget(Caster, CurrentUnit, Damage, AttackIndex, DamageIndex)
        endif
        call GroupRemoveUnit(AoE, CurrentUnit)
    endloop
    call SetUnitTimeScale(Caster, BaB_Spell_SlashStrike_AnimationSpeed() * 0.01)
    call TimerStart(t, MinTimerUpdate, false, function BaB_Spell_SlashStrike_Update)
    call RemoveLocation(TargetLoc)
    call DestroyGroup(AoE)
endfunction

CS Functions:

Collapse JASS:
// Casual Functions Engine
// Created and Updated by The)TideHunter(
// Creation Began: 28/05/06
// Last Updated: 17/07/06

// Global, the gamecache is needed for CS Functions to work
globals
    gamecache udg_GC = null
endglobals

// This is the GameCache 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, you may edit these to fit what you want.
constant function CF_Constant_CollisionDetectionRange takes nothing returns real
    return 25. // This is the value used in functions that use a collision method.
               // When the functions collision comes in this range, the function
               // will do whats its meant to do.
endfunction

constant function CF_Constant_MinTimerUpdate takes nothing returns real
    return 0.04 // This looks convincing, and isent lag friendly.
                // Credit: Vexorian
                // This was the value I used from his Caster System.
endfunction

constant function CF_Constant_DummyUnitRawcode takes nothing returns integer
    return '????' // Dummy rawcode or your dummy.
                  // This 'MUST' be Vexorian's custom created dummy model.
                  // ~It has the correct attachment points.
endfunction

constant function CF_Constant_MorphUnitFlyAbilityRawcode takes nothing returns integer
    return '????' // Rawcode of the Morph ability in your map.
endfunction

// Variable Switches
function CF_B2I takes boolean B returns integer
    if(B) then
        return 1
    endif
    return 0
endfunction

function CF_I2B takes integer I returns boolean
    if(I == 1) then
        return true
    endif
    return false
endfunction

function CF_B2S takes boolean B returns string
    return I2S(CF_B2I(B))
endfunction

function CF_S2B takes string S returns boolean
    return CF_I2B(S2I(S))
endfunction

// Return Bug
function CF_H2I takes handle H returns integer
    return H
    return 0
endfunction
function CF_H2S takes handle H returns string
    return I2S(CF_H2I(H))
endfunction

function CF_I2Ability takes integer I returns ability
    return I
    return null
endfunction
function CF_I2AIDifficulty takes integer I returns aidifficulty
    return I
    return null
endfunction
function CF_I2AillianceType takes integer I returns alliancetype
    return I
    return null
endfunction
function CF_I2AttackType takes integer I returns attacktype
    return I
    return null
endfunction
function CF_I2Blendmode takes integer I returns blendmode
    return I
    return null
endfunction
function CF_I2BooleanExpression takes integer I returns boolexpr
    return I
    return null
endfunction
function CF_I2Buff takes integer I returns buff
    return I
    return null
endfunction
function CF_I2Button takes integer I returns button
    return I
    return null
endfunction
function CF_I2Camerafield takes integer I returns camerafield
    return I
    return null
endfunction
function CF_I2CameraSetup takes integer I returns camerasetup
    return I
    return null
endfunction
function CF_I2ConditionFunction takes integer I returns conditionfunc
    return I
    return null
endfunction
function CF_I2DamageType takes integer I returns damagetype
    return I
    return null
endfunction
function CF_I2DefeatCondition takes integer I returns defeatcondition
    return I
    return null
endfunction
function CF_I2SDestructable takes integer I returns destructable
    return I
    return null
endfunction
function CF_I2Dialog takes integer I returns dialog
    return I
    return null
endfunction
function CF_I2DialogEvent takes integer I returns dialogevent
    return I
    return null
endfunction
function CF_I2Effect takes integer I returns effect
    return I
    return null
endfunction
function CF_I2EffectType takes integer I returns effecttype
    return I
    return null
endfunction
function CF_I2Event takes integer I returns event
    return I
    return null
endfunction
function CF_I2EffectID takes integer I returns eventid
    return I
    return null
endfunction
function CF_I2FGameState takes integer I returns fgamestate
    return I
    return null
endfunction
function CF_I2FilterFunction takes integer I returns filterfunc
    return I
    return null
endfunction
function CF_I2FogModifier takes integer I returns fogmodifier
    return I
    return null
endfunction
function CF_I2FogState takes integer I returns fogstate
    return I
    return null
endfunction
function CF_I2Force takes integer I returns force
    return I
    return null
endfunction
function CF_I2GameCache takes integer I returns gamecache
    return I
    return null
endfunction
function CF_I2GameDifficulty takes integer I returns gamedifficulty
    return I
    return null
endfunction
function CF_I2GameEvent takes integer I returns gameevent
    return I
    return null
endfunction
function CF_I2GameSpeed takes integer I returns gamespeed
    return I
    return null
endfunction
function CF_I2GameState takes integer I returns gamestate
    return I
    return null
endfunction
function CF_I2GameType takes integer I returns gametype
    return I
    return null
endfunction
function CF_I2Group takes integer I returns group
    return I
    return null
endfunction
function CF_I2IGameState takes integer I returns igamestate
    return I
    return null
endfunction
function CF_I2Image takes integer I returns image
    return I
    return null
endfunction
function CF_I2Item takes integer I returns item
    return I
    return null
endfunction
function CF_I2ItemPool takes integer I returns itempool
    return I
    return null
endfunction
function CF_I2ItemType takes integer I returns itemtype
    return I
    return null
endfunction
function CF_I2Leaderboard takes integer I returns leaderboard
    return I
    return null
endfunction
function CF_I2Lightning takes integer I returns lightning
    return I
    return null
endfunction
function CF_I2Limitop takes integer I returns limitop
    return I
    return null
endfunction
function CF_I2Location takes integer I returns location
    return I
    return null
endfunction
function CF_I2MapControl takes integer I returns mapcontrol
    return I
    return null
endfunction
function CF_I2MapDensity takes integer I returns mapdensity
    return I
    return null
endfunction
function CF_I2MapFlag takes integer I returns mapflag
    return I
    return null
endfunction
function CF_I2MapSetting takes integer I returns mapsetting
    return I
    return null
endfunction
function CF_I2MapVisability takes integer I returns mapvisibility
    return I
    return null
endfunction
function CF_I2Multiboard takes integer I returns multiboard
    return I
    return null
endfunction
function CF_I2MultiboardItem takes integer I returns multiboarditem
    return I
    return null
endfunction
function CF_I2PathingType takes integer I returns pathingtype
    return I
    return null
endfunction
function CF_I2Placement takes integer I returns placement
    return I
    return null
endfunction
function CF_I2Player takes integer I returns player
    return I
    return null
endfunction
function CF_I2PlayerColor takes integer I returns playercolor
    return I
    return null
endfunction
function CF_I2PlayerEvent takes integer I returns playerevent
    return I
    return null
endfunction
function CF_I2PlayerGameResult takes integer I returns playergameresult
    return I
    return null
endfunction
function CF_I2PlayerScore takes integer I returns playerscore
    return I
    return null
endfunction
function CF_I2PlayerSlotState takes integer I returns playerslotstate
    return I
    return null
endfunction
function CF_I2PlayerState takes integer I returns playerstate
    return I
    return null
endfunction
function CF_I2PlayerUnitEvent takes integer I returns playerunitevent
    return I
    return null
endfunction
function CF_I2Quest takes integer I returns quest
    return I
    return null
endfunction
function CF_I2QuestItem takes integer I returns questitem
    return I
    return null
endfunction
function CF_I2Race takes integer I returns race
    return I
    return null
endfunction
function CF_I2RacePreference takes integer I returns racepreference
    return I
    return null
endfunction
function CF_I2RarityControl takes integer I returns raritycontrol
    return I
    return null
endfunction
function CF_I2Rect takes integer I returns rect
    return I
    return null
endfunction
function CF_I2Region takes integer I returns region
    return I
    return null
endfunction
function CF_I2Sound takes integer I returns sound
    return I
    return null
endfunction
function CF_I2SoundType takes integer I returns soundtype
    return I
    return null
endfunction
function CF_I2StartLocPrio takes integer I returns startlocprio
    return I
    return null
endfunction
function CF_I2TerrainDeformation takes integer I returns terraindeformation
    return I
    return null
endfunction
function CF_I2TexMapFlags takes integer I returns texmapflags
    return I
    return null
endfunction
function CF_I2TextTag takes integer I returns texttag
    return I
    return null
endfunction
function CF_I2Timer takes integer I returns timer
    return I
    return null
endfunction
function CF_I2TimerDialog takes integer I returns timerdialog
    return I
    return null
endfunction
function CF_I2Trackable takes integer I returns trackable
    return I
    return null
endfunction
function CF_I2Trigger takes integer I returns trigger
    return I
    return null
endfunction
function CF_I2TriggerAction takes integer I returns triggeraction
    return I
    return null
endfunction
function CF_I2TriggerCondition takes integer I returns triggercondition
    return I
    return null
endfunction
function CF_I2Ubersplat takes integer I returns ubersplat
    return I
    return null
endfunction
function CF_I2Unit takes integer I returns unit
    return I
    return null
endfunction
function CF_I2UnitEvent takes integer I returns unitevent
    return I
    return null
endfunction
function CF_I2UnitPool takes integer I returns unitpool
    return I
    return null
endfunction
function CF_I2UnitState takes integer I returns unitstate
    return I
    return null
endfunction
function CF_I2UnitType takes integer I returns unittype
    return I
    return null
endfunction
function CF_I2Version takes integer I returns version
    return I
    return null
endfunction
function CF_I2VolumeGroup takes integer I returns volumegroup
    return I
    return null
endfunction
function CF_I2WeaponType takes integer I returns weapontype
    return I
    return null
endfunction
function CF_I2WeatherEffect takes integer I returns weathereffect
    return I
    return null
endfunction
function CF_I2Widget takes integer I returns widget
    return I
    return null
endfunction
function CF_I2WidgetEvent takes integer I returns widgetevent
    return I
    return null
endfunction

// Attach and Store Variables
function CF_StoreInteger takes integer whichInteger, string label returns nothing
    if(whichInteger != 0) then
        call StoreInteger(CF_GC(), "Integer", label, whichInteger)
    else
        call FlushStoredMission(CF_GC(), label)
    endif
endfunction
function CF_StoreReal takes real whichReal, string label returns nothing
    if(whichReal != 0.) then
        call StoreReal(CF_GC(), "Real", label, whichReal)
    else
        call FlushStoredMission(CF_GC(), label)
    endif
endfunction
function CF_StoreString takes string whichString, string label returns nothing
    if(whichString != "") then
        call StoreString(CF_GC(), "String", label, whichString)
    else
        call FlushStoredMission(CF_GC(), label)
    endif
endfunction
function CF_StoreBoolean takes boolean whichBoolean, string label returns nothing
    local integer i = CF_B2I(whichBoolean)
    if(i == 1) then
        call StoreInteger(CF_GC(), "Boolean", label, i)
    else
        call FlushStoredMission(CF_GC(), label)
    endif
endfunction
function CF_StoreHandle takes handle whichHandle, string label, string HandleType returns nothing
    local integer i = CF_H2I(whichHandle)
    if(i != 0) then
        call StoreInteger(CF_GC(), HandleType, label, i)
    else
        call FlushStoredMission(CF_GC(), label)
    endif
endfunction

function CF_LoadInteger takes string label returns integer
    return GetStoredInteger(CF_GC(), "Integer", label)
endfunction
function CF_LoadReal takes string label returns real
    return GetStoredReal(CF_GC(), "Real", label)
endfunction
function CF_LoadString takes string label returns string
    return GetStoredString(CF_GC(), "String", label)
endfunction
function CF_LoadBoolean takes string label returns boolean
    return CF_I2B(GetStoredInteger(CF_GC(), "Boolean", label))
endfunction

function CF_LoadUnit takes string label returns unit
    return CF_I2Unit(GetStoredInteger(CF_GC(), "Unit", label))
endfunction
function CF_LoadEffect takes string label returns effect
    return CF_I2Effect(GetStoredInteger(CF_GC(), "Effect", label))
endfunction
function CF_LoadPlayer takes string label returns player
    return CF_I2Player(GetStoredInteger(CF_GC(), "Player", label))
endfunction
function CF_LoadTrigger takes string label returns trigger
    return CF_I2Trigger(GetStoredInteger(CF_GC(), "Trigger", label))
endfunction
function CF_LoadTimer takes string label returns timer
    return CF_I2Timer(GetStoredInteger(CF_GC(), "Timer", label))
endfunction

function CF_AttachInteger takes integer whichInteger, string label, handle KeyHandle returns nothing
    local integer i = CF_H2I(KeyHandle)
    if(i != 0) then
        call StoreInteger(CF_GC(), I2S(i), label, whichInteger)
    else
        call FlushStoredMission(CF_GC(), label)
    endif
endfunction
function CF_AttachReal takes real whichReal, string label, handle KeyHandle returns nothing
    local integer i = CF_H2I(KeyHandle)
    if(i != 0) then
        call StoreReal(CF_GC(), I2S(i), label, whichReal)
    else
        call FlushStoredMission(CF_GC(), label)
    endif
endfunction
function CF_AttachString takes string whichString, string label, handle KeyHandle returns nothing
    local integer i = CF_H2I(KeyHandle)
    if(i != 0) then
        call StoreString(CF_GC(), I2S(i), label, whichString)
    else
        call FlushStoredMission(CF_GC(), label)
    endif
endfunction
function CF_AttachBoolean takes boolean whichBoolean, string label, handle KeyHandle returns nothing
    local integer b = CF_B2I(whichBoolean)
    local integer i = CF_H2I(KeyHandle)
    if(i != 0) then
        call StoreInteger(CF_GC(), I2S(i), label, b)
    else
        call FlushStoredMission(CF_GC(), label)
    endif
endfunction
function CF_AttachHandle takes handle whichHandle, string label, handle KeyHandle returns nothing
    local integer h = CF_H2I(whichHandle)
    local integer i = CF_H2I(KeyHandle)
    if(i+h != 0) then
        call StoreInteger(CF_GC(), I2S(i), label, h)
    else
        call FlushStoredMission(CF_GC(), label)
    endif
endfunction

function CF_GetAttachedInteger takes handle KeyHandle, string label returns integer
    return GetStoredInteger(CF_GC(), CF_H2S(KeyHandle), label)
endfunction
function CF_GetAttachedReal takes handle KeyHandle, string label returns real
    return GetStoredReal(CF_GC(), CF_H2S(KeyHandle), label)
endfunction
function CF_GetAttachedString takes handle KeyHandle, string label returns string
    return GetStoredString(CF_GC(), CF_H2S(KeyHandle), label)
endfunction
function CF_GetAttachedBoolean takes handle KeyHandle, string label returns boolean
    return CF_I2B(GetStoredInteger(CF_GC(), CF_H2S(KeyHandle), label))
endfunction

function CF_GetAttachedUnit takes handle KeyHandle, string label returns unit
    return CF_I2Unit(GetStoredInteger(CF_GC(), CF_H2S(KeyHandle), label))
endfunction
function CF_GetAttachedEffect takes handle KeyHandle, string label returns effect
    return CF_I2Effect(GetStoredInteger(CF_GC(), CF_H2S(KeyHandle), label))
endfunction
function CF_GetAttachedPlayer takes handle KeyHandle, string label returns player
    return CF_I2Player(GetStoredInteger(CF_GC(), CF_H2S(KeyHandle), label))
endfunction
function CF_GetAttachedTrigger takes handle KeyHandle, string label returns trigger
    return CF_I2Trigger(GetStoredInteger(CF_GC(), CF_H2S(KeyHandle), label))
endfunction
function CF_GetAttachedTimer takes handle KeyHandle, string label returns timer
    return CF_I2Timer(GetStoredInteger(CF_GC(), CF_H2S(KeyHandle), label))
endfunction


// Simple Functions
// Check Co-ordinates
function CF_IsXSafe takes real X returns boolean
    return (X > GetRectMinX(bj_mapInitialPlayableArea)) and (X < GetRectMaxX(bj_mapInitialPlayableArea))
endfunction

function CF_IsYSafe takes real Y returns boolean
    return (Y > GetRectMinY(bj_mapInitialPlayableArea)) and (Y < GetRectMaxY(bj_mapInitialPlayableArea))
endfunction

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

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

// Remove Attachments
function CF_RemoveAttachments takes handle KeyHandle returns nothing
    call FlushStoredMission(CF_GC(), CF_H2S(KeyHandle))
endfunction

function CF_RemoveStoredData takes string label returns nothing
    call FlushStoredMission(CF_GC(), label)
endfunction

// Remove Handles
function CF_DestroyTimer takes timer whichTimer returns nothing
    call PauseTimer(whichTimer)
    call CF_RemoveAttachments(whichTimer)
    call DestroyTimer(whichTimer)
endfunction

function CF_RemoveUnit takes unit whichUnit returns nothing
    call CF_RemoveAttachments(whichUnit)
    call RemoveUnit(whichUnit)
endfunction

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

function CF_DestroyTrigger takes trigger whichTrigger returns nothing
    call CF_RemoveAttachments(whichTrigger)
    call DestroyTrigger(whichTrigger)
endfunction

// Get a Dummy Unit, ready for anything
function CF_GetADummy takes real X, real Y returns unit
    local unit u
    if(CF_IsLocSafe(X, Y)) then
        set u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), CF_Constant_DummyUnitRawcode(), X, Y, 90.)
        call UnitAddAbility(u, CF_Constant_MorphUnitFlyAbilityRawcode())
        call UnitRemoveAbility(u, CF_Constant_MorphUnitFlyAbilityRawcode())
        call UnitAddAbility(u, 'Avul')
        call UnitAddAbility(u, 'Aloc')
        call SetUnitMoveSpeed(u, 522)
    endif
    return u
endfunction

// Change a colour value into a percent and vis-versa
function CF_PercentTo255 takes real percent returns real
    local real r = (percent / 100) * 255
    if(r > 255.) then
        set r = 255.
    elseif(r < 0.) then
        set r = 0.
    endif
    return r
endfunction

function CF_255ToPercent takes real amount returns real
    local real r = (amount / 255) * 100
    if(r > 100.) then
        set r = 100.
    elseif(r < 0.) then
        set r = 0.
    endif
    return r
endfunction

// Hide or Show a Multiboard for a single player.
function CF_HideMultiboardForPlayer takes multiboard whichMultiboard, player whichPlayer returns nothing
    if(GetLocalPlayer() == whichPlayer) then
        call MultiboardDisplay(whichMultiboard, false)
    endif
endfunction

function CF_ShowMultiboardForPlayer takes multiboard whichMultiboard, player whichPlayer returns nothing
    if(GetLocalPlayer() == whichPlayer) then
        call MultiboardDisplay(whichMultiboard, true)
    endif
endfunction

function CF_MultiboardDisplayForPlayer takes multiboard whichMultiboard, player whichPlayer, boolean show returns nothing
    if(GetLocalPlayer() == whichPlayer) then
        call MultiboardDisplay(whichMultiboard, show)
    endif
endfunction

// Make unit unselectable for a player
function CF_MakeUnitUnselectableForPlayer takes player whichPlayer, unit whichUnit returns nothing
    if(GetLocalPlayer() == whichPlayer) then
        call UnitAddAbility(whichUnit, 'Aloc') // Note:
                                               //      This method is irreversable.
                                               //      Once this function is used, it cant be put back to
                                               //      normal.
    endif
endfunction

function CF_MakeUnitUnselectableByEverybodyButPlayer takes player whichPlayer, unit whichUnit returns nothing
    local player CurrentPlayer
    local integer PlayerN
    loop
        set CurrentPlayer = Player(PlayerN)
        exitwhen (PlayerN == 11)
        if(not(CurrentPlayer == whichPlayer)) then
            call CF_MakeUnitUnselectableForPlayer(CurrentPlayer, whichUnit)
        endif
        set PlayerN = PlayerN + 1
    endloop    
endfunction

// Damage function thats uses index's instead of attack and damage type.
function CF_DamageWidget takes unit Credit, widget Target, real Damage, integer AttackIndex, integer DamageIndex returns nothing
    call UnitDamageTarget(Credit, Target, Damage, true, false, ConvertAttackType(AttackIndex), ConvertDamageType(DamageIndex), WEAPON_TYPE_WHOKNOWS)
endfunction

function CF_DamageUnitsInLoc_EnumUnits takes nothing returns boolean
    local boolean a = CF_LoadBoolean("CF_TEMP_DAMAGELOC_ALLIESB")
    local boolean e = CF_LoadBoolean("CF_TEMP_DAMAGELOC_ENEMIESB")
    if((a) and IsPlayerAlly(CF_LoadPlayer("CF_TEMP_DAMAGELOC_CREDIT"), GetOwningPlayer(GetEnumUnit()))) or ((e) and IsPlayerEnemy(CF_LoadPlayer("CF_TEMP_DAMAGELOC_CREDIT"), GetOwningPlayer(GetEnumUnit()))) then
        return true
    endif
    return false
endfunction    

function CF_DamageUnitsInLoc takes unit Credit, real X, real Y, real radius, real Damage, integer AttackIndex, integer DamageIndex, boolean effectEnemies, boolean effectAllies returns nothing
    local group g = CreateGroup()
    local location l = Location(X, Y)
    local unit u
    call CF_StoreHandle(GetOwningPlayer(Credit), "CF_TEMP_DAMAGELOC_CREDIT", "Player")
    call CF_StoreBoolean(effectAllies, "CF_TEMP_DAMAGELOC_ALLIESB")
    call CF_StoreBoolean(effectEnemies, "CF_TEMP_DAMAGELOC_ENEMIESB")
    call GroupEnumUnitsInRangeOfLoc(g, l, radius, Condition(function CF_DamageUnitsInLoc_EnumUnits))
    call CF_RemoveStoredData("CF_TEMP_DAMAGELOC_CREDIT")
    call CF_RemoveStoredData("CF_TEMP_DAMAGELOC_ALLIESB")
    call CF_RemoveStoredData("CF_TEMP_DAMAGELOC_ENEMIESB")
    loop
        set u = FirstOfGroup(g)
        exitwhen(u == null)
        call UnitDamageTarget(Credit, u, Damage, true, false, ConvertAttackType(AttackIndex), ConvertDamageType(DamageIndex), WEAPON_TYPE_WHOKNOWS)
        call GroupRemoveUnit(g, u)
    endloop
    call DestroyGroup(g)
    call RemoveLocation(l)
    set g = null
    set l = null
endfunction

function CF_DamageTargetOverTime_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit Credit = CF_GetAttachedUnit(t, "DamageOverTime_Credit")
    local unit Target = CF_GetAttachedUnit(t, "DamageOverTime_Target")
    local real Damage = CF_GetAttachedReal(t, "DamageOverTime_DpE")
    local integer IntervalsRemaining = CF_GetAttachedInteger(t, "DamageOverTime_IntervalsRemaining")
    local real Wait = CF_GetAttachedReal(t, "DamageOverTime_WaitPerInterval")
    local integer AttackIndex = CF_GetAttachedInteger(t, "DamageOverTime_AttackIndex")
    local integer DamageIndex = CF_GetAttachedInteger(t, "DamageOverTime_DamageIndex")
    call UnitDamageTarget(Credit, Target, Damage, true, false, ConvertAttackType(AttackIndex), ConvertDamageType(DamageIndex), WEAPON_TYPE_WHOKNOWS)
    if(IntervalsRemaining - 1 <= 0) then
        call CF_RemoveAttachments(t)
        call DestroyTimer(t)
        set t = null
        set Credit = null
        set Target = null
    else
        call CF_AttachInteger(IntervalsRemaining - 1, "DamageOverTime_IntervalsRemaining", t)
        call TimerStart(t, Wait, false, function CF_DamageTargetOverTime_Update)
    endif
endfunction
    

function CF_DamageTargetOverTime takes unit Credit, widget Target, real DamagePerInterval, integer IntervalCount, real IntervalTime, boolean FirstIntervalInstant, integer AttackIndex, integer DamageIndex returns nothing
    local timer t = CreateTimer()
    call CF_AttachHandle(Credit, "DamageOverTime_Credit", t)
    call CF_AttachHandle(Target, "DamageOverTime_Target", t)
    call CF_AttachReal(DamagePerInterval, "DamageOverTime_DpE", t)
    call CF_AttachInteger(IntervalCount, "DamageOverTime_IntervalsRemaining", t)
    call CF_AttachReal(IntervalTime, "DamageOverTime_WaitPerInterval", t)
    call CF_AttachInteger(AttackIndex, "DamageOverTime_AttackIndex", t)
    call CF_AttachInteger(DamageIndex, "DamageOverTime_DamageIndex", t)
    if(FirstIntervalInstant) then
        call UnitDamageTarget(Credit, Target, DamagePerInterval, true, false, ConvertAttackType(AttackIndex), ConvertDamageType(DamageIndex), WEAPON_TYPE_WHOKNOWS)
        call CF_AttachInteger(IntervalCount - 1, "DamageOverTime_IntervalsRemaining", t)
    endif
    if(FirstIntervalInstant != true) or (IntervalCount > 1) then
        call TimerStart(t, IntervalTime, false, function CF_DamageTargetOverTime_Update)
    else
        call CF_RemoveAttachments(t)
        call DestroyTimer(t)
        set t = null
    endif
endfunction

function CF_DamageLocOverTime takes unit Credit, real X, real Y, real radius, real DamagePerInterval, integer IntervalCount, real IntervalTime, integer AttackIndex, integer DamageIndex, boolean FirstIntervalInstant, boolean effectAllies, boolean effectEnemies returns nothing
    local group g = CreateGroup()
    local location l = Location(X, Y)
    local unit u
    call CF_StoreHandle(GetOwningPlayer(Credit), "CF_TEMP_DAMAGELOC_CREDIT", "Player")
    call GroupEnumUnitsInRangeOfLoc(g, l, radius, Condition(function CF_DamageUnitsInLoc_EnumUnits))
    call CF_RemoveStoredData("CF_TEMP_DAMAGELOC_CREDIT")
    loop
        set u = FirstOfGroup(g)
        exitwhen(u == null)
        call CF_DamageTargetOverTime(Credit, u, DamagePerInterval, IntervalCount, IntervalTime, FirstIntervalInstant, AttackIndex, DamageIndex)
        call GroupRemoveUnit(g, u)
    endloop
    call DestroyGroup(g)
    call RemoveLocation(l)
    set g = null
    set l = null    
endfunction

// Hide or Show a unit for a player
function CF_ShowUnitForPlayer takes unit whichUnit, player whichPlayer returns nothing
    if(GetLocalPlayer() == whichPlayer) then
        call ShowUnit(whichUnit, true)
    endif
endfunction

function CF_HideUnitForPlayer takes unit whichUnit, player whichPlayer returns nothing
    if(GetLocalPlayer() == whichPlayer) then
        call ShowUnit(whichUnit, false)
    endif
endfunction

function CF_UnitDisplayForPlayer takes unit whichUnit, player whichPlayer, boolean show returns nothing
    if(GetLocalPlayer() == whichPlayer) then
        call ShowUnit(whichUnit, show)
    endif
endfunction

// Run a function after a certain amount of time in a new thread.
function CF_RunFunctionTimed_Run takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local trigger run = CF_GetAttachedTrigger(t, "RunFunctionTimer_Code")
    call TriggerExecute(run)
    call CF_DestroyTimer(t)
    call CF_DestroyTrigger(run)
    set t = null
    set run = null
endfunction

function CF_RunFunctionTimed takes code Function, real Wait returns nothing // This function runs a different
                                                                            // function after a certain amount of
                                                                            // time, it will also open a new
                                                                            // thread.
    local timer t = CreateTimer()
    local trigger run = CreateTrigger()
    call TriggerAddAction(run, Function)
    call TimerStart(t, Wait, false, function CF_RunFunctionTimed_Run)
endfunction

// Find Letter
function CF_FindLetter takes string whichCharacter, integer letterCount, string source returns integer
    local integer i
    local integer newCount = letterCount
    if(StringLength(whichCharacter) == 1) then
        loop                                                        // Example:
            exitwhen i == StringLength(source)                      // source = Weird, letterCount = 0,
            if(SubString(source, i, i) == whichCharacter) then      // whichLetter = r. Result = 4. The first
                if(letterCount == 0) then                           // letter in the string that is a r is 4th
                    return i                                        // character
                endif                                               
                set letterCount = letterCount - 1                   // Example2:
            endif                                                   // source = Grass, letterCount = 1,
            set i = i + 1                                           // whichLetter = s. Result = 5. The second
        endloop                                                     // letter in the string that is a s is the
    endif                                                           // 5th character
    return 0                                             
endfunction

// Say Functions
function CF_SayMessage takes string Message, real Duration returns nothing
    call DisplayTimedTextFromPlayer(GetLocalPlayer(), 0., 0., Duration, Message)
endfunction

function CF_SayMessageLoc takes string Message, real Duration, real X, real Y returns nothing
    call DisplayTimedTextFromPlayer(GetLocalPlayer(), X, Y, Duration, Message)
endfunction    

function CF_WisperMessage takes string Message, player whichPlayer, real Duration returns nothing
    call DisplayTimedTextFromPlayer(whichPlayer, 0., 0., Duration, Message)
endfunction

function CF_WisperMessageLoc takes string Message, player whichPlayer, real Duration, real X, real Y returns nothing
    call DisplayTimedTextFromPlayer(whichPlayer, X, Y, Duration, Message)
endfunction

function CF_AnnounceMessage takes string Message, force whichForce, real Duration returns nothing
    if(IsPlayerInForce(GetLocalPlayer(), whichForce)) then
        call DisplayTimedTextFromPlayer(GetLocalPlayer(), 0., 0., Duration, Message)
    endif
endfunction

function CF_AnnounceMessageLoc takes string Message, force whichForce, real Duration, real X, real Y returns nothing
    if(IsPlayerInForce(GetLocalPlayer(), whichForce)) then
        call DisplayTimedTextFromPlayer(GetLocalPlayer(), X, Y, Duration, Message)
    endif
endfunction

// Move a item from 1 slot to another

function CF_MoveItemSlot takes unit MovingUnit, integer CurrentItemSlot, integer NewItemSlot returns nothing
    call IssueTargetOrderById(MovingUnit, 852001+NewItemSlot, UnitItemInSlot(MovingUnit, CurrentItemSlot)) 
endfunction

// Move unit Functions
function CF_SetUnitX takes unit whichUnit, real X returns nothing
    if(CF_IsXSafe(X)) then
        call SetUnitX(whichUnit, X)
    endif
endfunction

function CF_SetUnitY takes unit whichUnit, real Y returns nothing
    if(CF_IsYSafe(Y)) then
        call SetUnitY(whichUnit, Y)
    endif
endfunction

function CF_SetUnitLoc takes unit whichUnit, real X, real Y returns nothing
    if(CF_IsLocSafe(X, Y)) then
        call SetUnitX(whichUnit, X)
        call SetUnitY(whichUnit, Y)
    endif
endfunction

function CF_SetUnitLocEx takes unit whichUnit, location whichLocation returns nothing
    if(CF_IsLocSafeEx(whichLocation)) then
        call SetUnitX(whichUnit, GetLocationX(whichLocation))
        call SetUnitY(whichUnit, GetLocationY(whichLocation))
    endif
endfunction

// Get Casted Ability level
function CF_GetSpellLevel takes nothing returns integer
    return GetUnitAbilityLevel(GetSpellAbilityUnit(), GetSpellAbilityId())
endfunction        

// Special Functions:-
//                    Consists of things that the standard W/E dosent not let you do.
//

// Effect
function CF_CreateGroundEffect takes real X, real Y, real Z, real facing, real sizeFactor, string modelPath, integer red, integer green, integer blue, integer alpha returns effect
    local effect NewEffect
    local unit CarryingUnit
    if(CF_IsLocSafe(X, Y)) then
        set CarryingUnit = CF_GetADummy(X, Y)
        set NewEffect = AddSpecialEffectTarget(modelPath, CarryingUnit, "origin")
        call SetUnitFlyHeight(CarryingUnit, Z, 0.)
        call SetUnitFacing(CarryingUnit, facing)
        call SetUnitScalePercent(CarryingUnit, sizeFactor, sizeFactor, sizeFactor) // This uses scaling factor.
                                                                                   // 1. would be the same size.
                                                                                   // 1.1 would be 10% bigger than
                                                                                   // usual.
                                                                                   // 2. would be 100% bigger than
                                                                                   // usual.
        call SetUnitVertexColor(CarryingUnit, red, green, blue, alpha)
        call CF_AttachHandle(CarryingUnit, "Effect_CarryingUnit", NewEffect)
        call CF_AttachReal(X, "Effect_XCoord", NewEffect)
        call CF_AttachReal(Y, "Effect_YCoord", NewEffect)
        call CF_AttachReal(Z, "Effect_ZCoord", NewEffect)
        call CF_AttachReal(facing, "Effect_FacingDegrees", NewEffect)
        call CF_AttachReal(sizeFactor, "Effect_Size", NewEffect)
        call CF_AttachInteger(red, "Effect_RedColour", NewEffect)
        call CF_AttachInteger(green, "Effect_GreenColour", NewEffect)
        call CF_AttachInteger(blue, "Effect_BlueColour", NewEffect)
        call CF_AttachInteger(alpha, "Effect_AlphaColour", NewEffect)
        call CF_AttachString(modelPath, "Effect_ModelPath", NewEffect)
        call CF_StoreHandle(NewEffect, "CF_MEMORY_LASTCREATED_EFFECT", "Effect")
        return NewEffect
    endif
    set NewEffect = null
    set CarryingUnit = null
    return null
endfunction

function CF_GetLastCreatedEffect takes nothing returns effect
    return CF_LoadEffect("CF_MEMORY_LASTCREATED_EFFECT")
endfunction

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

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

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

function CF_GetEffectZ takes effect whichEffect returns real
    return CF_GetAttachedReal(whichEffect, "Effect_ZCoord")
endfunction

function CF_GetEffectFacing takes effect whichEffect returns real
    return CF_GetAttachedReal(whichEffect, "Effect_FacingDegrees")
endfunction

function CF_GetEffectSize takes effect whichEffect returns real
    return CF_GetAttachedReal(whichEffect, "Effect_Size")
endfunction

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

function CF_GetEffectRedColour takes effect whichEffect returns integer
    return CF_GetAttachedInteger(whichEffect, "Effect_RedColour")
endfunction

function CF_GetEffectGreenColour takes effect whichEffect returns integer
    return CF_GetAttachedInteger(whichEffect, "Effect_GreenColour")
endfunction

function CF_GetEffectBlueColour takes effect whichEffect returns integer
    return CF_GetAttachedInteger(whichEffect, "Effect_BlueColour")
endfunction

function CF_GetEffectAlphaColour takes effect whichEffect returns integer
    return CF_GetAttachedInteger(whichEffect, "Effect_AlphaColour")
endfunction

function CF_IsEffectLocked takes effect whichEffect returns boolean
    if(CF_GetAttachedBoolean(whichEffect, "Effect_Locked")) then
        return true
    endif
    return false
endfunction

function CF_IsEffectInRect takes effect whichEffect, real minX, real minY, real maxX, real maxY returns boolean
    local real X = CF_GetEffectX(whichEffect)
    local real Y = CF_GetEffectY(whichEffect)
    if(X > minX) and (X < maxX) and (Y > minY) and (Y < maxY) then
        return true
    endif
    return false
endfunction

function CF_IsEffectInRectEx takes effect whichEffect, rect whichRect returns boolean
    local real X
    local real Y
    if(X > GetRectMinX(whichRect)) and (X < GetRectMaxX(whichRect)) and (Y > GetRectMinY(whichRect)) and (Y < GetRectMaxY(whichRect)) then
        return true
    endif
    return false
endfunction

function CF_IsEffectInRange takes effect whichEffect, real X, real Y, real radius returns boolean
    return IsUnitInRangeXY(CF_GetEffectCarryingUnit(whichEffect), X, Y, radius)
endfunction

function CF_IsEffectInRangeEx takes effect whichEffect, location whichLocation, real radius returns boolean
    return IsUnitInRangeXY(CF_GetEffectCarryingUnit(whichEffect), GetLocationX(whichLocation), GetLocationY(whichLocation), radius)
endfunction 

function CF_SetEffectX takes effect whichEffect, real X returns nothing
    if(CF_IsXSafe(X) and (CF_IsEffectLocked(whichEffect) == false)) then
        call SetUnitX(CF_GetEffectCarryingUnit(whichEffect), X)
        call CF_AttachReal(X, "Effect_XCoord", whichEffect)
    endif
endfunction

function CF_SetEffectY takes effect whichEffect, real Y returns nothing
    if(CF_IsYSafe(Y) and (CF_IsEffectLocked(whichEffect) == false)) then
        call SetUnitY(CF_GetEffectCarryingUnit(whichEffect), Y)
        call CF_AttachReal(Y, "Effect_YCoord", whichEffect)
    endif
endfunction

function CF_SetEffectLoc takes effect whichEffect, real X, real Y returns nothing
    local unit CarryingUnit = CF_GetEffectCarryingUnit(whichEffect)
    if(CF_IsLocSafe(X, Y) and (CF_IsEffectLocked(whichEffect) == false)) then
        call SetUnitX(CarryingUnit, X)
        call SetUnitY(CarryingUnit, Y)
        call CF_AttachReal(X, "Effect_XCoord", whichEffect)
        call CF_AttachReal(Y, "Effect_YCoord", whichEffect)
    endif
    set CarryingUnit = null
endfunction

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

function CF_SetEffectZ takes effect whichEffect, real newZ returns nothing
    if(CF_IsEffectLocked(whichEffect) == false) then
        call SetUnitFlyHeight(CF_GetEffectCarryingUnit(whichEffect), newZ, 0.)
        call CF_AttachReal(newZ, "Effect_ZCoord", whichEffect)
    endif
endfunction

function CF_SetEffectFacing takes effect whichEffect, real facing returns nothing
    if(CF_IsEffectLocked(whichEffect) == false) then
        call SetUnitFacing(CF_GetEffectCarryingUnit(whichEffect), facing)
        call CF_AttachReal(facing, "Effect_FacingDegrees", whichEffect)
    endif
endfunction

function CF_SetEffectSize takes effect whichEffect, real sizeFactor returns nothing
    local real oldFactor = CF_GetEffectSize(whichEffect)
    if(CF_IsEffectLocked(whichEffect) == false) then
        call SetUnitScalePercent(CF_GetEffectCarryingUnit(whichEffect), sizeFactor, sizeFactor, sizeFactor)
        call CF_AttachReal(oldFactor + sizeFactor - 1., "Effect_Size", whichEffect)
    endif
endfunction

function CF_EffectAddExpirationTime_Destroy takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local effect e = CF_GetAttachedEffect(t, "Timer_Expiration_Effect")
    call CF_DestroyTimer(t)
    call CF_DestroyEffect(e)
    set t = null
    set e = null
endfunction

function CF_EffectAddExpirationTime takes effect whichEffect, real time returns nothing
    local timer t = CreateTimer()
    if(CF_IsEffectLocked(whichEffect) == false) then
        call CF_AttachHandle(whichEffect, "Timer_Expiration_Effect", t)
        call TimerStart(t, time, false, function CF_EffectAddExpirationTime_Destroy)
    endif
endfunction

function CF_SetEffectColour takes effect whichEffect, integer red, integer green, integer blue, integer alpha returns nothing
    if(CF_IsEffectLocked(whichEffect) == false) then
        call SetUnitVertexColor(CF_GetEffectCarryingUnit(whichEffect), red, green, blue, alpha)
    endif
endfunction

function CF_SetEffectRedColour takes effect whichEffect, integer red returns nothing
    local integer green = CF_GetEffectGreenColour(whichEffect)
    local integer blue = CF_GetEffectBlueColour(whichEffect)
    local integer alpha = CF_GetEffectAlphaColour(whichEffect)
    if(CF_IsEffectLocked(whichEffect) == false) then
        call SetUnitVertexColor(CF_GetEffectCarryingUnit(whichEffect), red, green, blue, alpha)
    endif
endfunction

function CF_SetEffectGreenColour takes effect whichEffect, integer green returns nothing
    local integer red = CF_GetEffectRedColour(whichEffect)
    local integer blue = CF_GetEffectBlueColour(whichEffect)
    local integer alpha = CF_GetEffectAlphaColour(whichEffect)
    if(CF_IsEffectLocked(whichEffect) == false) then
        call SetUnitVertexColor(CF_GetEffectCarryingUnit(whichEffect), red, green, blue, alpha)
    endif
endfunction

function CF_SetEffectBlueColour takes effect whichEffect, integer blue returns nothing
    local integer red = CF_GetEffectRedColour(whichEffect)
    local integer green = CF_GetEffectGreenColour(whichEffect)
    local integer alpha = CF_GetEffectAlphaColour(whichEffect)
    if(CF_IsEffectLocked(whichEffect) == false) then
        call SetUnitVertexColor(CF_GetEffectCarryingUnit(whichEffect), red, green, blue, alpha)
    endif
endfunction

function CF_SetEffectAlphaColour takes effect whichEffect, integer alpha returns nothing
    local integer red = CF_GetEffectRedColour(whichEffect)
    local integer green = CF_GetEffectGreenColour(whichEffect)
    local integer blue = CF_GetEffectBlueColour(whichEffect)
    if(CF_IsEffectLocked(whichEffect) == false) then
        call SetUnitVertexColor(CF_GetEffectCarryingUnit(whichEffect), red, green, blue, alpha)
    endif
endfunction

function CF_CopyEffect takes effect whichEffect returns effect
    return CF_CreateGroundEffect(CF_GetEffectX(whichEffect), CF_GetEffectY(whichEffect), CF_GetEffectZ(whichEffect), CF_GetEffectFacing(whichEffect), CF_GetEffectSize(whichEffect), CF_GetEffectModelPath(whichEffect), CF_GetEffectRedColour(whichEffect), CF_GetEffectGreenColour(whichEffect), CF_GetEffectBlueColour(whichEffect), CF_GetEffectAlphaColour(whichEffect))
endfunction

function CF_CopyEffectLoc takes effect whichEffect, real X, real Y returns effect
    local effect e = CF_CopyEffect(whichEffect)
    local integer Ie = CF_H2I(e)
    call CF_SetEffectLoc(e, X, Y)
    set e = null
    return Ie
    return null
endfunction

function CF_CopyEffectLocEx takes effect whichEffect, location whichLocation returns effect
    return CF_CopyEffectLoc(whichEffect, GetLocationX(whichLocation), GetLocationY(whichLocation))
endfunction

function CF_LockEffect takes effect whichEffect returns nothing
    call CF_AttachBoolean(true, "Effect_Locked", whichEffect) // If a effect is locked, nothing can be changed,
                                                              // Only things like copy and getting values is
                                                              // possible.
endfunction

function CF_UnlockEffect takes effect whichEffect returns nothing
    call CF_AttachBoolean(false, "Effect_Locked", whichEffect) // Allows the effect to be changed again
endfunction

function CF_LockEffectEdit takes effect whichEffect, boolean lock returns nothing
    call CF_AttachBoolean(lock, "Effect_Locked", whichEffect)
endfunction

function CF_ShowEffectForPlayer takes effect whichEffect, player whichPlayer returns nothing
    if(GetLocalPlayer() == whichPlayer) then
        call ShowUnit(CF_GetEffectCarryingUnit(whichEffect), true)
    endif
endfunction

function CF_HideEffectForPlayer takes effect whichEffect, player whichPlayer returns nothing
    if(GetLocalPlayer() == whichPlayer) then
        call ShowUnit(CF_GetEffectCarryingUnit(whichEffect), false)
    endif
endfunction

function CF_DisplayEffectForPlayer takes effect whichEffect, player whichPlayer, boolean show returns nothing
    if(GetLocalPlayer() == whichPlayer) then
        call ShowUnit(CF_GetEffectCarryingUnit(whichEffect), show)
    endif
endfunction
    
// Lightning
function CF_CreateLightningGroundEffect takes real X1, real Y1, real Z1, real X2, real Y2, real Z2, string codeName, integer red, integer green, integer blue, integer alpha returns lightning
    local lightning NewLightning
    if(CF_IsLocSafe(X1, Y1) and CF_IsLocSafe(X2, Y2)) then
       set NewLightning = AddLightningEx(codeName, true, X1, Y1, Z2, X2, Y2, Z2)
       call SetLightningColor(NewLightning, red, green, blue, alpha)
       call CF_AttachReal(X1, "Lightning_CoordX1", NewLightning)
       call CF_AttachReal(Y1, "Lightning_CoordY1", NewLightning)
       call CF_AttachReal(Z1, "Lightning_CoordZ1", NewLightning)
       call CF_AttachReal(X2, "Lightning_CoordX2", NewLightning)
       call CF_AttachReal(Y2, "Lightning_CoordY2", NewLightning)
       call CF_AttachReal(Z2, "Lightning_CoordZ2", NewLightning)
       call CF_AttachString(codeName, "Lightning_CodeName", NewLightning)
       call CF_AttachInteger(red, "Lightning_RedColour", NewLightning)
       call CF_AttachInteger(green, "Lightning_GreenColour", NewLightning)
       call CF_AttachInteger(blue, "Lightning_BlueColour", NewLightning)
       call CF_AttachInteger(alpha, "Lightning_AlphaColour", NewLightning)
       return NewLightning
    endif
    set NewLightning = null
    return null
endfunction

function CF_GetLightningX1 takes lightning whichLightning returns real
    return CF_GetAttachedReal(whichLightning, "Lightning_CoordX1")
endfunction

function CF_GetLightningY1 takes lightning whichLightning returns real
    return CF_GetAttachedReal(whichLightning, "Lightning_CoordY1")
endfunction

function CF_GetLightningZ1 takes lightning whichLightning returns real
    return CF_GetAttachedReal(whichLightning, "Lightning_CoordZ1")
endfunction

function CF_GetLightningX2 takes lightning whichLightning returns real
    return CF_GetAttachedReal(whichLightning, "Lightning_CoordX2")
endfunction

function CF_GetLightningY2 takes lightning whichLightning returns real
    return CF_GetAttachedReal(whichLightning, "Lightning_CoordY2")
endfunction

function CF_GetLightningZ2 takes lightning whichLightning returns real
    return CF_GetAttachedReal(whichLightning, "Lightning_CoordZ2")
endfunction

function CF_GetLightningLoc1 takes lightning whichLightning returns location
    return Location(CF_GetLightningX1(whichLightning), CF_GetLightningY1(whichLightning))
endfunction

function CF_GetLightningLoc2 takes lightning whichLightning returns location
    return Location(CF_GetLightningX2(whichLightning), CF_GetLightningY2(whichLightning))
endfunction

function CF_GetLightningCenter takes lightning whichLightning returns location
    local location Loc1 = CF_GetLightningLoc1(whichLightning)
    local real X1 = CF_GetLightningX1(whichLightning)
    local real Y1 = CF_GetLightningY1(whichLightning)
    local real X2 = CF_GetLightningX2(whichLightning)
    local real Y2 = CF_GetLightningY2(whichLightning)
    local real angle = bj_RADTODEG * Atan2(Y2 - Y1, X2 - X1)
    local real distance = SquareRoot(X2 - X1 * X2 - X1 + Y2 - Y1 * Y2 - Y1)
    local real HDistance = distance / 2
    local real DestX = GetLocationX(Loc1) + HDistance * Cos(angle * bj_DEGTORAD)
    local real DestY = GetLocationY(Loc1) + HDistance * Sin(angle * bj_DEGTORAD)
    call RemoveLocation(Loc1)
    set Loc1 = null
    return Location(DestX, DestY)
endfunction    

function CF_GetLightningColourRed takes lightning whichLightning returns real
    return CF_GetAttachedReal(whichLightning, "Lightning_RedColour")
endfunction

function CF_GetLightningColourGreen takes lightning whichLightning returns real
    return CF_GetAttachedReal(whichLightning, "Lightning_GreenColour")
endfunction

function CF_GetLightningColourBlue takes lightning whichLightning returns real
    return CF_GetAttachedReal(whichLightning, "Lightning_BlueColour")
endfunction

function CF_GetLightningColourAlpha takes lightning whichLightning returns real
    return CF_GetAttachedReal(whichLightning, "Lightning_AlphaColour")
endfunction

function CF_SetLightningToGround takes lightning whichLightning returns nothing
    local real X1 = CF_GetLightningX1(whichLightning)
    local real Y1 = CF_GetLightningY1(whichLightning)
    local real X2 = CF_GetLightningX2(whichLightning)
    local real Y2 = CF_GetLightningY2(whichLightning)
    call MoveLightningEx(whichLightning, true, X1, Y2, GetTerrainCliffLevel(X1, Y1), X2, Y2, GetTerrainCliffLevel(X2, Y2))
endfunction

And the test map is just in normal attach location.
Please, any help would be greatly appreicated.
Attached Files
File type: w3xSpell Problem.w3x (72.6 KB)
07-17-2006, 07:41 PM#2
Rising_Dusk
I want to ask about the '????' crap I see all over the place.
That won't return as anything usable, and it might cause severe errors.

Also, you have so many CF functions so poorly organized, and no rhyme/organization to the spell's code, I can barely even follow what you hope for it to do.
I'm sorry, I really like helping others work out their codes, but I simply cannot for the life of me follow this one OR your common functions list. >_<
07-17-2006, 08:55 PM#3
The)TideHunter(
The CS functions is poorly organised, its no where near done, it needs alot of work.
The ???? is just where the person using it needs to change.
Collapse JASS:
constant function BaB_Spell_SlashStrike_Rawcode takes nothing returns integer
    return '????'
endfunction
constant function BaB_Spell_SlashStrike_ChannelOrderString takes nothing returns string
    return "?????"
endfunction

To:

Collapse JASS:
constant function BaB_Spell_SlashStrike_Rawcode takes nothing returns integer
    return 'A000'
endfunction
constant function BaB_Spell_SlashStrike_ChannelOrderString takes nothing returns string
    return "SomeString"
endfunction

In my case, (the test map):

Collapse JASS:
constant function BaB_Spell_SlashStrike_Rawcode takes nothing returns integer
    return 'A002'
endfunction
constant function BaB_Spell_SlashStrike_ChannelOrderString takes nothing returns string
    return "tornado"
endfunction
07-17-2006, 09:16 PM#4
Rising_Dusk
Quote:
I used debug messages, and they work, but it just shows that the spell dosent.

Did you try placing BJDebugMsg's at different points in the code saying different things?
It'd be helpful to know WHERE in the code it's returning as you say.
07-17-2006, 09:37 PM#5
The)TideHunter(
Spell code (which was in the map -.-)
There was debugs all over the place.
Collapse JASS:
// Spell
// Slash Strike
//============================================================
// Configuration
constant function BaB_Spell_SlashStrike_Rawcode takes nothing returns integer
    return 'A002'
endfunction
constant function BaB_Spell_SlashStrike_ChannelOrderString takes nothing returns string
    return "tornado"
endfunction

constant function BaB_Spell_SlashStrike_Damage takes integer level returns real
    return (level * 100.) + 100.
endfunction
constant function BaB_Spell_SlashStrike_DamageRadius takes nothing returns real
    return 125.
endfunction
constant function BaB_Spell_SlashStrike_AttackTypeIndex takes nothing returns integer
    return 4
endfunction
constant function BaB_Spell_SlashStrike_DamageTypeIndex takes nothing returns integer
    return 4
endfunction
constant function BaB_Spell_SlashStrike_DamageInterval takes nothing returns real
    return 1.
endfunction

constant function BaB_Spell_SlashStrike_MoveSpeed takes nothing returns real
    return 700.
endfunction
constant function BaB_Spell_SlashStrike_AnimationSpeed takes nothing returns real
    return 300.
endfunction

constant function BaB_Spell_SlashStrike_NightChance takes integer level returns real
    return level * 5.
endfunction
constant function BaB_Spell_SlashStrike_NightChanceDamage takes nothing returns real
    return 100.
endfunction

//============================================================
// Slash Strike
function BaB_Spell_SlashStrike_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit Caster = CF_GetAttachedUnit(t, "Spell_SlashStrike_Caster")
    local integer AbilLevel = CF_GetAttachedInteger(t, "Spell_SlashStrike_AbilLevel")
    local real Progress = CF_GetAttachedReal(t, "Spell_SlashStrike_Progress")
    local real TargetX = CF_GetAttachedReal(t, "Spell_SlashStrike_TargetX")
    local real TargetY = CF_GetAttachedReal(t, "Spell_SlashStrike_TargetY")
    local real CasterX = GetUnitX(Caster)
    local real CasterY = GetUnitY(Caster)
    local real Angle = bj_RADTODEG * Atan2(TargetY - CasterY, TargetX - CasterX)
    local real StartingX = CF_GetAttachedReal(t, "Spell_SlashStrike_StartingX")
    local real StartingY = CF_GetAttachedReal(t, "Spell_SlashStrike_StartingY")
    local real MinTimerUpdate = CF_Constant_MinTimerUpdate()
    local real DistanceX = TargetX - CasterX
    local real DistanceY = TargetY - CasterY 
    local real Distance = SquareRoot((DistanceX * DistanceX) - (DistanceY * DistanceX))
    local real MoveSpeed = BaB_Spell_SlashStrike_MoveSpeed() 
    local real NewX = CasterX + (MoveSpeed / MinTimerUpdate) * Cos(Angle * bj_DEGTORAD)
    local real NewY = CasterY + (MoveSpeed / MinTimerUpdate) * Sin(Angle * bj_DEGTORAD)
    local group AoE
    local real Damage = BaB_Spell_SlashStrike_Damage(AbilLevel)
    local unit CurrentUnit
    local real Random = GetRandomReal(0., 100.)
    local integer AttackIndex = BaB_Spell_SlashStrike_AttackTypeIndex()
    local integer DamageIndex = BaB_Spell_SlashStrike_DamageTypeIndex()
    local real DamageInterval = BaB_Spell_SlashStrike_DamageInterval()
    call BJDebugMsg("Starting Update")
    if(Distance < CF_Constant_CollisionDetectionRange() or (GetUnitCurrentOrder(GetTriggerUnit()) != String2OrderIdBJ("monsoon"))) then
        call CF_DestroyTimer(t)
        set t = null
        call SetUnitTimeScale(Caster, 1.)
        call BJDebugMsg("Exiting")
    else
        call BJDebugMsg("Continuing")
        if(Progress >= DamageInterval) then
            set AoE = CreateGroup()
            call GroupEnumUnitsInRange(AoE, CasterX, CasterY, BaB_Spell_SlashStrike_DamageRadius(), null)
            if(BaB_Spell_SlashStrike_NightChance(AbilLevel) > Random) then
                set Damage = Damage + 100
                call BJDebugMsg("Crit")
            endif
            call BJDebugMsg("Damaging")
            loop
                set CurrentUnit = FirstOfGroup(AoE)
                exitwhen CurrentUnit == null
                if(IsPlayerEnemy(GetOwningPlayer(Caster), GetOwningPlayer(CurrentUnit))) then
                    call CF_DamageWidget(Caster, CurrentUnit, Damage, AttackIndex, DamageIndex)
                endif
                call GroupRemoveUnit(AoE, CurrentUnit)
            endloop
            call DestroyGroup(AoE)
        endif
        call CF_SetUnitLoc(Caster, NewX, NewY)
        call TimerStart(t, MinTimerUpdate, false, function BaB_Spell_SlashStrike_Update)
        call BJDebugMsg("Ending Update")
    endif
endfunction

function BaB_Spell_SlashStrike takes nothing returns nothing
    local timer t = CreateTimer()
    local unit Caster = GetSpellAbilityUnit()
    local integer AbilLevel = CF_GetSpellLevel()
    local real CasterX = GetUnitX(Caster)
    local real CasterY = GetUnitY(Caster)
    local location TargetLoc = GetSpellTargetLoc()
    local real TargetX = GetLocationX(TargetLoc)
    local real TargetY = GetLocationY(TargetLoc)
    local real Damage = BaB_Spell_SlashStrike_Damage(AbilLevel)
    local group AoE = CreateGroup()
    local integer AttackIndex = BaB_Spell_SlashStrike_AttackTypeIndex()
    local integer DamageIndex = BaB_Spell_SlashStrike_DamageTypeIndex()
    local unit CurrentUnit
    local real Random = GetRandomReal(0., 100.)
    local real MinTimerUpdate = CF_Constant_MinTimerUpdate()
    call BJDebugMsg("Beginning Spell")
    call CF_AttachHandle(Caster, "Spell_SlashStrike_Caster", t)
    call CF_AttachInteger(AbilLevel, "Spell_SlashStrike_AbilLevel", t)
    call CF_AttachReal(TargetX, "Spell_SlashStrike_TargetX", t)
    call CF_AttachReal(TargetY, "Spell_SlashStrike_TargetY", t)
    call CF_AttachReal(MinTimerUpdate, "Spell_SlashStrike_Progress", t)
    call CF_AttachReal(CasterX, "Spell_SlashStrike_StartingX", t)
    call CF_AttachReal(CasterY, "Spell_SlashStrike_StartingY", t)
    call GroupEnumUnitsInRange(AoE, CasterX, CasterY, BaB_Spell_SlashStrike_DamageRadius(), null)
    loop
        set CurrentUnit = FirstOfGroup(AoE)
        exitwhen CurrentUnit == null
        if(IsPlayerEnemy(GetOwningPlayer(Caster), GetOwningPlayer(CurrentUnit))) then
            if(Random <= BaB_Spell_SlashStrike_NightChance(AbilLevel)) then
                set Damage = Damage + BaB_Spell_SlashStrike_NightChanceDamage()
            endif
            call CF_DamageWidget(Caster, CurrentUnit, Damage, AttackIndex, DamageIndex)
        endif
        call GroupRemoveUnit(AoE, CurrentUnit)
    endloop
    call SetUnitTimeScale(Caster, BaB_Spell_SlashStrike_AnimationSpeed() * 0.01)
    call TimerStart(t, MinTimerUpdate, false, function BaB_Spell_SlashStrike_Update)
    call RemoveLocation(TargetLoc)
    call DestroyGroup(AoE)
endfunction

function BaB_Spell_SlashStrike_Condition takes nothing returns boolean
    return (GetSpellAbilityId() == BaB_Spell_SlashStrike_Rawcode())
endfunction

//===========================================================================
function InitTrig_Slash_Strike takes nothing returns nothing
    set gg_trg_Slash_Strike = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Slash_Strike, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_Slash_Strike, Condition(function BaB_Spell_SlashStrike_Condition))
    call TriggerAddAction(gg_trg_Slash_Strike, function BaB_Spell_SlashStrike)
endfunction

EDIT: It says: Beginning spell, then Starting Update, then Exiting. So the condition:
Collapse JASS:
if(Distance < CF_Constant_CollisionDetectionRange() or (GetUnitCurrentOrder(GetTriggerUnit()) != String2OrderIdBJ("monsoon"))) then
Is returning false, which stops the rest of it running.
Thing is: I dont know why.
EDIT2: OMG! i just saw GetTriggerUnit() in my code! im ashamed. I will test to see if its fixed.
EDIT3: He does slash faster, and the dubugs show its looping, but he still dosent move over to the location.
07-17-2006, 10:12 PM#6
Rising_Dusk
Isn't it wonderful what going over your spell again can result in? :D
Also, why it doesnt move anything can be caused by a couple things...

Collapse JASS:
call TimerStart(t, MinTimerUpdate, false, function BaB_Spell_SlashStrike_Update)
Notably the timer runs only once there.
Why not set it to periodic true in the bottom function so you dont have to start it again and again?

Also, notably.
You set the caster's position AFTER the loop exits.
Therefore at most you'll set position once. (Also note I didnt check your CF function for moving units, so you'll need to make sure that's working properly too).
07-18-2006, 02:59 PM#7
The)TideHunter(
I went over my spell alot of times.
The timer runs every time until the spell exits.

Collapse JASS:
// Spell
// Slash Strike
//============================================================
// Configuration
constant function BaB_Spell_SlashStrike_Rawcode takes nothing returns integer
    return '????'
endfunction
constant function BaB_Spell_SlashStrike_ChannelOrderString takes nothing returns string
    return "?????"
endfunction

constant function BaB_Spell_SlashStrike_Damage takes integer level returns real
    return (level * 100.) + 100.
endfunction
constant function BaB_Spell_SlashStrike_DamageRadius takes nothing returns real
    return 125.
endfunction
constant function BaB_Spell_SlashStrike_AttackTypeIndex takes nothing returns integer
    return 4
endfunction
constant function BaB_Spell_SlashStrike_DamageTypeIndex takes nothing returns integer
    return 4
endfunction
constant function BaB_Spell_SlashStrike_DamageInterval takes nothing returns real
    return 1.
endfunction

constant function BaB_Spell_SlashStrike_MoveSpeed takes nothing returns real
    return 700.
endfunction
constant function BaB_Spell_SlashStrike_AnimationSpeed takes nothing returns real
    return 300.
endfunction

constant function BaB_Spell_SlashStrike_NightChance takes integer level returns real
    return level * 5.
endfunction
constant function BaB_Spell_SlashStrike_NightChanceDamage takes nothing returns real
    return 100.
endfunction

//============================================================
// Slash Strike
function BaB_Spell_SlashStrike_Update takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit Caster = CF_GetAttachedUnit(t, "Spell_SlashStrike_Caster")
    local integer AbilLevel = CF_GetAttachedInteger(t, "Spell_SlashStrike_AbilLevel")
    local real Progress = CF_GetAttachedReal(t, "Spell_SlashStrike_Progress")
    local real TargetX = CF_GetAttachedReal(t, "Spell_SlashStrike_TargetX")
    local real TargetY = CF_GetAttachedReal(t, "Spell_SlashStrike_TargetY")
    local real CasterX = GetUnitX(Caster)
    local real CasterY = GetUnitY(Caster)
    local real Angle = bj_RADTODEG * Atan2(TargetY - CasterY, TargetX - CasterX)
    local real StartingX = CF_GetAttachedReal(t, "Spell_SlashStrike_StartingX")
    local real StartingY = CF_GetAttachedReal(t, "Spell_SlashStrike_StartingY")
    local real MinTimerUpdate = CF_Constant_MinTimerUpdate()
    local real DistanceX = TargetX - CasterX
    local real DistanceY = TargetY - CasterY 
    local real Distance = SquareRoot((DistanceX * DistanceX) - (DistanceY * DistanceX))
    local real MoveSpeed = BaB_Spell_SlashStrike_MoveSpeed() 
    local real NewX = CasterX + (MoveSpeed / MinTimerUpdate) * Cos(Angle * bj_DEGTORAD)
    local real NewY = CasterY + (MoveSpeed / MinTimerUpdate) * Sin(Angle * bj_DEGTORAD)
    local group AoE
    local real Damage = BaB_Spell_SlashStrike_Damage(AbilLevel)
    local unit CurrentUnit
    local real Random = GetRandomReal(0., 100.)
    local integer AttackIndex = BaB_Spell_SlashStrike_AttackTypeIndex()
    local integer DamageIndex = BaB_Spell_SlashStrike_DamageTypeIndex()
    local real DamageInterval = BaB_Spell_SlashStrike_DamageInterval()
    if(Distance < CF_Constant_CollisionDetectionRange() or (GetUnitCurrentOrder(GetTriggerUnit()) != String2OrderIdBJ("monsoon"))) then
        call CF_DestroyTimer(t)
        set t = null
        call SetUnitTimeScale(Caster, 1.)
    else
        if(Progress >= DamageInterval) then
            set AoE = CreateGroup()
            call GroupEnumUnitsInRange(AoE, CasterX, CasterY, BaB_Spell_SlashStrike_DamageRadius(), null)
            if(BaB_Spell_SlashStrike_NightChance(AbilLevel) > Random) then
                set Damage = Damage + 100
            endif
            loop
                set CurrentUnit = FirstOfGroup(AoE)
                exitwhen CurrentUnit == null
                if(IsPlayerEnemy(GetOwningPlayer(Caster), GetOwningPlayer(CurrentUnit))) then
                    call CF_DamageWidget(Caster, CurrentUnit, Damage, AttackIndex, DamageIndex)
                endif
                call GroupRemoveUnit(AoE, CurrentUnit)
            endloop
            call DestroyGroup(AoE)
        endif
        call CF_SetUnitLoc(Caster, NewX, NewY)
        call TimerStart(t, MinTimerUpdate, false, function BaB_Spell_SlashStrike_Update)
    endif
endfunction

function BaB_Spell_SlashStrike takes nothing returns nothing
    local timer t = CreateTimer()
    local unit Caster = GetSpellAbilityUnit()
    local integer AbilLevel = CF_GetSpellLevel()
    local real CasterX = GetUnitX(Caster)
    local real CasterY = GetUnitY(Caster)
    local location TargetLoc = GetSpellTargetLoc()
    local real TargetX = GetLocationX(TargetLoc)
    local real TargetY = GetLocationY(TargetLoc)
    local real Damage = BaB_Spell_SlashStrike_Damage(AbilLevel)
    local group AoE = CreateGroup()
    local integer AttackIndex = BaB_Spell_SlashStrike_AttackTypeIndex()
    local integer DamageIndex = BaB_Spell_SlashStrike_DamageTypeIndex()
    local unit CurrentUnit
    local real Random = GetRandomReal(0., 100.)
    local real MinTimerUpdate = CF_Constant_MinTimerUpdate()
    call CF_AttachHandle(Caster, "Spell_SlashStrike_Caster", t)
    call CF_AttachInteger(AbilLevel, "Spell_SlashStrike_AbilLevel", t)
    call CF_AttachReal(TargetX, "Spell_SlashStrike_TargetX", t)
    call CF_AttachReal(TargetY, "Spell_SlashStrike_TargetY", t)
    call CF_AttachReal(MinTimerUpdate, "Spell_SlashStrike_Progress", t)
    call CF_AttachReal(CasterX, "Spell_SlashStrike_StartingX", t)
    call CF_AttachReal(CasterY, "Spell_SlashStrike_StartingY", t)
    call GroupEnumUnitsInRange(AoE, CasterX, CasterY, BaB_Spell_SlashStrike_DamageRadius(), null)
    loop
        set CurrentUnit = FirstOfGroup(AoE)
        exitwhen CurrentUnit == null
        if(IsPlayerEnemy(GetOwningPlayer(Caster), GetOwningPlayer(CurrentUnit))) then
            if(Random <= BaB_Spell_SlashStrike_NightChance(AbilLevel)) then
                set Damage = Damage + BaB_Spell_SlashStrike_NightChanceDamage()
            endif
            call CF_DamageWidget(Caster, CurrentUnit, Damage, AttackIndex, DamageIndex)
        endif
        call GroupRemoveUnit(AoE, CurrentUnit)
    endloop
    call SetUnitTimeScale(Caster, BaB_Spell_SlashStrike_AnimationSpeed() * 0.01)
    call TimerStart(t, MinTimerUpdate, false, function BaB_Spell_SlashStrike_Update)
    call RemoveLocation(TargetLoc)
    call DestroyGroup(AoE)
endfunction

Notice:

Collapse JASS:
        call CF_SetUnitLoc(Caster, NewX, NewY)
        call TimerStart(t, MinTimerUpdate, false, function BaB_Spell_SlashStrike_Update)
        call BJDebugMsg("Ending Update")

I dont know why i dont use true, i'v always used it like this.
And if true, it will run in times you dont want too.
When false, you have more control.

The loop is damaging nearby enemies.

Also:

Collapse JASS:
function CF_SetUnitLoc takes unit whichUnit, real X, real Y returns nothing
    if(CF_IsLocSafe(X, Y)) then
        call SetUnitX(whichUnit, X)
        call SetUnitY(whichUnit, Y)
    endif
endfunction

Collapse JASS:
function CF_IsXSafe takes real X returns boolean
    return (X > GetRectMinX(bj_mapInitialPlayableArea)) and (X < GetRectMaxX(bj_mapInitialPlayableArea))
endfunction

function CF_IsYSafe takes real Y returns boolean
    return (Y > GetRectMinY(bj_mapInitialPlayableArea)) and (Y < GetRectMaxY(bj_mapInitialPlayableArea))
endfunction

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

And

MinTimerUpdate is equal too CF_Constant_MinTimerUpdate()
Collapse JASS:
constant function CF_Constant_MinTimerUpdate takes nothing returns real
    return 0.04 // This looks convincing, and isent lag friendly.
                // Credit: Vexorian
                // This was the value I used from his Caster System.
endfunction

Everything works, but the unit moving.
I need to look into this, i will brb.
07-18-2006, 03:04 PM#8
Rising_Dusk
Notably how I work timers is I attach an integer 'index' onto them or some such, then flush/pause/destroy when it passes a certain point.
Works very smoothly for me.

Also, try this before the CF_SetUnitLoc(...) --
Collapse JASS:
call BJDebugMsg(GetUnitName(Caster))
See if the caster is transfering properly.
Also make sure your caster has movement of at least 1 in the OE.

To top it off, not sure if you noticed this, but your code is leaking pretty badly.
You don't nullify timers, locations, units, or groups.
07-18-2006, 03:15 PM#9
The)TideHunter(
OMG, this is taking the micky out of me.
I tested this time, and it keeps running, without instant exit, but still not moving.
I got a fatal error after a few seconds, it looked like he was flashing into and out of existance, until it crashed.
I will go over my code again.

EDIT: I noticed why it crashed.
The line:
Collapse JASS:
local real NewX = CasterX + (MoveSpeed / MinTimerUpdate) * Cos(Angle * bj_DEGTORAD)

MoveSpeed = 600
MinTimerUpdate = 0.04
MoveSpeed / MinTimerUpdate = 15000

Thats why it was flashing, it was jumping all over the place, back and forth trying to get close enough to the targetlocation.

Does anybody know a good way to work out unit move speed with this type of calculation?

Collapse JASS:
    local real TargetX = CF_GetAttachedReal(t, "Spell_SlashStrike_TargetX")
    local real TargetY = CF_GetAttachedReal(t, "Spell_SlashStrike_TargetY")
    local real CasterX = GetUnitX(Caster)
    local real CasterY = GetUnitY(Caster)
    local real Angle = bj_RADTODEG * Atan2(TargetY - CasterY, TargetX - CasterX)
    local real MinTimerUpdate = CF_Constant_MinTimerUpdate()
    local real MoveSpeed = BaB_Spell_SlashStrike_MoveSpeed() 
    local real NewX = CasterX + (MoveSpeed / MinTimerUpdate) * Cos(Angle * bj_DEGTORAD)
    local real NewY = CasterY + (MoveSpeed / MinTimerUpdate) * Sin(Angle * bj_DEGTORAD)

Thats what i have at the moment, and it dosent work
07-18-2006, 03:25 PM#10
Rising_Dusk
Use some preset interval constant that can be changed based on level to the top of the spell's code.
For my spells, I usually use 33 as the interval between iterations of the timer since it looks smooth and causes the projectile/unit to move at roughly 1500-1700 MS.

However, if you still want a calculation --
Try dividing how far you want the unit to move over the entire course of the spell by how many times you want the timer to run.
This allows you to control duration as well as distance, while still offering loads of customability.
07-18-2006, 03:36 PM#11
The)TideHunter(
I changed the movespeed to 7.49, because the detection range is 15., and i dont want it to not be detected and rotate around the target location if the unit cant get close enough.
I tried it, and it exits instantly again.
This is getting rediculous, some times it exits some times it dosent, and all i'v changed is the constant movespeed and detection range!

I need to look into this again -.-

EDIT: This is having a laugh, a tried it again and it worked perfect, it moved and stopped when it got to the target point. I think i need to test a few more times and adjust some things.

EDIT2: Ok it wasent having a laugh, iv tested 20 times, and my results are as follows: You cant target a location in about 200-300 range of the caster, or it will instant exit. Very weird, seen i though i detect with the value of 5. from now on. And it moves 7.49 units every 0.04 secs.
This is a odd odd happening.
Move testing and "looking into it" is needed. Brb
07-18-2006, 03:57 PM#12
Rising_Dusk
Use a 'DistanceBetweenPointsXY(...)" function to get the max distance, then divide it by the number of iterations of the timer.
That will cause the spell to always move to the target point no matter where it is targeting. (Assuming the code works as you say)
07-18-2006, 04:25 PM#13
The)TideHunter(
It dosent matter now, i just added a If to check if the targeted loc is in range of 400, if it is pause, stop, unpause, destroy stuff etc.
And i changed the event from Begins the effect to Begins casting.
Nobody can take advantage of this spell, seen as it checks to see if the order ID is tornado.
That stops cooldown and mana stuff.

Thanks for the help, you tried your best.
I would rep you but im not allowed, i need to "Spread more reputation around before giving to to Rising_Dusk again." =(.
07-18-2006, 04:29 PM#14
Rising_Dusk
Well as long as it works.
That's all that really matters.