1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. 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
  3. 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
  4. 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
  5. The 4th SFX Contest has started. Be sure to participate and have a fun factor in it.
    Dismiss Notice
  6. The poll for the 21st Terraining Contest is LIVE. Be sure to check out the entries and vote for one.
    Dismiss Notice
  7. The results are out! Check them out.
    Dismiss Notice
  8. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  9. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    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.

Trigger Viewer

SunRay 1.5.1.w3x
Variables
Map
Systems Used
TimerUtils
Spell
JESP Standard Document
SunRay
Map Stuff
Initialization
Other
Maxy
Ressurect death
Enter map-specific custom script code below. This text will be included in the map script after variables are declared and before any trigger code.
//TESH.scrollpos=0
//TESH.alwaysfold=0
Name Type Is Array Initial Value
//TESH.scrollpos=0
//TESH.alwaysfold=0
library_once TimerUtils initializer init
//*********************************************************************
//* TimerUtils (Blue flavor for 1.23b or later)
//* ----------
//*
//*  To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//*  To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass)   More scripts: htt://www.wc3campaigns.net
//*
//* For your timer needs:
//*  * Attaching
//*  * Recycling (with double-free protection)
//*
//* set t=NewTimer()      : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t)       : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2)     : Attach value 2 to timer
//* GetTimerData(t)       : Get the timer's value.
//*                         You can assume a timer's value is 0
//*                         after NewTimer.
//*
//* Blue Flavor: Slower than the red flavor, it got a 408000 handle id
//*             limit, which means that if more than 408000 handle ids
//*             are used in your map, TimerUtils might fail, this
//*             value is quite big and it is much bigger than the
//*             timer limit in Red flavor.
//*
//********************************************************************

    //==================================================================================================
    globals
        private hashtable hasht //I <3 blizz
    endglobals

    //It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
    function SetTimerData takes timer t, integer value returns nothing
        call SaveInteger(hasht,0, GetHandleId(t), value)
    endfunction

    function GetTimerData takes timer t returns integer
        return LoadInteger(hasht, 0, GetHandleId(t))
    endfunction

    //==========================================================================================
    globals
        private timer array tT
        private integer tN = 0
        private constant integer HELD=0x28829022
        //use a totally random number here, the more improbable someone uses it, the better.
    endglobals

    //==========================================================================================
    function NewTimer takes nothing returns timer
        if (tN==0) then
            set tT[0]=CreateTimer()
        else
            set tN=tN-1
        endif
        call SetTimerData(tT[tN],0)
     return tT[tN]
    endfunction

    //==========================================================================================
    function ReleaseTimer takes timer t returns nothing
        if(t==null) then
            debug call BJDebugMsg("Warning: attempt to release a null timer")
            return
        endif
        if (tN==8191) then
            debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")

            //stack is full, the map already has much more troubles than the chance of bug
            call DestroyTimer(t)
        else
            call PauseTimer(t)
            if(GetTimerData(t)==HELD) then
                debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
                return
            endif
            call SetTimerData(t,HELD)
            set tT[tN]=t
            set tN=tN+1
        endif    
    endfunction

    private function init takes nothing returns nothing
        set hasht = InitHashtable()
    endfunction

endlibrary
 
History

Version 1.0
- Fixed a Math problem
- Spell was ready, initial release to the forums, for improvements

Version 1.1
- Now you can have waves of lights! If you don't like, just set the interval to zero!

Version 1.2
- Optimization in the code's speed, now it is even faster, and the code is more simple than ever !

Version 1.3
- Added a JESP manifest document
- Added a nice effect on the hero

Version 1.4
- Removed some members from the structure that weren't needed, now x, y and angle are just local variables
- Added Anitarf to the credits section

Version 1.4a
- Removed member "i" it was not needed. Now it is also a local variable
- Made some improvements to the comments

Version 1.5
- Added a boolean variable. Now the rays can depend on the casters angle if the user wants to

Version 1.5.1
- Updated for version 1.24
//TESH.scrollpos=0
//TESH.alwaysfold=0
  This is the JESP standard document, if a map contains this document it means that there are
 spells that follow this standard.

 Spells of this map that follow the standard:
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 - "Sun Ray"
 
 Advantages of the Standard
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 - Implementing spells that follow the standard is relatively easier than implementing JASS
 spells that don't follow the standard.

 - Configuring/Balancing spells that follow the standard is relatively easier than
 implementing JASS spells that don'
t follow the standard.

 - Users may do the following procedure to make a new ability that uses the spell's script :

 * Create a new Trigger with a name (case sensitive)
 * Convert that trigger to custom text.
 * Copy the spell'
s script to a text editor like Notepad or your OS equivalent.
 * Replace the spell's Code name with the name you used on the trigger.
 * Copy the new text to the new trigger
 * Duplicate the Spell'
