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 18th Icon Contest is ON! Choose any ingame unit and give him/her Hero abilities. Good luck to all.
    Dismiss Notice
  4. The Secrets of Warcraft 3 have revealed interesting works. The RESULTS for Abelhawk's Mini-Mapping Contest #15 have come out!
    Dismiss Notice
  5. Contestants are to create a scene set in the Stone Age. Come and see what you can come up with. We wish you the best of luck!
    Dismiss Notice
  6. Colour outside the lines! Techtree Contest #13 is a go. The contest is optionally paired.
    Dismiss Notice
  7. Night Rider gained several songs for his journey. The poll for the 12th Music Contest has started. Check it out!
    Dismiss Notice
  8. Greetings cerebrates, our Swarm needs new spawners that will have numerous children. Join the HIVE's 31st Modeling Contest - Spawners and Spawned! The contest is optionally paired.
    Dismiss Notice
  9. Join other hivers in a friendly concept-art contest. The contestants have to create a genie coming out of its container. We wish you the best of luck!
    Dismiss Notice
  10. 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.

Zephyr Contest #11 - My aura, Your aura

Discussion in 'Contest Archive' started by Pharaoh_, Jul 1, 2014.

Thread Status:
Not open for further replies.
  1. Empirean

    Empirean

    Joined:
    Jun 20, 2014
    Messages:
    390
    Resources:
    8
    Spells:
    8
    Resources:
    8
    Thank you for your guidance.

    Ok heres my entry for the contest. This is also my first spell.

    Aura of Faith
    Emits an aura that heals nearby allied units whenever the bearer of the aura is attacked. Also allows you to force nearby enemy units to attack you for a duration.

    |cffffcc00Level 1|r - Heals nearby units based on 30% of the bearer's Strength
    |cffffcc00Level 2|r - Heals nearby units based on 60% of the bearer's Strength
    |cffffcc00Level 3|r - Heals nearby units based on 90% of the bearer's Strength
    |cffffcc00Level 4|r - Heals nearby units based on 120% of the bearer's Strength

    Area of Effect: 500
    Units that has this ability will not be healed by this aura.
     

    Attached Files:

    Last edited: Jul 5, 2014
  2. Pharaoh_

    Pharaoh_

    Joined:
    Nov 6, 2008
    Messages:
    8,127
    Resources:
    11
    Icons:
    3
    Skins:
    1
    Spells:
    6
    Tutorials:
    1
    Resources:
    11
    I think it sounds balanced enough, but that also depends on the damage bonus (remember, you will have 3 effects for one passive skill). You could increase the damage depending on how many enemy units are around (X for heroes, Y for regular units) and have the evasion and speed bonus static.
    As for the "targets stalked", this means that you will need to set a trigger that checks if the targeted unit (unit acquires a target or a damage detection system) is the unit that generated the Stalk buff (so that the damage bonus is removed upon switching target - or in the case you get taunted).
     
  3. Mythic

    Mythic

    Joined:
    Apr 24, 2012
    Messages:
    7,668
    Resources:
    101
    Models:
    86
    Icons:
    4
    Maps:
    3
    Spells:
    6
    Tutorials:
    2
    Resources:
    101
    I see, thanks for the tips.
     
  4. Zeatherann

    Zeatherann

    Joined:
    Nov 25, 2008
    Messages:
    1,303
    Resources:
    6
    Skins:
    1
    Tools:
    1
    Maps:
    4
    Resources:
    6
    While not needed, configurability would grant you more points in the coding aspect of the challenge. Back to my original question: Can I import my map script?
     
  5. Pharaoh_

    Pharaoh_

    Joined:
    Nov 6, 2008
    Messages:
    8,127
    Resources:
    11
    Icons:
    3
    Skins:
    1
    Spells:
    6
    Tutorials:
    1
    Resources:
    11
    Why do you need it, what does it contain?
     
  6. Kyrbi0

    Kyrbi0

    Joined:
    Jul 29, 2008
    Messages:
    7,768
    Resources:
    1
    Models:
    1
    Resources:
    1
    SallyAnna raises an important issue (and one which, to my disadvantage, I failed to bring up earlier), and it's one that I have raised for other, similar contests (esp. Hero & Techtree): What are we comparing these Aura's to?

    More below, but example here:

    If the answer is "in-game/existing/TFT/ladder/standard Auras", then SallyAnna's is perfect & RulerOfIron's & TankCommander's might be a little too good, too advanced (not quite sure, waiting to see full implementation).

    On the contrary, if the answer is not "in-game/existing/TFT/ladder/standard Auras", then SallyAnna is correct; his submission might easily be considered "too simple" (and conversely, RoI & TC have the right idea).
    Now, an argument can be made here that, as simple as all the Auras in-game are, it'd be a pretty boring contest... // Also an argument can be made that a "Zephyr" contest is as much about Coding as it is about Ideas, in which case a true "challenge" (contest) should end up with something complex enough to be a challenge to make, thus = somewhat more complex than 'in-game Auras'...

    But that being said, which is it? And in the future, let's definitely make sure this is well-defined from the start. Saying "balance it according to in-game stuff" isn't quite enough; "balance" has part to do with "how over-/under-powered it is", but also has to do with "how simple/complex is it, comparatively"? Even stretching the definition of Aura as we have (to include Toggled Auras & Active Auras & DD Auras & such), their really not all the complex.

    ~~~

    Let me be clear, though; I mean no ill will towards RoI's or TC's entries. Both are pretty snazzy-lookin' and I'm glad someone is cranking stuff out early. :p
     
    Last edited: Jul 2, 2014
  7. rulerofiron99

    rulerofiron99

    Joined:
    Jul 10, 2006
    Messages:
    3,129
    Resources:
    14
    Maps:
    4
    Spells:
    9
    Tutorials:
    1
    Resources:
    14
    @Kyrbi0
    No ill will detected :)

    I think the judging criteria answers your issue:

    A bland vanilla-ish aura will score low on uniqueness, and lose a few points on coding for limited configurables.

    With these criteria, the emphasis is on making a unique and good-looking spell that has no bugs. Balance isn't listed.

    The requirement in this contest is simply to make an aura, so any aura, no matter how complex or how bland, is acceptable for the contest.

    Anyway, progress report:
    All the functions have been implemented and seem to work. I'm going to test it further in a game against bots.

    There is still a lot of room for improvement with my spell in terms of efficiency; since it's currently checking unit groups and spell levels in the main loop (0.03 sec).
     
  8. Zeatherann

    Zeatherann

    Joined:
    Nov 25, 2008
    Messages:
    1,303
    Resources:
    6
    Skins:
    1
    Tools:
    1
    Maps:
    4
    Resources:
    6
    It just makes it a whole lot quicker and simpler to code.
     
  9. Pharaoh_

    Pharaoh_

    Joined:
    Nov 6, 2008
    Messages:
    8,127
    Resources:
    11
    Icons:
    3
    Skins:
    1
    Spells:
    6
    Tutorials:
    1
    Resources:
    11
    Adding natives is like using WEU, which is not supported. Use custom functions or libraries to make it easier to code. If it can be opened in the regular editor, however, then it's fine.
     
  10. Mythic

    Mythic

    Joined:
    Apr 24, 2012
    Messages:
    7,668
    Resources:
    101
    Models:
    86
    Icons:
    4
    Maps:
    3
    Spells:
    6
    Tutorials:
    2
    Resources:
    101
    How about mine? Is mine around the middle of simplicity and complexity?
     
  11. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,855
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    in fact, there are plenty natives that you can get your hands on using JNGP.

    Here is the entire list:

    http://jass.sourceforge.net/doc/api/common_ai-functions.shtml

    the most notable are
    GetUnitGold/WoodCost
    and
    UnitAlive


    they are all in the file that game has access to, but for some reason world editor doesnt. However, you can forward declare the natives even if they are not in the common.j or blizzard.j(like the ones from common.ai)

    You would have to ban quite a few resources if you wanted to make natives undeclarable. Many resources use
    UnitAlive
     
  12. Zeatherann

    Zeatherann

    Joined:
    Nov 25, 2008
    Messages:
    1,303
    Resources:
    6
    Skins:
    1
    Tools:
    1
    Maps:
    4
    Resources:
    6
    Well, since the script is imported with the import editor, the map can be opened and saved.
     
  13. Pharaoh_

    Pharaoh_

    Joined:
    Nov 6, 2008
    Messages:
    8,127
    Resources:
    11
    Icons:
    3
    Skins:
    1
    Spells:
    6
    Tutorials:
    1
    Resources:
    11
    I am kind of torn here. However, I feel that you are taking too much advantage of utilities. You're already allowed to use any kind of system (unlike the first Zephyr contests), which is something I changed :)goblin_yeah:) and it is more than enough. It's just a spell!
     
  14. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,855
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    I think he means writing the code outside of the editor and importing it, like if I had library in folder in JNGP and used
    //! import "myScript.j"
    . You dont get new natives or anything, you just get the possibility to create it outside of the world editor
     
  15. Zeatherann

    Zeatherann

    Joined:
    Nov 25, 2008
    Messages:
    1,303
    Resources:
    6
    Skins:
    1
    Tools:
    1
    Maps:
    4
    Resources:
    6
    It's still coded in pure, normal, vanilla, plain old JASS. Imports are listed as allowed...
     
  16. Mythic

    Mythic

    Joined:
    Apr 24, 2012
    Messages:
    7,668
    Resources:
    101
    Models:
    86
    Icons:
    4
    Maps:
    3
    Spells:
    6
    Tutorials:
    2
    Resources:
    101
    Version 2, tooltip;

    I scrapped the evasion feeling life steal + evasion combo was too much. How is the spell as an ultimate right now? Underpowered?
     

    Attached Files:

  17. BlueSaint

    BlueSaint

    Joined:
    Jun 18, 2012
    Messages:
    2,772
    Resources:
    3
    Tools:
    1
    Spells:
    2
    Resources:
    3
    This means no vJASS? (I just read the OP if you've already discussed about this I'm sorry, but there's 4 pages..)
     
  18. Pharaoh_

    Pharaoh_

    Joined:
    Nov 6, 2008
    Messages:
    8,127
    Resources:
    11
    Icons:
    3
    Skins:
    1
    Spells:
    6
    Tutorials:
    1
    Resources:
    11
    No, we don't discuss something that is obvious; Jass includes vJass :)
     
  19. BlueSaint

    BlueSaint

    Joined:
    Jun 18, 2012
    Messages:
    2,772
    Resources:
    3
    Tools:
    1
    Spells:
    2
    Resources:
    3
    mk, then if I assume right that I can use Table by Bribe, PUI and TimerUtils,
    you can count me in
     
  20. Tank-Commander

    Tank-Commander

    Spell Reviewer

    Joined:
    May 26, 2009
    Messages:
    1,543
    Resources:
    44
    Packs:
    1
    Spells:
    41
    Tutorials:
    2
    Resources:
    44
    Just posting code listing WIP, move along

    Code

    Code (vJASS):

    ///////////////////////////////////////////////////////////////////
    //  Configuration                                                //
    ///////////////////////////////////////////////////////////////////
    constant function STA_AbilityID takes nothing returns integer
        return 'A000'
    endfunction

    constant function STA_DummyID takes nothing returns integer
        return 'u000'
    endfunction

    constant function STA_TimerRate takes nothing returns real
        return 0.03125
    endfunction

    constant function STA_DummyRemovalDelay takes nothing returns real
        return 2.
    endfunction

    constant function STA_EffectReductionDelay takes nothing returns real
        return 0.5
    endfunction

    constant function STA_AuraEffect takes nothing returns string
        return "Abilities\\Spells\\Undead\\RegenerationAura\\ObsidianRegenAura.mdl"
    endfunction

    constant function STA_SoulFragmentEffect takes nothing returns string
        return "Abilities\\Spells\\Undead\\Curse\\CurseTarget.mdl"
    endfunction

    constant function STA_SoulFragmentProjectileEffect takes nothing returns string
        return "Abilities\\Spells\\Undead\\Possession\\PossessionMissile.mdl"
    endfunction

    constant function STA_InitialDamageEffect takes nothing returns string
        return "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
    endfunction

    constant function STA_DeathDamageEffect takes nothing returns string
        return "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
    endfunction

    constant function STA_BonusDamageEffect takes nothing returns string
        return "Abilities\\Spells\\Items\\AIil\\AIilTarget.mdl"
    endfunction

    constant function STA_HealEffect takes nothing returns string
        return "Abilities\\Spells\\Human\\DispelMagic\\DispelMagicTarget.mdl"
    endfunction

    constant function STA_AuraAttachmentPoint takes nothing returns string
        return "origin"
    endfunction

    constant function STA_SoulFragmentAttachmentPoint takes nothing returns string
        return "overhead"
    endfunction

    constant function STA_SoulFragmentProjectileAttachmentPoint takes nothing returns string
        return "chest"
    endfunction

    constant function STA_InitialDamageAttachmentPoint takes nothing returns string
        return "chest"
    endfunction

    constant function STA_DeathDamageAttachmentPoint takes nothing returns string
        return "chest"
    endfunction

    constant function STA_BonusDamageAttachmentPoint takes nothing returns string
        return "chest"
    endfunction

    constant function STA_HealEffectAttachmentPoint takes nothing returns string
        return "chest"
    endfunction

    constant function STA_SoulFragmentProjectileScaleBase takes nothing returns real
        return .9
    endfunction

    constant function STA_SoulFragmentProjectileScalePerLevel takes nothing returns real
        return .05
    endfunction

    constant function STA_AOEBase takes nothing returns real
        return 400.
    endfunction

    constant function STA_AOEPerLevel takes nothing returns real
        return 100.
    endfunction

    constant function STA_SearchAOEBase takes nothing returns real
        return 100.
    endfunction

    constant function STA_SearchAOEPerLevel takes nothing returns real
        return 90.
    endfunction

    constant function STA_ImpactAOEBase takes nothing returns real
        return 100.
    endfunction

    constant function STA_ImpactAOEPerLevel takes nothing returns real
        return 0.
    endfunction

    constant function STA_SoulFragmentProjectileSpeedBase takes nothing returns real
        return 9.
    endfunction

    constant function STA_SoulFragmentProjectileSpeedPerLevel takes nothing returns real
        return 6.
    endfunction

    constant function STA_SoulFragmentProjectileHitTimeBase takes nothing returns real
        return 2.
    endfunction

    constant function STA_SoulFragmentProjectileHitTimePerLevel takes nothing returns real
        return -0.3
    endfunction

    constant function STA_SoulFragmentMovementType takes nothing returns boolean
        return false
    endfunction

    constant function STA_SoulFragmentHeightStartOffset takes nothing returns real
        return 90.
    endfunction

    constant function STA_SoulFragmentHeightEndOffset takes nothing returns real
        return 45.
    endfunction

    constant function STA_InitialEffectHealthDamageBase takes nothing returns real
        return 25.
    endfunction

    constant function STA_InitialEffectHealthDamagePerLevel takes nothing returns real
        return 10.
    endfunction

    constant function STA_InitialEffectManaDamageBase takes nothing returns real
        return 0.
    endfunction

    constant function STA_InitialEffectManaDamagePerLevel takes nothing returns real
        return 0.
    endfunction

    constant function STA_DeathHealthDamageBase takes nothing returns real
        return 50.
    endfunction

    constant function STA_DeathHealthDamagePerLevel takes nothing returns real
        return 25.
    endfunction

    constant function STA_DeathManaDamageBase takes nothing returns real
        return 0.
    endfunction

    constant function STA_DeathManaDamagePerLevel takes nothing returns real
        return 0.
    endfunction

    constant function STA_BonusHealthDamagePercentBase takes nothing returns real
        return 0.1
    endfunction

    constant function STA_BonusHealthDamagePercentPerLevel takes nothing returns real
        return 0.05
    endfunction

    constant function STA_BonusManaDamagePercentBase takes nothing returns real
        return 0.
    endfunction

    constant function STA_BonusManaDamagePercentPerLevel takes nothing returns real
        return 0.
    endfunction

    constant function STA_HeroHealthHealBase takes nothing returns real
        return 100.
    endfunction

    constant function STA_HeroHealthHealPerLevel takes nothing returns real
        return 50.
    endfunction

    constant function STA_HeroManaHealBase takes nothing returns real
        return 0.
    endfunction

    constant function STA_HeroManaHealPerLevel takes nothing returns real
        return 0.
    endfunction

    constant function STA_AttackType takes nothing returns attacktype
        return ATTACK_TYPE_MAGIC
    endfunction

    constant function STA_DamageType takes nothing returns damagetype
        return DAMAGE_TYPE_MAGIC
    endfunction

    constant function STA_WeaponType takes nothing returns weapontype
        return null
    endfunction

    constant function STA_CollisionSize takes nothing returns real
        return 50.
    endfunction
    ///////////////////////////////////////////////////////////////////
    //  This marks the end of the configuration section, it is not   //
    //  recommended to go beyond this point unless you know what     //
    //  you are doing and have programming experience yourself       //
    ///////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////
    //  Function used to get the z height of locations needed by the //
    //  spell, since it can only be done with locations, this one    //
    //  is reused throughout, instead of creating/destroying them    //
    ///////////////////////////////////////////////////////////////////
    function STA_GetZ takes real x, real y returns real

        //Gets the location Z of the selected location
        call MoveLocation(udg_STA_ZLoc, x, y)
        return GetLocationZ(udg_STA_ZLoc)
       
    endfunction

    ///////////////////////////////////////////////////////////////////
    //  Function used to recycle instances, so that they can used    //
    //  again later, keeping the total array sizes smaller           //
    ///////////////////////////////////////////////////////////////////
    function STA_Recycle takes integer Node, timer T returns nothing
               
            if (udg_STA_LastNode == Node) then
                set udg_STA_LastNode = udg_STA_PrevNode[Node]
            endif
               
            //Recycles the node
            set udg_STA_RecycleNodes[udg_STA_RecyclableNodes] = Node
            set udg_STA_RecyclableNodes = udg_STA_RecyclableNodes + 1
            set udg_STA_NextNode[udg_STA_PrevNode[Node]] = udg_STA_NextNode[Node]
            set udg_STA_PrevNode[udg_STA_NextNode[Node]] = udg_STA_PrevNode[Node]
            set udg_STA_AbilityCounter = udg_STA_AbilityCounter - 1

            if (udg_STA_AbilityCounter == 0) then
                call DestroyTimer(T)
            endif

    endfunction

    ////////////////////////////////////////////////////////////////////
    //  Target filter function - passed units and players and checks  //
    //  if the unit is allowed to be targetted by this ability        //
    ////////////////////////////////////////////////////////////////////
    function STA_TargetFilter takes unit u, player pl returns boolean

        //Checks if the unit can be used as a target
        if (not IsUnitType(u, UNIT_TYPE_STRUCTURE)) and (not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)) and (IsUnitEnemy(u, pl)) and (GetUnitTypeId(u) != STA_DummyID()) and (not IsUnitType(u, UNIT_TYPE_DEAD)) then
            return true
        endif
       
        return false

    endfunction

    ///////////////////////////////////////////////////////////////////
    //  This function handles the damage dealt to units by the       //
    //  projectiles, including health and mana in one function,      //
    //  since both forms of projectile use the same damage method    //
    ///////////////////////////////////////////////////////////////////
    function STA_SoulProjectileDamage takes integer Node returns nothing
         //Declare Locals
        local real x = GetUnitX(udg_STA_Unit[Node])
        local real y = GetUnitY(udg_STA_Unit[Node])
        local unit u
        local player pl = GetOwningPlayer(udg_STA_Caster[Node])

        call GroupEnumUnitsInRange(udg_STA_TempGroup, x, y, udg_STA_ImpactAOE[udg_STA_CasterNode[Node]], null)
        set pl = GetOwningPlayer(udg_STA_Caster[Node])
                   
        loop
           //Scanning through
           set u = FirstOfGroup(udg_STA_TempGroup)
           exitwhen u == null
                               
           //Select all the units which are to be damaged
           if (STA_TargetFilter(u, pl)) then
                call UnitDamageTarget(udg_STA_Caster[Node], u, udg_STA_HealthDamage[Node], false, false, STA_AttackType(), STA_DamageType(), STA_WeaponType())
                call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MANA) - udg_STA_ManaDamage[Node])
           endif

           //Remove the unit from the unit group
           call GroupRemoveUnit(udg_STA_TempGroup, u)
        endloop
       
        //Null variables
        set pl = null
    endfunction

    ///////////////////////////////////////////////////////////////////
    //  Function used to create each projectile and set up all the   //
    //  information they need to run, since both the caster and the  //
    //  affected units can produce these projectiles                 //
    ///////////////////////////////////////////////////////////////////
    function STA_CreateProjectile takes real x, real y, real z, real zSpeed, real Speed, real Angle, real Distance, real HealthDamage, real ManaDamage, integer Node, boolean Type, integer Target returns nothing
        local integer TempNode
       
        set udg_STA_AbilityCounter = udg_STA_AbilityCounter + 1
       
        //Checking for recycleable Nodes
        if (udg_STA_RecyclableNodes == 0) then
            set udg_STA_NodeNumber = udg_STA_NodeNumber + 1
            set TempNode = udg_STA_NodeNumber
        else
            set udg_STA_RecyclableNodes = udg_STA_RecyclableNodes - 1
            set TempNode = udg_STA_RecycleNodes[udg_STA_RecyclableNodes]
        endif

        set udg_STA_NextNode[TempNode] = 0
        set udg_STA_NextNode[udg_STA_LastNode] = TempNode
        set udg_STA_PrevNode[TempNode] = udg_STA_LastNode
        set udg_STA_LastNode = TempNode
        set udg_STA_Caster[TempNode] = udg_STA_Caster[Node]
        set udg_STA_CasterNode[TempNode] = udg_STA_CasterNode[Node]
       
        set udg_STA_Unit[TempNode] = CreateUnit(Player(14), STA_DummyID(), x, y, Angle)
        if UnitAddAbility(udg_STA_Unit[TempNode], 'Amrf') and UnitRemoveAbility(udg_STA_Unit[TempNode], 'Amrf') then
        endif
        set udg_STA_CurrentEffect[TempNode] = AddSpecialEffectTarget(STA_SoulFragmentProjectileEffect(), udg_STA_Unit[TempNode], STA_SoulFragmentProjectileAttachmentPoint())
        call SetUnitScale(udg_STA_Unit[TempNode], udg_STA_SoulFragmentScale[Node],0.,0.)
        call SetUnitFlyHeight(udg_STA_Unit[TempNode], z, 0)
       
        set udg_STA_StageID[TempNode] = 3
        set udg_STA_ZSpeed[TempNode] = zSpeed
        set udg_STA_Speed[TempNode] = Speed
        set udg_STA_HealthDamage[TempNode] = HealthDamage
        set udg_STA_ManaDamage[TempNode] = ManaDamage
        set udg_STA_FragmentType[TempNode] = Type
       
        set udg_STA_DistanceTravelled[TempNode] = 0.
       
        if (Type == true) then
            set udg_STA_Target[TempNode] = udg_STA_Unit[Target]
            set udg_STA_TargetID[TempNode] = Target
        else
            set udg_STA_MaxDistance[TempNode] = Distance
            set udg_STA_TargetID[TempNode] = 0
            set udg_STA_Target[TempNode] = null
        endif
       
    endfunction
    ///////////////////////////////////////////////////////////////////
    //  Function used to update the stats for Heros generating the   //
    //  aura, so that level ups are in effect instantly              //
    ///////////////////////////////////////////////////////////////////
    function STA_UpdateAura takes integer Node returns nothing

        set udg_STA_SoulFragmentScale[Node] = STA_SoulFragmentProjectileScaleBase() + (STA_SoulFragmentProjectileScalePerLevel() * udg_STA_Level[Node])
        set udg_STA_AOE[Node] = STA_AOEBase() + (STA_AOEPerLevel() * udg_STA_Level[Node])
        set udg_STA_SearchAOE[Node] = STA_SearchAOEBase() + (STA_SearchAOEPerLevel() * udg_STA_Level[Node])
        set udg_STA_ImpactAOE[Node] = STA_ImpactAOEBase() + (STA_ImpactAOEPerLevel() * udg_STA_Level[Node])
        set udg_STA_SoulProjectileSpeed[Node] = STA_SoulFragmentProjectileSpeedBase() + (STA_SoulFragmentProjectileSpeedPerLevel() * udg_STA_Level[Node])
        set udg_STA_SoulProjectileHitTime[Node] = STA_SoulFragmentProjectileHitTimeBase() + (STA_SoulFragmentProjectileHitTimePerLevel() * udg_STA_Level[Node])
        set udg_STA_InitialEffectHealthDamage[Node] = STA_InitialEffectHealthDamageBase() + (STA_InitialEffectHealthDamagePerLevel() * udg_STA_Level[Node])
        set udg_STA_InitialEffectManaDamage[Node] = STA_InitialEffectManaDamageBase() + (STA_InitialEffectManaDamagePerLevel() * udg_STA_Level[Node])
        set udg_STA_DeathHealthDamage[Node] = STA_DeathHealthDamageBase() + (STA_DeathHealthDamagePerLevel() * udg_STA_Level[Node])
        set udg_STA_DeathManaDamage[Node] = STA_DeathManaDamageBase() + (STA_DeathManaDamagePerLevel() * udg_STA_Level[Node])
        set udg_STA_BonusHealthDamagePercent[Node] = STA_BonusHealthDamagePercentBase() + (STA_BonusHealthDamagePercentPerLevel() * udg_STA_Level[Node])
        set udg_STA_BonusManaDamagePercent[Node] = STA_BonusManaDamagePercentBase() + (STA_BonusManaDamagePercentPerLevel() * udg_STA_Level[Node])
        set udg_STA_HeroHealthHeal[Node] = STA_HeroHealthHealBase() + (STA_HeroHealthHealPerLevel() * udg_STA_Level[Node])
        set udg_STA_HeroManaHeal[Node] = STA_HeroManaHealBase() + (STA_HeroManaHealPerLevel() * udg_STA_Level[Node])
       
    endfunction

    ///////////////////////////////////////////////////////////////////
    //  The main loop function of the spell, it handles the main     //
    //  operations of the ability such as assigning new units,       //
    //  moving projectiles and dealing bonus damage to units         //
    ///////////////////////////////////////////////////////////////////
    function STA_Loop takes nothing returns nothing
        //Declare Locals
        local integer Node = 0
        local integer TempNode = 0
        local integer TempInt = 0
        local integer TempInt2 = 0
        local real TempReal
        local real TempReal2
        local real TempReal3
        local real x
        local real y
        local real x2
        local real y2
        local real z
        local real z2
        local real Angle
        local unit u
        local player pl
       
        loop
            //Moves to the next node
            set TempInt = TempInt + 1
            exitwhen TempInt > udg_STA_AbilityCounter
            set Node = udg_STA_NextNode[Node]

            if (udg_STA_StageID[Node] == 3) then
                set x = GetUnitX(udg_STA_Unit[Node])
                set y = GetUnitY(udg_STA_Unit[Node])
                           
                call SetUnitX(udg_STA_Unit[Node], x + udg_STA_Speed[Node] * Cos(GetUnitFacing(udg_STA_Unit[Node]) * bj_DEGTORAD))
                call SetUnitY(udg_STA_Unit[Node], y + udg_STA_Speed[Node] * Sin(GetUnitFacing(udg_STA_Unit[Node]) * bj_DEGTORAD))
                call SetUnitFlyHeight(udg_STA_Unit[Node], GetUnitFlyHeight(udg_STA_Unit[Node]) + udg_STA_ZSpeed[Node], 0.)
                set udg_STA_DistanceTravelled[Node] = udg_STA_DistanceTravelled[Node] + udg_STA_Speed[Node]

                if (udg_STA_FragmentType[Node] == true) then
               
                    set x2 = GetUnitX(udg_STA_Target[Node])
                    set y2 = GetUnitY(udg_STA_Target[Node])
                    set TempReal = SquareRoot(Pow(x - x2, 2) + Pow(y - y2, 2))
                   
                    if (TempReal > STA_CollisionSize()) then
                        set Angle = Atan2(y2 - y, x2 - x)
                        call SetUnitFacing(udg_STA_Unit[Node], bj_RADTODEG * Angle)

                        set z = STA_GetZ(x,y) + GetUnitFlyHeight(udg_STA_Unit[Node])
                        set z2 = STA_GetZ(x2, y2) + GetUnitFlyHeight(udg_STA_Target[Node]) + STA_SoulFragmentHeightEndOffset()
                       
                        //Calculate Speed
                        if (STA_SoulFragmentMovementType() == true) then
                            set udg_STA_Speed[Node] = (TempReal + udg_STA_DistanceTravelled[Node] / udg_STA_SoulProjectileHitTime[udg_STA_CasterNode[Node]]) * STA_TimerRate()
                        endif
                       
                        set udg_STA_ZSpeed[Node] = (z2 - z) / (TempReal / udg_STA_Speed[Node])
                    else
                        set udg_STA_Disabled[udg_STA_TargetID[Node]] = false
                        call STA_SoulProjectileDamage(Node)
                        set udg_STA_StageID[Node] = 4
                        call DestroyEffect(udg_STA_CurrentEffect[Node])
                        call DestroyEffect(AddSpecialEffectTarget(STA_InitialDamageEffect(), udg_STA_Unit[Node], STA_InitialDamageAttachmentPoint()))
                    endif
                elseif (udg_STA_DistanceTravelled[Node] >= udg_STA_MaxDistance[Node]) then
                    call STA_SoulProjectileDamage(Node)
                    set udg_STA_StageID[Node] = 4
                    call DestroyEffect(udg_STA_CurrentEffect[Node])
                    call DestroyEffect(AddSpecialEffectTarget(STA_DeathDamageEffect(), udg_STA_Unit[Node], STA_DeathDamageAttachmentPoint()))
                endif
                   

               
            elseif (udg_STA_StageID[Node] == 2) and (udg_STA_Disabled[Node] == false) then
                set TempReal = GetUnitState(udg_STA_Unit[Node], UNIT_STATE_LIFE)
                set TempReal2 = GetUnitState(udg_STA_Unit[Node], UNIT_STATE_MANA)
                set udg_STA_EffectDelayTimer[Node] = udg_STA_EffectDelayTimer[Node] + STA_TimerRate()

                if (TempReal < udg_STA_CurrentHealth[Node]) or (TempReal2 < udg_STA_CurrentMana[Node]) then
               
                    if (udg_STA_EffectDelayTimer[Node] >= STA_EffectReductionDelay()) then
                        set udg_STA_EffectDelayTimer[Node] = 0.
                        call DestroyEffect(AddSpecialEffectTarget(STA_BonusDamageEffect(), udg_STA_Unit[Node], STA_BonusDamageAttachmentPoint()))
                    endif
                   
                    if (TempReal < udg_STA_CurrentHealth[Node]) then
                        set TempReal = (udg_STA_CurrentHealth[Node] - TempReal) * udg_STA_BonusHealthDamagePercent[udg_STA_CasterNode[Node]]
                        call UnitDamageTarget(udg_STA_Caster[Node], udg_STA_Unit[Node], TempReal, false, false, STA_AttackType(), STA_DamageType(), STA_WeaponType())
                        set udg_STA_CurrentHealth[Node] = GetUnitState(udg_STA_Unit[Node], UNIT_STATE_LIFE)
                    else
                        set TempReal2 = (udg_STA_CurrentMana[Node] - TempReal2) * udg_STA_BonusManaDamagePercent[udg_STA_CasterNode[Node]]
                        call SetUnitState(udg_STA_Unit[Node], UNIT_STATE_MANA, TempReal2)
                    endif
                   
                endif
               
                set x = GetUnitX(udg_STA_Unit[Node])
                set y = GetUnitY(udg_STA_Unit[Node])
                set x2 = GetUnitX(udg_STA_Caster[Node])
                set y2 = GetUnitY(udg_STA_Caster[Node])
                set TempReal = SquareRoot(Pow(x - x2, 2) + Pow(y - y2, 2))
               
                if (TempReal > udg_STA_AOE[udg_STA_CasterNode[Node]]) then
                    call DestroyEffect(udg_STA_CurrentEffect[Node])
                    call GroupRemoveUnit(udg_STA_AffectedUnits,udg_STA_Unit[Node])
                    call STA_Recycle(Node, GetExpiredTimer())
                    set TempInt = TempInt - 1
               
                else
               
                    if (IsUnitType(udg_STA_Unit[Node], UNIT_TYPE_DEAD)) then
                   
                        set TempInt2 = 0
                        set TempNode = 0

                        loop
                            //Moves to the next node
                            set TempInt2 = TempInt2 + 1
                            exitwhen TempInt2 > udg_STA_AbilityCounter
                            set TempNode = udg_STA_NextNode[TempNode]
                           
                            if (udg_STA_Target[TempNode] == udg_STA_Unit[Node]) and (udg_STA_StageID[TempNode] == 3) then
                                call DestroyEffect(udg_STA_CurrentEffect[TempNode])
                                call DestroyEffect(AddSpecialEffectTarget(STA_DeathDamageEffect(), udg_STA_Unit[TempNode], STA_DeathDamageAttachmentPoint()))
                                set udg_STA_StageID[TempNode] = 4
                            endif

                        endloop
                        call GroupEnumUnitsInRange(udg_STA_TempGroup, x, y, udg_STA_SearchAOE[udg_STA_CasterNode[Node]], null)
                        set pl = GetOwningPlayer(udg_STA_Caster[Node])
                       
                        loop
                            //Scanning through
                            set u = FirstOfGroup(udg_STA_TempGroup)
                            exitwhen u == null
                                   
                            //Select all the units which are to be damaged
                            if (STA_TargetFilter(u, pl)) and (IsUnitInGroup(u, udg_STA_AffectedUnits)) then
                                //Set up data for the Soul Fragment Projectile
                                set x2 = GetUnitX(u)
                                set y2 = GetUnitY(u)
                                set z = STA_GetZ(x,y) + GetUnitFlyHeight(udg_STA_Unit[Node]) + STA_SoulFragmentHeightStartOffset()
                                set z2 = STA_GetZ(x2, y2) + GetUnitFlyHeight(u) + STA_SoulFragmentHeightEndOffset()
                                set TempReal = SquareRoot(Pow(x - x2, 2) + Pow(y - y2, 2))
                               
                                //Calculate Speed
                                if (STA_SoulFragmentMovementType() == true) then
                                    set TempReal2 = (TempReal / udg_STA_SoulProjectileHitTime[udg_STA_CasterNode[Node]]) * STA_TimerRate()
                                else
                                    set TempReal2 = udg_STA_SoulProjectileSpeed[udg_STA_CasterNode[Node]]
                                endif
                               
                                set TempReal3 = (z2 - z) / (TempReal / TempReal2)
                                set Angle = bj_RADTODEG * Atan2(y2 - y, x2 - x)

                                //Create Projectile
                                call STA_CreateProjectile(x, y, z, TempReal3, TempReal2, Angle, TempReal, udg_STA_DeathHealthDamage[udg_STA_CasterNode[Node]], udg_STA_DeathManaDamage[udg_STA_CasterNode[Node]], udg_STA_CasterNode[Node], false, 0)
                            endif

                            //Remove the unit from the unit group
                            call GroupRemoveUnit(udg_STA_TempGroup, u)
                        endloop

                        call DestroyEffect(udg_STA_CurrentEffect[Node])
                        call GroupRemoveUnit(udg_STA_AffectedUnits,udg_STA_Unit[Node])
                        call STA_Recycle(Node, GetExpiredTimer())
                        set TempInt = TempInt - 1
                       
                        //Null variables
                        set pl = null
                    endif

                endif

            elseif (udg_STA_StageID[Node] == 1) then
           
                if (IsUnitType(udg_STA_Caster[Node], UNIT_TYPE_DEAD)) then

                    set TempInt2 = 0
                    set TempNode = 0

                    loop
                        //Moves to the next node
                        set TempInt2 = TempInt2 + 1
                        exitwhen TempInt2 > udg_STA_AbilityCounter
                        set TempNode = udg_STA_NextNode[TempNode]
                       
                        if (udg_STA_Caster[TempNode] == udg_STA_Caster[Node]) then

                            if (udg_STA_StageID[TempNode] == 2) then
                                call DestroyEffect(AddSpecialEffectTarget(STA_HealEffect(), udg_STA_Unit[TempNode], STA_HealEffectAttachmentPoint()))
                                call SetUnitState(udg_STA_Unit[TempNode], UNIT_STATE_LIFE, GetUnitState(udg_STA_Unit[TempNode], UNIT_STATE_LIFE) + udg_STA_HeroHealthHeal[Node])
                                call SetUnitState(udg_STA_Unit[TempNode], UNIT_STATE_MANA, GetUnitState(udg_STA_Unit[TempNode], UNIT_STATE_MANA) + udg_STA_HeroManaHeal[Node])
                                call DestroyEffect(udg_STA_CurrentEffect[TempNode])
                                call GroupRemoveUnit(udg_STA_AffectedUnits,udg_STA_Unit[TempNode])
                                call STA_Recycle(TempNode, GetExpiredTimer())
                                set TempInt2 = TempInt2 - 1
                            elseif (udg_STA_StageID[TempNode] == 3) then
                                call DestroyEffect(udg_STA_CurrentEffect[TempNode])
                                call DestroyEffect(AddSpecialEffectTarget(STA_DeathDamageEffect(), udg_STA_Unit[TempNode], STA_DeathDamageAttachmentPoint()))
                                set udg_STA_StageID[TempNode] = 4
                            endif
                        endif

                    endloop
                   
                else
                    set TempReal = I2R(GetUnitAbilityLevel(udg_STA_Caster[Node], STA_AbilityID()))
                   
                    if (TempReal > udg_STA_Level[Node]) then
                        set udg_STA_Level[Node] = TempReal
                        call STA_UpdateAura(Node)
                    endif
                   
                    set x = GetUnitX(udg_STA_Caster[Node])
                    set y = GetUnitY(udg_STA_Caster[Node])
                    set pl = GetOwningPlayer(udg_STA_Caster[Node])
                    call GroupEnumUnitsInRange(udg_STA_TempGroup, x, y, udg_STA_AOE[Node], null)
                   
                    loop
                        //Scanning through
                        set u = FirstOfGroup(udg_STA_TempGroup)
                        exitwhen u == null
                               
                        //Select all the units which are to be damaged
                        if (STA_TargetFilter(u, pl)) and (not(IsUnitInGroup(u, udg_STA_AffectedUnits))) then
                           
                            //Prevent this unit from being selected again
                            call GroupAddUnit(udg_STA_AffectedUnits,u)
                               
                            set udg_STA_AbilityCounter = udg_STA_AbilityCounter + 1
                               
                            //Checking for recycleable Nodes
                            if (udg_STA_RecyclableNodes == 0) then
                                set udg_STA_NodeNumber = udg_STA_NodeNumber + 1
                                set TempNode = udg_STA_NodeNumber
                            else
                                set udg_STA_RecyclableNodes = udg_STA_RecyclableNodes - 1
                                set TempNode = udg_STA_RecycleNodes[udg_STA_RecyclableNodes]
                            endif

                            //Sets up this Node
                            set udg_STA_NextNode[TempNode] = 0
                            set udg_STA_NextNode[udg_STA_LastNode] = TempNode
                            set udg_STA_PrevNode[TempNode] = udg_STA_LastNode
                            set udg_STA_LastNode = TempNode
                            //Sets up data for this unit
                            set udg_STA_Caster[TempNode] = udg_STA_Caster[Node]
                            set udg_STA_CasterNode[TempNode] = Node
                            set udg_STA_Unit[TempNode] = u
                            set udg_STA_CurrentEffect[TempNode] = AddSpecialEffectTarget(STA_SoulFragmentEffect(), u, STA_SoulFragmentAttachmentPoint())
                            set udg_STA_Disabled[TempNode] = true
                            set udg_STA_StageID[TempNode] = 2
                            set udg_STA_CasterNode[TempNode] = Node
                            set udg_STA_CurrentHealth[TempNode] = GetUnitState(u, UNIT_STATE_LIFE)
                            set udg_STA_CurrentMana[TempNode] = GetUnitState(u, UNIT_STATE_MANA)
       
                            //Set up data for the Soul Fragment Projectile
                            set x2 = GetUnitX(u)
                            set y2 = GetUnitY(u)
                            set z = STA_GetZ(x,y) + GetUnitFlyHeight(udg_STA_Caster[Node]) + STA_SoulFragmentHeightStartOffset()
                            set z2 = STA_GetZ(x2, y2) + GetUnitFlyHeight(u) + STA_SoulFragmentHeightEndOffset()
                            set TempReal = SquareRoot(Pow(x - x2, 2) + Pow(y - y2, 2))
                               
                            //Calculate Speed
                            if (STA_SoulFragmentMovementType() == true) then
                                set TempReal2 = (TempReal / udg_STA_SoulProjectileHitTime[Node]) * STA_TimerRate()
                            else
                                set TempReal2 = udg_STA_SoulProjectileSpeed[Node]
                            endif
                               
                            set TempReal = (z2 - z) / (TempReal / TempReal2)
                            set Angle = bj_RADTODEG * Atan2(y2 - y, x2 - x)

                            //Create Projectile
                            call STA_CreateProjectile(x, y, z, TempReal, TempReal2, Angle, 0, udg_STA_InitialEffectHealthDamage[Node], udg_STA_InitialEffectManaDamage[Node], Node, true, TempNode)
                           
                        endif
                        //Remove the unit from the unit group
                        call GroupRemoveUnit(udg_STA_TempGroup, u)
                               
                    endloop
                   
                    //Null variables
                    set pl = null
                endif
               
            elseif (udg_STA_StageID[Node] == 4) and (udg_STA_CurrentDeathTimer[Node] >= STA_DummyRemovalDelay()) then
                set udg_STA_CurrentDeathTimer[Node] = 0.00
               
                //Removes the projectile
                call RemoveUnit(udg_STA_Unit[Node])
                call STA_Recycle(Node, GetExpiredTimer())
                set TempInt = TempInt - 1
           
            else
                set udg_STA_CurrentDeathTimer[Node] = udg_STA_CurrentDeathTimer[Node] + STA_TimerRate()
            endif
           
        endloop
       
    endfunction

    ///////////////////////////////////////////////////////////////////
    //  Caster assignment function, when a new unit fits any         //
    //  requirement to become a caster, this function is called      //
    //  passing the unit to add, the system then checks if the       //
    //  caster already exists in the system (this is for if they     //
    //  meet multiple requirements to call the function) in order    //
    //  to prevent dubplications of information                      //
    ///////////////////////////////////////////////////////////////////
    function STA_NewAura takes nothing returns boolean
        //Set up locals
        local integer TempInt = 0
        local integer Node = 0
        local boolean scan = false
        local unit u
       
        if (GetLearnedSkill() == STA_AbilityID()) then
            set u = GetTriggerUnit()

            loop
                //Moves to the next node
                set TempInt = TempInt + 1
                exitwhen TempInt > udg_STA_AbilityCounter
                set Node = udg_STA_NextNode[Node]
           
                if (u == udg_STA_Caster[Node]) then
                    set scan = true
                endif

            endloop

            if (scan == false) then
                set udg_STA_AbilityCounter = udg_STA_AbilityCounter + 1
               
                //Checking for recycleable Nodes
                if (udg_STA_RecyclableNodes == 0) then
                    set udg_STA_NodeNumber = udg_STA_NodeNumber + 1
                    set Node = udg_STA_NodeNumber
                else
                    set udg_STA_RecyclableNodes = udg_STA_RecyclableNodes - 1
                    set Node = udg_STA_RecycleNodes[udg_STA_RecyclableNodes]
                endif

                //Sets up this Node
                set udg_STA_NextNode[Node] = 0
                set udg_STA_NextNode[udg_STA_LastNode] = Node
                set udg_STA_PrevNode[Node] = udg_STA_LastNode
                set udg_STA_LastNode = Node
               
                //Set up the data needed for the Aura
                set udg_STA_Level[Node] = I2R(GetUnitAbilityLevel(u, STA_AbilityID()))
                set udg_STA_StageID[Node] = 1
                set udg_STA_Caster[Node] = u
                set udg_STA_CasterNode[Node] = Node
                set udg_STA_CurrentEffect[Node] = AddSpecialEffectTarget(STA_AuraEffect(), u, STA_AuraAttachmentPoint())

                call STA_UpdateAura(Node)
               
                //Applies timer if this is the only instance of the aura
                if (udg_STA_AbilityCounter == 1) then
                    call TimerStart(CreateTimer(), STA_TimerRate(), true, function STA_Loop)
                endif
           
            endif

            //Null variables
            set u = null  
        endif

        return false

    endfunction

    ///////////////////////////////////////////////////////////////////
    //  Initialisation trigger, applies the conditions to triggers   //
    //  and sets up the global location used to get location Z's     //
    ///////////////////////////////////////////////////////////////////
    function InitTrig_Soul_Tear_Aura takes nothing returns nothing
        //Set up locals
        local trigger STA
        local integer index = 0
       
        set STA = CreateTrigger()

        //Initialise the event for every player
        loop
            call TriggerRegisterPlayerUnitEvent(STA, Player(index), EVENT_PLAYER_HERO_SKILL, null)
            set index = index + 1
            exitwhen index == bj_MAX_PLAYER_SLOTS
        endloop

        call TriggerAddCondition(STA, Condition(function STA_NewAura))
       
        //Set up the location used to find Z heights
        set udg_STA_ZLoc = Location(0,0)
        //Nulls trigger variable
        set STA = null
       
    endfunction
    ///////////////////////////////////////////////////////////////////
    // End of the spell                                              //
    ///////////////////////////////////////////////////////////////////
     



    Next on the to-do-list is comment everything and write up a nice API

    Edit: and a couple more Wips because why not
    Wip4 is the aura just starting to take effect on nearby enemies
    Wip5 is when a chain reaction has started, killing large volumes of the enemies
    Wip6 is of units being healed when the hero using the aura dies
     

    Attached Files:

    Last edited: Jul 3, 2014
Thread Status:
Not open for further replies.