1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. The Lich King demands your service! We've reached the 19th edition of the Icon Contest. Come along and make some chilling servants for the one true king.
    Dismiss Notice
  4. The 4th SFX Contest has started. Be sure to participate and have a fun factor in it.
    Dismiss Notice
  5. The poll for the 21st Terraining Contest is LIVE. Be sure to check out the entries and vote for one.
    Dismiss Notice
  6. The results are out! Check them out.
    Dismiss Notice
  7. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  8. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    Dismiss Notice
  9. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[JASS] Opinion and help about spells

Discussion in 'Triggers & Scripts' started by Flame_Phoenix, Sep 14, 2007.

  1. Flame_Phoenix

    Flame_Phoenix

    Joined:
    May 4, 2007
    Messages:
    2,283
    Resources:
    11
    Tools:
    1
    Maps:
    1
    Spells:
    6
    Tutorials:
    3
    Resources:
    11
    Hi guys, well, recently i decided to convert all my GUI spells into JASS, for greater efficiency. However it being more complicated than i expected ... to start i have this spell:

    • Frost Nova
      • Events
        • Unit - A unit Starts the effect of an ability
      • Conditions
        • (Ability being cast) Equal to Frost Nova
      • Actions
        • Set FrostNovaLevel = (Level of Frost Nova for (Triggering unit))
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • FrostNovaLevel Equal to 1
          • Then - Actions
            • For each (Integer A) from 1 to 16, do (Actions)
              • Loop - Actions
                • Unit - Create 1 Frost Nova Caster for (Owner of (Triggering unit)) at (Position of (Triggering unit)) facing Default building facing degrees
                • Unit - Set level of Frost nova wave (Neutral Hostile) for (Last created unit) to FrostNovaLevel
                • Unit - Add a 2.00 second Generic expiration timer to (Last created unit)
                • Unit - Order (Last created unit) to Undead Crypt Lord - Impale ((Position of (Triggering unit)) offset by 100.00 towards PointofTargetNova degrees)
                • Set PointofTargetNova = (PointofTargetNova + 25.00)
          • Else - Actions
            • Do nothing


    Jass converted version

    Code (vJASS):
    function Trig_Ice_Force_Conditions takes nothing returns boolean
        if ( not ( GetSpellAbilityId() == 'A022' ) ) then
            return false
        endif
        return true
    endfunction

    function Trig_Ice_Force_Func002C takes nothing returns boolean
        if ( not ( udg_FrostNovaLevel == 1 ) ) then
            return false
        endif
        return true
    endfunction

    function Trig_Ice_Force_Actions takes nothing returns nothing
        set udg_FrostNovaLevel = GetUnitAbilityLevelSwapped('A022', GetTriggerUnit())
        if ( Trig_Ice_Force_Func002C() ) then
            set bj_forLoopAIndex = 1
            set bj_forLoopAIndexEnd = 16
            loop
                exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
                call CreateNUnitsAtLoc( 1, 'h01B', GetOwningPlayer(GetTriggerUnit()), GetUnitLoc(GetTriggerUnit()), bj_UNIT_FACING )
                call SetUnitAbilityLevelSwapped( 'A021', GetLastCreatedUnit(), udg_FrostNovaLevel )
                call UnitApplyTimedLifeBJ( 2.00, 'BTLF', GetLastCreatedUnit() )
                call IssuePointOrderLocBJ( GetLastCreatedUnit(), "impale", PolarProjectionBJ(GetUnitLoc(GetTriggerUnit()), 100.00, udg_Point_Nova_Spell) )
                set udg_Point_Nova_Spell = ( udg_Point_Nova_Spell + 25.00 )
                set bj_forLoopAIndex = bj_forLoopAIndex + 1
            endloop
        else
            call DoNothing(  )
        endif
    endfunction

    //===========================================================================
    function InitTrig_Ice_Force takes nothing returns nothing
        set gg_trg_Ice_Force = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_Ice_Force, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( gg_trg_Ice_Force, Condition( function Trig_Ice_Force_Conditions ) )
        call TriggerAddAction( gg_trg_Ice_Force, function Trig_Ice_Force_Actions )
    endfunction


    This is the GUi version .... which i don't even know if it is MUI... and leaks like hell(that i am sure).

    Now here is my version of the same spell:

    Code (vJASS):
    function IceForce_Conds takes nothing returns boolean
        return GetSpellAbilityId() == 'A022'
    endfunction
    //==========================================================================
    function IceForce_Acts takes nothing returns nothing
        local unit caster = GetTriggerUnit()
        local unit dum
        local location loc = GetUnitLoc(caster)
        set bj_forLoopAIndex = 1
        set bj_forLoopAIndexEnd = 16
        loop
            exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
            set dum = CreateUnit(GetOwningPlayer(caster), 'h01B', GetUnitX(caster), GetUnitY(caster), 0)
            call SetUnitAbilityLevel(dum, 'A021', 1)
            call UnitApplyTimedLife(dum, 'BTLF', 2.00)
            call IssuePointOrderLoc(dum, "impale", PolarProjectionBJ(loc), 100.00, udg_Point_Nova_Spell) )
            set udg_Point_Nova_Spell = ( udg_Point_Nova_Spell + 25.00 )
            set bj_forLoopAIndex = bj_forLoopAIndex + 1
        endloop
    endfunction
    //===========================================================================
    function InitTrig_Ice_Force takes nothing returns nothing
        local trigger IceForce = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( IceForce, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( IceForce, Condition( function IceForce_Conds ) )
        call TriggerAddAction( IceForce, function IceForce_Acts )
        set IceForce = null
    endfunction


    A lot smaller but there is something wrong ... So, could you guys help me ???
    For now i just want to improve the GUI spell, and see if my JASS version works .. =S




    Another spell i found is this knock back spell:
    Code (vJASS):

    constant function BloodyPile_SpellId takes nothing returns integer
        return 'A000' //Rawcode of the BloodyPile Ability
    endfunction  

    constant function BloodyPile_SlideDuration takes nothing returns real
        return 0.60 //Defines the slide duration of target
    endfunction

    constant function BloodyPile_SpellDemage takes integer level returns real
        return level*90.00
        //This formula adds 90 demage per level of the spell
        //Starting from 90
    endfunction

    constant function BloodyPile_TargetConditions takes unit Caster, unit Target returns boolean
        return (Target != Caster) and ( IsPlayerEnemy(GetOwningPlayer(Target), GetOwningPlayer(Caster)) ) and not(IsUnitType(Target, UNIT_TYPE_STRUCTURE)) and not(IsUnitType(Target,UNIT_TYPE_DEAD)) and not(IsUnitType(Target, UNIT_TYPE_MAGIC_IMMUNE))
        //Defines the targetable units which will get demage from unit sliding effect
    endfunction

    // This spell is playing target units death animation while sliding
    // This gives a pain effect but if you use units which has no fleshy
    // body animation modify this function

    constant function BloodyPile_DeathAnimation takes nothing returns boolean
        return true //Make this "false" to disable targets death animation.
    endfunction
    //===================================================================================================

    function BloodyPile_Conditions takes nothing returns boolean
        return GetSpellAbilityId() == BloodyPile_SpellId()
    endfunction

    //Kills Picked Destructables near target when sliding
    function BloodyPile_KillTreesOnTheWay takes nothing returns nothing
        call KillDestructable( GetEnumDestructable() )
    endfunction

    //Makes target unit slide and demage nearby units and throw them avay from it
    function BloodyPile_SlideUnit takes nothing returns nothing    
        local timer Loop = GetExpiredTimer()
        local unit Target = H2U(GetHandleHandle(Loop, "Target"))
        local unit Caster = H2U(GetHandleHandle(Loop, "Caster"))
        local unit PickedUnit
        local group UnitsInRange
        local real Angle = GetHandleReal(Loop, "Angle")
        local real AngleSmall
        local location TargetPoint = GetUnitLoc(Target)
        local location TargetPointSmall
        local location MovePoint = PolarProjectionBJ(TargetPoint,20.00,Angle)
        local location MovePointSmall
        local effect MiniEffect

        call SetUnitPositionLoc(Target, MovePoint)
        set MiniEffect = AddSpecialEffectTarget("Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl",Target,"origin")
        call DestroyEffect(MiniEffect)
        call EnumDestructablesInCircleBJ( 200.00, TargetPoint, function BloodyPile_KillTreesOnTheWay )
        set UnitsInRange = GetUnitsInRangeOfLocAll(250, TargetPoint)
        call GroupRemoveUnit(UnitsInRange,Target)
        set PickedUnit = FirstOfGroup(UnitsInRange)

        loop
            exitwhen PickedUnit==null
            set PickedUnit = FirstOfGroup(UnitsInRange)
            call GroupRemoveUnit(UnitsInRange,PickedUnit)
            if (BloodyPile_TargetConditions(Caster, PickedUnit)) then            
                set TargetPointSmall = GetUnitLoc(PickedUnit)
                set AngleSmall = AngleBetweenPoints(TargetPoint,TargetPointSmall)
                set MovePointSmall = PolarProjectionBJ(TargetPointSmall,80,AngleSmall)
                call SetUnitPositionLoc(PickedUnit, MovePointSmall)
                call UnitDamageTarget(Caster,PickedUnit,25*GetUnitAbilityLevel(Caster, BloodyPile_SpellId()),false,false,null,null,null)

                call RemoveLocation(TargetPointSmall)
                call RemoveLocation(MovePointSmall)
            endif
        endloop      
     
        call RemoveLocation(MovePoint)
        call RemoveLocation(TargetPoint)
        call DestroyGroup(UnitsInRange)    
        set Caster = null
        set Target = null
    endfunction

    function BloodyPile_Actions takes nothing returns nothing
        local timer Loop = CreateTimer()
        local effect StunEffect
        local unit Target = GetSpellTargetUnit()
        local unit Caster = GetSpellAbilityUnit()
        local location TargetPoint = GetUnitLoc(Target)
        local location CasterPoint = GetUnitLoc(Caster)
        local real Angle = AngleBetweenPoints(CasterPoint, TargetPoint)
        local real Demage = BloodyPile_SpellDemage(GetUnitAbilityLevel(Caster, BloodyPile_SpellId()))
        local real Duration = BloodyPile_SlideDuration()

     
        call SetHandleHandle(Loop, "Target", Target)
        call SetHandleHandle(Loop, "Caster", Caster)
        call SetHandleReal(Loop, "Angle", Angle)
        call SetUnitFacingToFaceUnitTimed( Target, Caster, 0 )
        call PauseUnit(Target,true)
       
        if (BloodyPile_DeathAnimation()) then
            call SetUnitAnimation( Target, "death" )
        endif
       
        call UnitDamageTarget(Caster,Target,Demage,false,false,null,null,null)
        call TimerStart(Loop, 0.03, true, function BloodyPile_SlideUnit)    
        call TriggerSleepAction( Duration )
        call PauseTimer(Loop)
        call FlushHandleLocals(Loop)
        call DestroyTimer(Loop)

        if not (IsUnitType(Target,UNIT_TYPE_DEAD)) then
            set StunEffect = AddSpecialEffectTarget( "Abilities\\Spells\\Human\\Thunderclap\\ThunderclapTarget.mdl", Target, "overhead")        
            call TriggerSleepAction( 1.25 * GetUnitAbilityLevel(Caster, BloodyPile_SpellId()))
            call DestroyEffectBJ( StunEffect )
        endif
        call PauseUnit(Target,false)

        call RemoveLocation(TargetPoint)
        call RemoveLocation(CasterPoint)
        set Caster = null
        set Target = null    
    endfunction

    // ===========================================================================
    function InitTrig_BloodyPile takes nothing returns nothing
        local trigger gg_trg_BloodyPile = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( gg_trg_BloodyPile, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( gg_trg_BloodyPile, Condition( function BloodyPile_Conditions ) )
        call TriggerAddAction( gg_trg_BloodyPile, function BloodyPile_Actions )
    endfunction
     


    It is really cool, it knockback units destroys trees, creates a nice smooth effect and plays the unit death animation.
    Still my JASS editor finds some errors ... However the spell seems to work fine... Which leads me to the question, is this spell MUI and leak free ??? Why are the errors here ??

    Errors:
    41-46 Undeclared function GetHandleHandle; Undeclared function H2U
    46 Cannot convert null to real
    96-97 Undeclared function SetHandleHandle
    98 Undeclared function SetHandleReal
    100 Undeclared function FlushHandleLocals

    10 errors total

    I know about handles, but i don't know why the jasscraft sees them as an error ... is there anything wrong with the spell ???? Or is my program going nuts ?

    plx help =S
     
    Last edited: Sep 14, 2007
  2. HINDYhat

    HINDYhat

    Joined:
    Apr 22, 2007
    Messages:
    1,594
    Resources:
    3
    Maps:
    2
    Spells:
    1
    Resources:
    3
    Gah, use coordinates please. loc is leaking.

    Also, you closed the parenthesis on PolarProjectionBJ(loc). It should be: PolarProjectionBJ(loc, 100.00, udg_Point_Nova_Spell).

    You could also use a local integer for the loop count. No need to use bj globals.

    Finally, why don't you use a local for udg_Point_Nova_Spell? Here's how I would do it:
    Code (vJASS):
    function IceForce_Conds takes nothing returns boolean
        return GetSpellAbilityId() == 'A022'
    endfunction
    //========================================================
    function IceForce_Acts takes nothing returns nothing
        local unit caster = GetTriggerUnit()
        local unit dum
        local real x=GetUnitX(caster)
        local real y=GetUnitY(caster)
        local integer i=1
        loop
            exitwhen i>16
            set dum = CreateUnit(GetOwningPlayer(caster), 'h01B',x,y, 0)
            call SetUnitAbilityLevel(dum, 'A021', 1)
            call UnitApplyTimedLife(dum, 'BTLF', 2.00)
            call IssuePointOrder(dum, "impale",x+Cos(22.5*i*bj_DEGTORAD)*100,y+Sin(22.5*i*bj_DEGTORAD)*100)
            call UnitAddAbility(dum,'Aloc')
            set i=i+1
        endloop
        set caster=null
        set dum=null
    endfunction
    //========================================================
    function InitTrig_Ice_Force takes nothing returns nothing
        set gg_trg_Ice_Force = CreateTrigger( )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_Ice_Force, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( gg_trg_Ice_Force, Condition( function IceForce_Conds ) )
        call TriggerAddAction( gg_trg_Ice_Force, function IceForce_Acts )
    endfunction

    Tested and works fine.
     
  3. Flame_Phoenix

    Flame_Phoenix

    Joined:
    May 4, 2007
    Messages:
    2,283
    Resources:
    11
    Tools:
    1
    Maps:
    1
    Spells:
    6
    Tutorials:
    3
    Resources:
    11
    Exactly my point, i knew my version had something wrong .. just forgot to destroy the loc and nullify it ... but i was going to do it ....

    The main reason why i had so many problems was because i didn't understand the use of so many globals =S it just overloads my brain ..
    thx for help

    Still
    Code (vJASS):
    x+Cos(22.5*i*bj_DEGTORAD)*100,y+Sin(22.5*i*bj_DEGTORAD)*100)

    HOLYMACAROLY !! what the h*** is this ... BJ's are bad, but you use them ... also where does that formula come from !? Thx anyway, please reply back.

    Also any ideas about my seconds spell !??!!? why is it wrong or something !??!? guys plz ??
     
  4. HINDYhat

    HINDYhat

    Joined:
    Apr 22, 2007
    Messages:
    1,594
    Resources:
    3
    Maps:
    2
    Spells:
    1
    Resources:
    3
    Got into trigonometry yet? Basically, what I did is polar projection using coordinates.

    Cos A = a/c
    Sin A = b/c
    Where c is the hypotenuse of a right triangle, and a is the side opposite to the angle A. b is the adjacent side. You can use x + Cos(direction)*length to project an x coordinate, and y + Sin(direction)*length to project a y coordinate. Or course, the direction angle is in radians, so I used bj_DEGTORAD*22.5 to convert it that way. I could have used CosBJ, but that's a BJ function = bad.

    I'm not using BJ functions, I'm using bj globals, which aren't bad at all. You could still use this (which is somewhat better and shorter). Here, use this line if you don't want to use the bj globals:
    Code (vJASS):
    call IssuePointOrder(dum, "impale",x+Cos(i*3.14159/8)*100,y+Sin(i*3.14159/8)*100)

    I'll check up your other spell.

    EDIT: Found the bugs and I'm overall optimizing it. I'll post it up when I'm done.

    EDIT2: Remaking it completely.
     
    Last edited: Sep 14, 2007
  5. Flame_Phoenix

    Flame_Phoenix

    Joined:
    May 4, 2007
    Messages:
    2,283
    Resources:
    11
    Tools:
    1
    Maps:
    1
    Spells:
    6
    Tutorials:
    3
    Resources:
    11
    MMmmm, i didn't know the other spell i posted was such a mess =S

    Anyway, thx by the tips on the first spell. I changed some stuff as you will notice, and removed some locals to speed up the process.
    About the polarprojectionBJ, well, i guess there there are things i will never understand ... this is the second time i can't understand what you guys do =S
    Anyway, really thx by the help, i have also added some rep points to you =)

    Improved spell:
    Code (vJASS):
    function IceForce_Conds takes nothing returns boolean  
        return GetSpellAbilityId() == 'A022'
    endfunction
    //========================================================
    function IceForce_Acts takes nothing returns nothing  
        local unit caster = GetTriggerUnit()  
        local unit dum  
        local integer i=1
        loop  
            exitwhen i>16
            set dum = CreateUnit(GetOwningPlayer(caster), 'h01B',GetUnitX(caster),GetUnitY(caster), 0)  
            call UnitAddAbility(dum,'Aloc')
            call SetUnitAbilityLevel(dum, 'A021', 1)  
            call UnitApplyTimedLife(dum, 'BTLF', 2.00)  
            call IssuePointOrder(dum, "impale",GetUnitX(caster)+Cos(i*3.14159/8)*100,GetUnitY(caster)+Sin(i*3.14159/8)*100)
            set i=i+1
        endloop  
        set caster=null  
        set dum=null
    endfunction
    //========================================================
    function InitTrig_Ice_Force takes nothing returns nothing  
        local trigger IceForce = CreateTrigger( )  
        local integer index = 0
        loop
            exitwhen index == 16
            call TriggerRegisterPlayerUnitEvent(IceForce, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            set index = index + 1
        endloop
        call TriggerAddCondition( IceForce, Condition( function IceForce_Conds ) )  
        call TriggerAddAction( IceForce, function IceForce_Acts )
        set IceForce = null
    endfunction
     
  6. HINDYhat

    HINDYhat

    Joined:
    Apr 22, 2007
    Messages:
    1,594
    Resources:
    3
    Maps:
    2
    Spells:
    1
    Resources:
    3
    Here, I'm done with fixing up the knockback spell. If you would use JNGP, it would be easier to make, but blah.
    Code (vJASS):
    constant function BloodyPile_SpellId takes nothing returns integer
        return 'AHtb' //Rawcode of the BloodyPile Ability
    endfunction
    constant function BloodyPile_SpellDemage takes integer level returns real
        return level*90.00
        //This formula adds 90 demage per level of the spell
        //Starting from 90
    endfunction
    constant function BloodyPile_KnockPower takes nothing returns real
        return 40.
    endfunction
    constant function BloodyPile_TargetConditions takes unit Caster, unit Target returns boolean
        return (Target != Caster) and (Target!=bj_ghoul[100]) and ( IsPlayerEnemy(GetOwningPlayer(Target), GetOwningPlayer(Caster)) ) and not(IsUnitType(Target, UNIT_TYPE_STRUCTURE)) and not(IsUnitType(Target,UNIT_TYPE_DEAD)) and not(IsUnitType(Target, UNIT_TYPE_MAGIC_IMMUNE))
        //Defines the targetable units which will get demage from unit sliding effect
    endfunction
    // This spell is playing target units death animation while sliding
    // This gives a pain effect but if you use units which has no fleshy
    // body animation modify this function
    constant function BloodyPile_DeathAnimation takes nothing returns boolean
        return true //Make this "false" to disable targets death animation.
    endfunction
    //===================================================================================================
    function BloodyPile_Conditions takes nothing returns boolean
        return GetSpellAbilityId() == BloodyPile_SpellId()
    endfunction
    //Kills Picked Destructables near target when sliding
    function BloodyPile_KillTreesOnTheWay takes nothing returns nothing
        call KillDestructable( GetEnumDestructable() )
    endfunction
    function CheckPathabilityTrickGet takes nothing returns nothing
        set bj_rescueChangeColorUnit = bj_rescueChangeColorUnit or (GetEnumItem()!=bj_itemRandomCurrentPick)
    endfunction
    function CheckPathabilityTrick takes item p, real x, real y returns boolean
        local integer i=30
        local rect r
        call SetItemPosition(p,x,y)
        if ((Pow(GetItemX(p)-x,2)+Pow(GetItemY(p)-y,2))<=100) then
            return true
        endif
        set r=Rect(x-i,y-i,x+i,y+i)
        set bj_itemRandomCurrentPick=p
        set bj_rescueChangeColorUnit=false
        call EnumItemsInRect(r,null,function CheckPathabilityTrickGet)
        call RemoveRect(r)
        set r=null
        return bj_rescueChangeColorUnit
    endfunction
    function CheckPathability takes real x, real y returns boolean
        local item it = CreateItem('ciri',x,y)
        local boolean b = CheckPathabilityTrick(it,x,y)
        call SetItemVisible(it,false)
        call RemoveItem(it)
        set it=null
        return b
    endfunction
    function TrueFilter takes nothing returns boolean
        return true
    endfunction
    function DestroyEffectEx takes nothing returns nothing
        local effect StunEffect = AddSpecialEffectTarget( "Abilities\\Spells\\Human\\Thunderclap\\ThunderclapTarget.mdl", bj_ghoul[101], "overhead")
        local unit target=bj_ghoul[101]
        call PolledWait( 1.25 * GetUnitAbilityLevel(bj_ghoul[100], BloodyPile_SpellId()))
        call DestroyEffect( StunEffect )
        call PauseUnit(target,false)
        set StunEffect=null
    endfunction
    function BloodyPile_SlideUnit takes nothing returns nothing
        local timer t=GetExpiredTimer()
        local unit target=GetHandleUnit(t,"target")
        local unit caster=GetHandleUnit(t,"caster")
        local real radians=GetHandleReal(t,"angle")
        local real power=GetHandleReal(t,"power")
        local real x=GetUnitX(target)+power*Cos(radians)
        local real y=GetUnitY(target)+power*Sin(radians)
        local group g=CreateGroup()
        local unit u
        local real r
        local real x2
        local real y2
        local rect r2=Rect(x-100,y-100,x+100,y+100)
        set bj_ghoul[100]=target
        call EnumDestructablesInRect(r2,Filter(function TrueFilter),function BloodyPile_KillTreesOnTheWay)
        call GroupEnumUnitsInRange(g,x,y,100.,Filter(function TrueFilter))
        loop
            set u=FirstOfGroup(g)
            exitwhen u==null
            if BloodyPile_TargetConditions(caster,u) then
                set r=Atan2(GetUnitY(u)-GetUnitY(target),GetUnitX(u)-GetUnitX(target))
                call UnitDamageTarget(caster,u,25*GetUnitAbilityLevel(caster, BloodyPile_SpellId()),false,false,null,null,null)
                set x2=GetUnitX(u)+Cos(r)*40
                set y2=GetUnitY(u)+Sin(r)*40
                if CheckPathability(x2,y2) then
                    call SetUnitX(u,x2)
                    call SetUnitY(u,y2)
                endif
            endif
            call GroupRemoveUnit(g,u)
        endloop
        if CheckPathability(x,y) then
            call SetUnitX(target,x)
            call SetUnitY(target,y)
        endif
        set power=power-GetHandleReal(t,"totalpower")*0.1
        if power<=0 then
            call PauseTimer(t)
            call DestroyTimer(t)
            call FlushHandleLocals(t)
            if GetUnitState(target,UNIT_STATE_LIFE)>0 then
                set bj_ghoul[101]=target
                set bj_ghoul[100]=caster
                call ExecuteFunc("DestroyEffectEx")
            endif
        else
            call SetHandleReal(t,"power",power)
        endif
        call RemoveRect(r2)
        call DestroyGroup(g)
        set g=null
        set target=null
        set caster=null
        set u=null
        set r2=null
    endfunction
    function BloodyPile_Actions takes nothing returns nothing
        local timer t=CreateTimer()
        local unit caster=GetTriggerUnit()
        local unit target=GetSpellTargetUnit()
        local real angle=Atan2(GetUnitY(target)-GetUnitY(caster),GetUnitX(target)-GetUnitX(caster))
        call SetHandleHandle(t, "target", target)
        call SetHandleHandle(t, "caster", caster)
        call SetHandleReal(t, "angle", angle)
        call SetHandleReal(t,"totalpower",BloodyPile_KnockPower())
        call SetHandleReal(t,"power",BloodyPile_KnockPower())
        call SetUnitFacing(caster,angle*180/3.14159)
        call PauseUnit(target,true)
        if (BloodyPile_DeathAnimation()) then
            call SetUnitAnimation( target, "death" )
        endif
        call UnitDamageTarget(caster,target,BloodyPile_SpellDemage(GetUnitAbilityLevel(caster, BloodyPile_SpellId())),false,false,null,null,null)
        call TimerStart(t, 0.03, true, function BloodyPile_SlideUnit)
    endfunction
    // ===========================================================================
    function InitTrig_BloodyPile takes nothing returns nothing
        set gg_trg_BloodyPile = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( gg_trg_BloodyPile, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( gg_trg_BloodyPile, Condition( function BloodyPile_Conditions ) )
        call TriggerAddAction( gg_trg_BloodyPile, function BloodyPile_Actions )
    endfunction


    IMO it looks nicer this way.

    EDIT: Thanks for the rep :D. +REP @ you!

    Here are some things you should be aware of. There's no need to make local triggers in your InitTrig function, because the global trigger variable IS in the map, and you can't take it off (unless you delete the trigger). You're just using up more map memory. Might aswell use the global trigger while it's there.

    Here's an explanation of polar projections. Lemme look up the polar projection function in JassCraft...
    Code (vJASS):
    function PolarProjectionBJ takes location source, real dist, real angle returns location
        local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
        local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
        return Location(x, y)
    endfunction

    See? It's doing the exact same thing I did: x + Cos(angle)*length, y + Sin(angle)*length.

    Here I'll try to explain using math... Lets say you have a right triangle (a triangle with a 90 degree angle). The side opposite to that angle is called the hypotenuse, which is often referred to as h, or c, in trigonometry. The other two sides of the triangle can have inversed names. I call them a, and b. Some other people call the, a (for adjacent) and o (for opposite). Usually, the angle that is opposite to a side is the variable letter of the side, in capital letters.

    Heard about the Pythagorean theorem? One of the most important trigonometric equations. It states that a^2 + b^2 = c^2. The sum of the length of the sides of a right triangle, squared, equals the hypotenuse of that triangle squared. Other important equations:
    sin A = a/c
    cos A = b/c
    tan A = a/b
    Works in the other way too:
    sin B = b/c
    cos B = a/c
    tan B = b/a
    To get the angle value, we use the inverse functions:
    cos(-1) b/c = A
    sin(-1) a/c = A
    tan(-1) a/b = A
    And they work in the other way too.

    Now, the use of the sine and cosine functions in Warcraft III. Well, Warcraft III works sort of like a 3 dimensional graph... with the X, Y and Z axis. Let's just use the X and Y axis for now. Let's say you have a point on the map, (0,0). You want to 'project' that point towards a direction:
    [​IMG]

    I don't know if you understand... I suck at explaining stuff. If you still don't understand, ask me a direct question about exactly what that you don't get, or www.wikipedia.org :D.
     
    Last edited: Sep 14, 2007
  7. Flame_Phoenix

    Flame_Phoenix

    Joined:
    May 4, 2007
    Messages:
    2,283
    Resources:
    11
    Tools:
    1
    Maps:
    1
    Spells:
    6
    Tutorials:
    3
    Resources:
    11
    MMM i see your modifications ... thx but now according to JassCraft i have 17 errors instead of 10 =S .... Is the other spell such a mess ??? Or is my program wrong ??? or your spell wrong ???
     
  8. HINDYhat

    HINDYhat

    Joined:
    Apr 22, 2007
    Messages:
    1,594
    Resources:
    3
    Maps:
    2
    Spells:
    1
    Resources:
    3
    JassCraft reports no errors to me. Probably just because you didn't add the Handle Vars script to the syntax checker.

    BTW I tested it, and it works fine.
     
  9. Flame_Phoenix

    Flame_Phoenix

    Joined:
    May 4, 2007
    Messages:
    2,283
    Resources:
    11
    Tools:
    1
    Maps:
    1
    Spells:
    6
    Tutorials:
    3
    Resources:
    11
    Very impressive explication =) I am very familiar with maths and i understand very well the trign stuff Triangles are easy for me as well as formulas. You also skipped some important maths formulas, that use cos, sin and tan.
    sin^2+cos^2 = 1 ( I think don't remember very well).
    and more formulas that i will soon post if you want or need.

    But anyway i have 2 questions for you.
    1 - How do i add the HandleVars into the memory of JAssCraft so it can access it for syntax checks ??
    2 - The second question is about your explication. Personally in my opinion you did a great job in your mini-tutorial, however i didn't understood 2 things.
    Those 2 things i will tell you tomorrow, because i don't have time right now, i am just making a quick reply.

    Also, about the rep points, you are the one who deserves them, check out the logic:
    1 - You help people > they give you a reward
    2 - I ask for help > i am helped > I get a reward without doing anything (well, i asked of help, that can count =p)

    So thx by the rep points but in my opinion, you deserve them more than i do =)
     
  10. PurplePoot

    PurplePoot

    Joined:
    Dec 14, 2005
    Messages:
    11,161
    Resources:
    3
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    3
    Those formulae have nothing to do with the math used here, though - that's for algebra stuff with no practical use within warcraft 3 (that I can think of)

    Put it into a .j file, then View -- Options -- Jass Enchantments -- Add (under the Native Files category)

    No, I don't mean "Jass Enhancements", JassCraft calls it "Enchantments" for some reason -.-
     
  11. HINDYhat

    HINDYhat

    Joined:
    Apr 22, 2007
    Messages:
    1,594
    Resources:
    3
    Maps:
    2
    Spells:
    1
    Resources:
    3
    I know that there are loads of other formulas, but I only pasted the important ones used in Warcraft III.

    To add the handle vars script to JassCraft syntax, make a notepad file with the functions used in handle vars. Change the extension to .j, and place it in the jasscraft folder. Then open jasscraft and go to options, and check the handle vars .j file at the syntax checking tab.

    I'm just returning the favor about rep :D. You rep me, I rep you.

    EDIT: GAH poot, responded faster than me.
     
  12. PurplePoot

    PurplePoot

    Joined:
    Dec 14, 2005
    Messages:
    11,161
    Resources:
    3
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    3
    Blarg, please don't do that -.-

    If everyone did, there would be giant rep-chains that would make it meaningless (more so than it already is...)
     
  13. HINDYhat

    HINDYhat

    Joined:
    Apr 22, 2007
    Messages:
    1,594
    Resources:
    3
    Maps:
    2
    Spells:
    1
    Resources:
    3
    Maybe change the message that pops up after you rep someone then??
     
  14. PurplePoot

    PurplePoot

    Joined:
    Dec 14, 2005
    Messages:
    11,161
    Resources:
    3
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    3
    It means for other reasons... meh, just ignore that.
     
  15. Flame_Phoenix

    Flame_Phoenix

    Joined:
    May 4, 2007
    Messages:
    2,283
    Resources:
    11
    Tools:
    1
    Maps:
    1
    Spells:
    6
    Tutorials:
    3
    Resources:
    11
    OOk, so, to start what is the file i must add to jasscraft ?? Which script is it ??. Do i have to add that script in the headers of my map too if i use the spell ?
    My map already has a script in it's header ... can it have more than 1 ?

    Also, my questions about polarbj:

    What i mainly don't understand is the formula you guys use ...

    and you have:
    real x = x + Cos(angle)*length
    real y = y + Sin(angle)*length

    Where it should be:
    real x = x + dist*Cos(angle*(3.14159/180.0))
    real y = y + dist*Sin(angle*(3.14159/180.0))

    So, to start, we don't know the "distance" value, the length value seems to be in the wrong place and the bj_degtorad just ran away ... This is my main first problem ... not understanding how you people use the formula.

    The other question i have is about how warcraft uses it.

    The image is pretty good, but how can we consider a 2 axis system in a formula, when warcraft has a 3 axis system ??
    To make that work the Z value would have to be 0 ... but that value doesn't show up in polarprojectionBJ. Also the Z axis would have to be the something else besides the sin, cos and tan.

    Please explain these 3 questions ... very messed up ? =S
     
  16. PurplePoot

    PurplePoot

    Joined:
    Dec 14, 2005
    Messages:
    11,161
    Resources:
    3
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    3
    len*Cos = Cos*len... doesn't matter what order they come in.

    And you don't need to use bj_DEGTORAD if they're already in radians, flame.
     
  17. HINDYhat

    HINDYhat

    Joined:
    Apr 22, 2007
    Messages:
    1,594
    Resources:
    3
    Maps:
    2
    Spells:
    1
    Resources:
    3
    Okay here goes.

    The file you add is a .j script of Handle Vars. Just paste the handle vars script into jasscraft and save it as a .j and put it in your jasscraft folder (then follow poot's directives). You don't have to add it twice in your map (that would make loads of syntax errors).

    See, I used radians instead of degrees. Most Warcraft III functions work with radians. Like the CosBJ function takes a degree value, and here's what it does:
    Code (vJASS):
    function CosBJ takes real degrees returns real
        return Cos(degrees * bj_DEGTORAD)
    endfunction

    Which is stupid, since we could directly run the Cos function using radian angles. bj_DEGTORAD is simply 3.14159/180, and bj_RADTODEG is 180/3.14159. The PolarProjectionBJ function takes degree values, that's why they are using bj_DEGTORAD as a factor in the Cos and Sin functions.

    Okay here you've got it wrong. Example: Let's say you have this equation:
    x = 2 + 4 * 3
    Based on the order of equations and stuff, the multiplication always goes before the addition, so it would be the same thing as:
    x = 3 * 4 + 2
    No matter how much you mess it up, if 3 and 4 are next to eachother, it will work.

    The Z axis is changed using:
    Code (vJASS):
    native          SetUnitFlyHeight    takes unit whichUnit, real newHeight, real rate returns nothing

    But before using that, if the unit is not a flying one, you have to do this:
    Code (vJASS):
    call UnitAddAbility(yourunit, 'Amrf')
    call UnitRemoveAbility(yourunit, 'Amrf')


    Warcraft III just follows the height of the location you moved the unit to, + the height of the unit.

    Hope you understand... :/
     
  18. Flame_Phoenix

    Flame_Phoenix

    Joined:
    May 4, 2007
    Messages:
    2,283
    Resources:
    11
    Tools:
    1
    Maps:
    1
    Spells:
    6
    Tutorials:
    3
    Resources:
    11
    mmmm, more two question ... first
    I already know HOW to do it, i just don't know with WHICH script i have to use to do that ...

    Also
    well, you explacation about signals is not a new to me ... My problem is the values you have !!

    like:
    GetLocationX(source) = x
    dist = ?
    bj_DEGTORAD = 3.14159/180.0
    angle = ?
    cos = well if i don't kno1 value i can't know the other one

    and you use a different method (i think):
    GetLocationX(source) = x
    length = what is this !?
    angle = how do i know it !?
    cos = blarg ..

    About he Z axis, if you are in a 3d world, don't you also have to give a Z value to the polar projection ??? Imagine that i want to do a vertical ray, i have to do give it a Z value ...




    Also, i have some question about one of my spells.

    Code (vJASS):
    function AnimalAura_Acts takes nothing returns nothing
        local unit Killer = GetKillingUnit()
        local unit dead = GetDyingUnit()
        local unit dum
        local integer AAchance
        if GetUnitAbilityLevel(GetKillingUnit(), 'B019' ) > 0 and GetRandomInt(1, 100) <= AAchance then
            set AAchance = 5
            set dum = CreateUnit(GetOwningPlayer(Killer), 'h01H', GetUnitX(dead), GetUnitY(dead), 0.00)
            call UnitAddAbility(dum, 'A04V')
            call SetUnitAbilityLevel(dum, 'A04V', 1)
            call IssuePointOrder(dum, "darkportal", GetUnitX(dead), GetUnitY(dead))
            call UnitApplyTimedLife(dum, 'BTLF', 3.00)
            set Killer = null
            set dum = null
            set dead = null
        endif
        if GetUnitAbilityLevel(GetKillingUnit(), 'B01A' )>0 and GetRandomInt(1, 100) <= AAchance then
            set AAchance = 10
            set dum = CreateUnit(GetOwningPlayer(Killer), 'h01H', GetUnitX(dead), GetUnitY(dead), 0.00)
            call UnitAddAbility(dum, 'A04V')
            call SetUnitAbilityLevel(dum, 'A04V', 2)
            call IssuePointOrder(dum, "darkportal", GetUnitX(dead), GetUnitY(dead))
            call UnitApplyTimedLife(dum, 'BTLF', 3.00)
            set Killer = null
            set dum = null
            set dead = null
        endif
        if GetUnitAbilityLevel(GetKillingUnit(), 'B01B' )>0 and GetRandomInt(1, 100) <= AAchance then
            set AAchance = 15
            set dum = CreateUnit(GetOwningPlayer(Killer), 'h01H', GetUnitX(dead), GetUnitY(dead), 0.00)
            call UnitAddAbility(dum, 'A04V')
            call SetUnitAbilityLevel(dum, 'A04V', 2)
            call IssuePointOrder(dum, "darkportal", GetUnitX(dead), GetUnitY(dead))
            call UnitApplyTimedLife(dum, 'BTLF', 3.00)
            set Killer = null
            set dum = null
            set dead = null
        endif
    endfunction
    //===========================================================================
    function InitTrig_Animal_Aura takes nothing returns nothing
        local trigger AnimalAura = CreateTrigger(  )
        local integer index = 0
        loop
            exitwhen index == 16
            call TriggerRegisterPlayerUnitEvent(AnimalAura, Player(index), EVENT_PLAYER_UNIT_DEATH, null)
            set index = index +1
        endloop
        call TriggerAddAction( AnimalAura, function AnimalAura_Acts )
        set AnimalAura = null
    endfunction


    does this work ??? i mean, i really am confused with the AAchance local because of the chances ... shouldn't i set the variable before the If ???
     
  19. PurplePoot

    PurplePoot

    Joined:
    Dec 14, 2005
    Messages:
    11,161
    Resources:
    3
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    Resources:
    3
    Put the handle vars in a .j script

    length = dist

    Also, you can find the angle between 2 positions with Atan2, if that's what you're asking there.
     
  20. HINDYhat

    HINDYhat

    Joined:
    Apr 22, 2007
    Messages:
    1,594
    Resources:
    3
    Maps:
    2
    Spells:
    1
    Resources:
    3
    Your spell doesn't work. It could say "Uninitialized variable" or something like that. You have to set AAChange before the ifs.

    Please STOP using local triggers!!!