s original objects to have new ones for the new spell script.

   You are now able to use that new version of the spell.

 - In case two guys give the same name to 2 different spells, there are no conflict problems
 because you can easily change the name of one of them

 What is the JESP Standard?
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
   The JESP standard was designed to make spell sharing much better. And to make sure JASS
 enhanced spells follow a rule, to prevent chaos.

 What does JESP Standard stands for?
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 JASS
 Enhanced
 Spell
 Pseudotemplate

 Requirements for a spell to follow the JESP Standard
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 - The spell is written in JASS
 - The spell is 100% multi instanceable.
 - The spell script is ready to support spells of any number of levels.
   (default config header is not required to support all of them)

 - The Spell has an specific code name.

 - The Spell's trigger must have the spell's codename as name

 - The Spell's InitTrig function must be named: InitTrig_<CodeName>

 - The spell has a configuration header.

 - It is mandatory that rawcodes of objects are configurable in the header.

 - All the spell'
s specific code is inside the spell's "Trigger" (Trigger== that custom text
   slot that world editor calls Trigger, the spell may use as many '
trigger' OBJECTS as needed)

 - Every spell-specific single identifier or key works in such a way that reproducing the
   spell'
s trigger but after performing a text-replace of codename with another name (and thus
   renaming the cloned trigger to the new code name) it won't cause compile errors / conflicts
   when playing the map.

 - There is no code inside the spell'
s "Trigger" that is not specific to the spell.

 - There are no requirements for GUI variables that are specific to the spell. If a system
   used by the spell requires GUI variables the code for the system must be outside the "Trigger"

 - Eyecandy and spell's balance have to be easy to configure

 - The name of the author should be included in the spell'
s script.

 - The reason to exist of this standard is spell sharing. This document should be included
 within the map. And it should specify which spell follows the standard, in the top list.
 
//TESH.scrollpos=0
//TESH.alwaysfold=0
//===========================================================================
//The caster uses his light powers to summon waves of Light Rays around him,
//damaging enemy Undead units nearby, and healing allied units
//
//Requires TimerUtils
//
//@author Flame_Phoenix
//
//@credits
//- Blackroot (aka Modeler), the first creator, gave me the basic idea and concept
//- the-thingy, by telling me where to use bj_DEGTORAD and why
//- Alexander244, for helping me fixing a bug with parenthesis ... lol
//- Anitarf, for suggesting a slight improvement for the code
//- My first teacher of vJASS: Blue_Jeans
//- All other people I forgot or ignored
//
//@version 1.5
//===========================================================================
scope SunRay initializer Init
   
    //needed for spell's core, don't change
    private keyword tmpPlayer
//===========================================================================
//=============================SETUP START===================================
//===========================================================================
    globals
        private constant integer AID = 'A000'   //raecode of ability
        private constant real LIGHT_RADIUS = 100    //radius of each single light
        private constant string LIGHT_EFFECT = "Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl" //the effect of the light
        private constant real LIGHT_INTERVAL = 0.2 //the interval that separates each light
        private constant boolean CASTER_ANG = true //if true we consider the caster's facing angle, else we don't
    endglobals

    private constant function Damage takes integer level returns real
        return level * 5.  //the damage the enemy undead units will take
    endfunction
   
    private constant function Heal takes integer level returns real
        return level * 10. //the heal your allied units will receive
    endfunction
   
    private constant function LightNumber takes integer level returns integer
    //each Sun Ray of (4 + level) lights
        return 4 + level
    endfunction
   
    private constant function RayNumber takes integer level returns integer
    //the number of Sun Rays of the spell
        return 5 + level
    endfunction
   
    private function AllyTargets takes nothing returns boolean
    //what allied units will be affected by the spell
        return IsUnitAlly(GetFilterUnit(), tmpPlayer) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false) and (GetWidgetLife(GetFilterUnit()) > 0.405)
    endfunction
   
    private function EnemyTargets takes nothing returns boolean
    //what enemy units will be affected by the spell
        return IsUnitEnemy(GetFilterUnit(), tmpPlayer) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false) and (GetUnitRace(GetFilterUnit()) == RACE_UNDEAD) and (GetWidgetLife(GetFilterUnit()) > 0.405)
    endfunction
//===========================================================================
//=============================SETUP END=====================================
//===========================================================================

    globals
        private player tmpPlayer
        private group g
        private boolexpr enemies
        private boolexpr allies
    endglobals
   
    private struct MyStruct
        unit caster
        real casterX
        real casterY
        integer level
        timer t
        real distInc
        integer lightsCreated
       
        static method create takes unit caster returns MyStruct
            local MyStruct data = MyStruct.allocate()
           
            //setting variables
            set data.caster = caster
            set data.casterX = GetUnitX(caster)
            set data.casterY = GetUnitY(caster)
            set data.level = GetUnitAbilityLevel(caster, AID)
            set data.t = NewTimer() //this will create the lights =)
            set data.distInc = LIGHT_RADIUS
            set data.lightsCreated = 0
           
            return data
        endmethod
       
        method onDestroy takes nothing returns nothing
            call ReleaseTimer(.t)
        endmethod
    endstruct
//===========================================================================    
    private function CreateLights takes nothing returns nothing
        local MyStruct data = MyStruct(GetTimerData(GetExpiredTimer()))
        local unit f
        local real x    //the X position of the effect
        local real y    //the Y position of the effect
        local real angle
        local integer i //a counter for the loop
       
        //we set this variable depending if we want to consider the
        //caster's angle or not
        if CASTER_ANG then
            set angle = GetUnitFacing(data.caster)
        else
            set angle = 0
        endif
       
        //if we didn't pass the number of lights, than we create lights
        //again, however, if we did, we end everything
        if data.lightsCreated < LightNumber(data.level) then
           
            //in this outer loop we create the Sun Rays
            set i = 0
            loop
                exitwhen(i == RayNumber(data.level))
   
                set x = data.casterX + data.distInc * Cos(angle)
                set y = data.casterY + data.distInc * Sin(angle)
           
                call DestroyEffect(AddSpecialEffect(LIGHT_EFFECT, x, y))
           
                //in this first double inner loop we select the enemy units and damage them
                set tmpPlayer = GetOwningPlayer(data.caster)
                call GroupEnumUnitsInRange(g, x, y, LIGHT_RADIUS, enemies)
                loop
                    set f = FirstOfGroup(g)
                    exitwhen(f == null)
                    call GroupRemoveUnit(g, f)
                    call UnitDamageTarget(data.caster, f, Damage(data.level), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
                endloop
           
                //in this second double inner loop we select the allied units and heal them
                set tmpPlayer = GetOwningPlayer(data.caster)
                call GroupEnumUnitsInRange(g, x, y, LIGHT_RADIUS, allies)
                loop
                    set f = FirstOfGroup(g)
                    exitwhen(f == null)
                    call GroupRemoveUnit(g, f)
                    call SetWidgetLife(f, GetWidgetLife(f) + Heal(data.level))
                endloop
           
                set angle = angle + (360 / RayNumber(data.level)) * bj_DEGTORAD
                set i = i + 1
            endloop
           
            set data.distInc = data.distInc + LIGHT_RADIUS
            set data.lightsCreated = data.lightsCreated + 1
        else
            call data.destroy()
        endif
       
    endfunction
//===========================================================================
    private function Conditions takes nothing returns boolean
        local MyStruct data
        if GetSpellAbilityId() == AID then
            set data = MyStruct.create(GetTriggerUnit())
           
            //now we start the timer !
            call SetTimerData(data.t, integer(data))
            call TimerStart(data.t, LIGHT_INTERVAL, true, function CreateLights)
        endif
           
        return false
    endfunction
//===========================================================================
    private function Init takes nothing returns nothing
        local trigger SunRayTrg = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( SunRayTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( SunRayTrg, Condition( function Conditions ) )
       
        set SunRayTrg = null
       
        //setting globals
        set g = CreateGroup()
        set enemies = Condition(function EnemyTargets)
        set allies = Condition(function AllyTargets)
       
        //preloading effect
        call Preload(LIGHT_EFFECT)
    endfunction
endscope
Initialization
  Events
    Map initialization
  Conditions
  Actions
    Game - Display to (All players) for 30 seconds the text: Spell created by: Flame_PhoenixThanks for trying my spell! , Give credit if you use it !You can fully heal/restore cooldowns with the "Esc" key.
Other
  Events
    Map initialization
  Conditions
  Actions
    Visibility - Create an initially Enabled visibility modifier for Player 1 (Red) emitting Visibility across (Playable map area)
    Hero - Set Paladin 0001 <gen> Hero-level to 10, Hide level-up graphics
Maxy
  Events
    Player - Player 1 (Red) skips a cinematic sequence
  Conditions
  Actions
    Unit - Set life of Paladin 0001 <gen> to 100%
    Unit - Set mana of Paladin 0001 <gen> to 100%
    Unit - Reset ability cooldowns for Paladin 0001 <gen>
Ressurect death
  Events
    Unit - A unit owned by Player 1 (Red) Dies
  Conditions
    ((Unit-type of (Dying unit)) is A Hero) Equal to True
  Actions
    Hero - Instantly revive Paladin 0001 <gen> at (Position of (Dying unit)), Hide revival graphics