• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Hammer of Dawn [v1.30] by -Yixx,,-

Due to model dissappearing and reappearing, i reccommend the spell to have a maximum level of 5 of 6!


Finally i had inspiration to do a new spell,,
Now i wanted to do it in vJass, so i tried it in vJass,,
At first i had a very hard time doing it, and i even dropped the idea,
But then i tried it again and i got help from a new friend,,

so: Thank you, xxdingo93xx!

Hammer of Dawn:
You call a satalite, and leave a mark on the ground.
The satalite charges and shoots a lightning out of the sky.
The lightning draws more lightnings to it, all lightnings do
damage to surrounding units.

As the_Witcher says: It is not like the real Hammer of Dawn, only based off it!

NOTE: To import this spell, you need Jass New Gen Pack!
Also, this spell uses TimerUtils, by Vexorian.

Known bugs:
- The higher the level, the further the main lightning gets from the target point. Remind this, when you set a maximum level for this spell!

Credits:
- xxdingo93xx, for helping with the code and vJass in general
- Dark Destiny, for the test-map
- Vexorian, for TimerUtils
- darkreapers, for reporting level bug

Give credit if you use it and do not redistribute without my permission!!


v1.00 - Uploaded
v1.01 - Updated hotkeys
v1.11 - Lightnings come from sky now, and removed missile art
v1.20 - Spell would not work for the levels 4 and 7 due to formulas being 0. Fixed Max level is now 21
v1.30 - Spell supports patch 1.24, updated to new natives, updated small efficiency


Because this is easier for the mods to review, here is the current code:
JASS:
scope HoD
//==========================================================================\\
//============================ Hammer of Dawn ==============================\\
//============================ Documentation ===============================\\
//==========================================================================\\
// * Concept:   You call the Satalite for help. The satalite shoots a       \\
//              lightning to the Earth, pulling more lightnings to it,      \\
//              which all leave a trail of electricity behind, damaging     \\
//              units in range.                                             \\
//                                                                          \\
// * Execution: This is my very first vJass spell. I have had quite some    \\
//              problems with the execution. Those problems all seemed      \\
//              to be rather newbish. That is why i want to thank one       \\
//              person in special.                                          \\
//                                    xxdingo93xx                           \\
//              He has not only helped me with the code, but with vJass     \\
//              in General. Thanks and credit to him!                       \\
//                                                                          \\
// * Credits:   - xxdingo93xx   = For helping and teaching me               \\
//              - My friends    = For playing way too much Gears of War     \\
//                                with me, which brought me to this idea    \\
//                                                                          \\
// * Import:    How to import this in your map:                             \\
//              IMPORTANT NOTICE: You need JNGP to import this!!!!          \\
//                      Also known as: Jass New Gen Pack                    \\
//              - First of all, make sure you have TimerUtils in your map   \\
//                I used the Blue flavor, because I was told it is best     \\
//                for spells. To do this, make a custom script trigger by   \\
//                clicking 'Edit > Convert to Custom Text' and paste the    \\
//                TimerUtils library in it                                  \\
//              - Secondly, make a trigger in your map, and convert it to   \\
//                custom text by: 'Edit > Convert to Custom Text' this will \\
//                show a message, but just click ok. Paste the code of this \\
//                map in that trigger, which means from:                    \\
//                'scope HoD initializer Init' until 'endscope'             \\
//                that is all =)                                            \\
//                                                                          \\
// * Editing:   This spell is made to be able to be edited as easy as       \\
//              possible. I will tell you the parts that are to be edited   \\
//              and i have also highlighted them in the script.             \\
//              Parts to be edited:                                         \\
//              - The first globals block. This block is full of editable   \\
//                variables. All are explained in the next block.           \\
//              - The five functions under the first globals block. They    \\
//                are named: DamageF,RadiusF,AmountF,TimeF and DistanceF    \\
//                They calculate the Damage, Damage Radius, Lightning       \\
//                Amount, Time of the spell, and Starting Distance of the   \\
//                lightnings. Change them as suits to you and your map.     \\
//              NOTE: the variable 'LightningString' is to choose the       \\
//                    lightning type, which are as follows:                 \\
//               LSA[1] = "CLPB"     // Chain Lightning Primary             \\
//               LSA[2] = "CLSB"     // Chain Lightning Secondary           \\
//               LSA[3] = "DRAB"     // Drain                               \\
//               LSA[4] = "DRAL"     // Drain Life                          \\
//               LSA[5] = "DRAM"     // Drain Mana                          \\
//               LSA[6] = "AFOD"     // Finger of Death                     \\
//               LSA[7] = "FORK"     // Forked Lightning                    \\
//               LSA[8] = "HWPB"     // Healing Wave Primary                \\
//               LSA[9] = "HWSB"     // Healing Wave Secondary              \\
//               LSA[10] = "CHIM"    // Lightning Attack                    \\
//               LSA[11] = "LEAS"    // Magic Leash                         \\
//               LSA[12] = "MBUR"    // Mana Burn                           \\
//               LSA[13] = "MFPB"    // Mana Flare                          \\
//               LSA[14] = "SPLK"    // Spirit Link                         \\
//              NOTE: The special effects used in this spell are chosen     \\
//                    to fit with lightning type '1'. The effects are       \\
//                    declared in the first globals block, also to be       \\
//                    easily edited.                                        \\
//                                                                          \\
// * Variables: - AID: The rawcode of the ability                           \\
//              - INT: The interval of the Timers                           \\
//              - DeltaZ: The height difference between source and point    \\
//                        of the Lightnings                                 \\
//              - DeltaDist: The distance difference between source and     \\
//                           point of the Lightnings                        \\
//              - LightningString: The array of the string variable         \\
//              - MaxLights: This must be calculated as follows:            \\
//                           with the function 'AmountF', use as parameter  \\
//                           the maximum levels of the spell, by default 3  \\
//              - SFX1: The effect string on ground under the lightnings    \\
//              - SFX2: The effect string when the spell stops              \\
//                                                                          \\
// * Functions: - DamageF: Calculates the Damage done every interval.       \\
//              - RadiusF: Calculates the Radius of the damage done         \\
//              - AmountF: Calculates the amount of lightnings made         \\
//              - TimeF: Calculates the time to fuse the lightnings         \\
//              - DistanceF: Calculates the main distance of the lightnings \\
//              - LoadTimeF: Calculates time to spawn the lightnings        \\
//                                                                          \\
//==========================================================================\\
//============================ End Documentation ===========================\\
//==========================================================================\\

//==========================================================================\\
//================================== Setup =================================\\
//==========================================================================\\
    globals
        private constant integer AID = 'A000'
        private constant integer LightningString = 1
        private constant integer MaxLights = 5
        private constant real INT = 0.035
        private constant real DeltaZ = 1000
        private constant real DeltaDist = 50
        private constant string SFX1 = "Objects\\Spawnmodels\\NightElf\\NEDeathMedium\\NEDeath.mdl"
        private constant string SFX2 = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
        private constant string SFX3 = "Abilities\\Spells\\NightElf\\TrueshotAura\\TrueshotAura.mdl"
    endglobals
//==========================================================================\\
    private constant function DamageF takes integer level returns real
        return 0.4 * level + 0.3
    endfunction
//==========================================================================\\
    private constant function RadiusF takes integer level returns real
        return 10. * level + 50.
    endfunction
//==========================================================================\\
    private constant function AmountF takes integer level returns integer
        return 2 + 1 * level
    endfunction
//==========================================================================\\
    private constant function TimeF takes integer level returns real
        return 2.5 + 1.25 * level
    endfunction
//==========================================================================\\
    private constant function DistanceF takes integer level returns real
        return 150. + 50. * level
    endfunction
//==========================================================================\\
    private function LoadTimeF takes integer level returns real
        return 7.00 - 1.48 * SquareRoot(level)
    endfunction
//==========================================================================\\
    private function DropTimeF takes integer level returns real
        return 1.3 - ((Pow(level/1.5,1.5))/level*2.)
    endfunction
//==========================================================================\\
//================================ End Setup ===============================\\
//========= Do NOT edit below unless you know what you are doing! ==========\\
//==========================================================================\\
    globals
        private constant integer MaxArray = MaxLights - 1
        private location TempLoc = Location(0,0)
        private group g = CreateGroup()
        private unit TempCaster
        private string DLS
        private string array LSA
        private boolexpr AbilityFilter = null
        private boolexpr GroupFilter = null
    endglobals
//==========================================================================\\
    private function GetTerrainZ takes real x, real y returns real
        call MoveLocation(TempLoc,x,y)
        return GetLocationZ(TempLoc)
    endfunction
//==========================================================================\\
    private struct DATA
//==========================================================================\\
        unit Caster
        lightning array Light [MaxArray]
        lightning MainLight
        effect Indication
        real x
        real y
        real z
        real Distance
        real Damage
        real Radius
        real DistIncrease
        real ZIncrease
        real LoadTime
        real DropTime
        integer Amount
        integer SFXSpam
        timer t
//==========================================================================\\
        static method Loop takes nothing returns nothing
            local DATA dat = DATA(GetTimerData(GetExpiredTimer()))
            local integer i = 0
            local real a
            local real x1
            local real y1
            local real x2
            local real y2
            local real z2
            local real z1
            local unit temp = null
            if dat.LoadTime <= 0 then
                if dat.DropTime > 0 then
                    set dat.DropTime = dat.DropTime - INT
                    set dat.z = dat.z - dat.ZIncrease
                    call MoveLightningEx(dat.MainLight, false,dat.x,dat.y,dat.z,dat.x,dat.y,GetTerrainZ(dat.x,dat.y) + DeltaZ)
                    loop
                        exitwhen i > dat.Amount - 1
                        set a = ((360/dat.Amount) * (i+1)) * bj_DEGTORAD
                        set x1 = dat.x + dat.Distance * Cos(a)
                        set y1 = dat.y + dat.Distance * Sin(a)
                        set x2 = x1 + DeltaDist * Cos(a)
                        set y2 = y1 + DeltaDist * Sin(a)
                        set z1 = GetTerrainZ(x1,y1) + dat.z
                        set z2 = GetTerrainZ(x1,y1) + DeltaZ
                        call MoveLightningEx(dat.Light [i], false, x1,y1,z1,x2,y2,z2)
                        set i = i + 1
                    endloop
                else
                    set dat.Distance = dat.Distance - dat.DistIncrease
                    if dat.Distance <= 0 then
                        call DestroyEffect(AddSpecialEffect(SFX1,dat.x,dat.y))
                        call dat.remove()
                    else
                        loop
                            exitwhen i > dat.Amount - 1
                            set a = ((360/dat.Amount) * (i+1)) * bj_DEGTORAD
                            set x1 = dat.x + dat.Distance * Cos(a)
                            set y1 = dat.y + dat.Distance * Sin(a)
                            set x2 = x1 + DeltaDist * Cos(a)
                            set y2 = y1 + DeltaDist * Sin(a)
                            set z1 = GetTerrainZ(x1,y1)
                            set z2 = z1 + DeltaZ
                            call MoveLightningEx(dat.Light [i], false, x1,y1,z1,x2,y2,z2)
                            set TempCaster = dat.Caster
                            call GroupEnumUnitsInRange(g,x1,y1,dat.Radius,GroupFilter)
                            loop
                                set temp = FirstOfGroup(g)
                                exitwhen temp == null
                                call UnitDamageTarget(dat.Caster, temp,dat.Damage,true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_LIGHTNING, WEAPON_TYPE_WHOKNOWS)
                                call GroupRemoveUnit(g, temp)
                            endloop
                            if dat.SFXSpam >= 3 then
                            call DestroyEffect(AddSpecialEffect(SFX2, x1,y1))
                            endif
                            set i = i + 1
                        endloop
                        call GroupEnumUnitsInRange(g,dat.x,dat.y,dat.Radius,GroupFilter)
                        loop
                            set temp = FirstOfGroup(g)
                            exitwhen temp == null
                            call UnitDamageTarget(dat.Caster, temp,dat.Damage,true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_LIGHTNING, WEAPON_TYPE_WHOKNOWS)
                            call GroupRemoveUnit(g,temp)
                        endloop
                        if dat.SFXSpam >= 3 then
                            call DestroyEffect(AddSpecialEffect(SFX2, dat.x,dat.y))
                            set dat.SFXSpam = 0
                        endif
                        set dat.SFXSpam = dat.SFXSpam + 1
                    endif
                endif
            else
                set dat.LoadTime = dat.LoadTime - INT
                if dat.LoadTime <= 0 then
                    set i = 0
                    set dat.MainLight = AddLightningEx(DLS, false, dat.x,dat.y,dat.z, dat.x,dat.y,dat.z)
                    loop
                        exitwhen i > dat.Amount - 1
                        set a = ((360/dat.Amount) * (i+1)) * bj_DEGTORAD
                        set x1 = dat.x + dat.Distance * Cos(a)
                        set y1 = dat.y + dat.Distance * Sin(a)
                        set x2 = x1 + DeltaDist * Cos(a)
                        set y2 = y1 + DeltaDist * Sin(a)
                        set z1 = dat.z
                        set z2 = dat.z
                        set dat.Light [i] = AddLightningEx(DLS,false, x1,y1,z1,x2,y2,z2)
                        set i = i + 1
                    endloop
                    call DestroyEffect(dat.Indication)
                endif
            endif
            set temp = null
        endmethod
//==========================================================================\\
        static method Create takes nothing returns boolean
            local thistype this
            local integer lvl
            if GetSpellAbilityId() == AID then
                set this = thistype.allocate()
                set lvl = GetUnitAbilityLevel(GetTriggerUnit(), AID)
                set .Caster = GetTriggerUnit()
                set .x = GetSpellTargetX()
                set .y = GetSpellTargetY()
                set .z = GetTerrainZ(.x,.y) + DeltaZ
                set .Distance = DistanceF(lvl)
                set .Damage = DamageF(lvl)
                set .Radius = RadiusF(lvl)
                set .Amount = AmountF(lvl)
                set .LoadTime = LoadTimeF(lvl)
                set .DropTime = DropTimeF(lvl)
                set .DistIncrease = .Distance/R2I(TimeF(lvl)/INT)
                set .ZIncrease = DeltaZ/R2I(DropTimeF(lvl)/INT)
                set .SFXSpam = 5
                set .t = NewTimer()
                set .Indication = AddSpecialEffect(SFX3,.x,.y)
                call SetTimerData(.t, integer(this))
                call TimerStart(.t, INT, true, function thistype.Loop)
            endif
            return false
        endmethod
//==========================================================================\\
        private method remove takes nothing returns nothing
            local integer i = 0
            set .Caster = null
            loop
                exitwhen i > .Amount - 1
                call DestroyLightning(.Light [i])
                set .Light [i] = null
                set i = i + 1
            endloop
            call DestroyLightning(.MainLight)
            set .MainLight = null
            call ReleaseTimer(.t)
            call .destroy()
        endmethod
//==========================================================================\\
        private static method groupfilter takes nothing returns boolean
            return IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(TempCaster))
        endmethod
//==========================================================================\\
        static method StringSettings takes nothing returns nothing
            set LSA[1] = "CLPB"     // Chain Lightning Primary
            set LSA[2] = "CLSB"     // Chain Lightning Secondary
            set LSA[3] = "DRAB"     // Drain
            set LSA[4] = "DRAL"     // Drain Life
            set LSA[5] = "DRAM"     // Drain Mana
            set LSA[6] = "AFOD"     // Finger of Death
            set LSA[7] = "FORK"     // Forked Lightning
            set LSA[8] = "HWPB"     // Healing Wave Primary
            set LSA[9] = "HWSB"     // Healing Wave Secondary
            set LSA[10] = "CHIM"    // Lightning Attack
            set LSA[11] = "LEAS"    // Magic Leash
            set LSA[12] = "MBUR"    // Mana Burn
            set LSA[13] = "MFPB"    // Mana Flare
            set LSA[14] = "SPLK"    // Spirit Link
        endmethod
//==========================================================================\\
        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            local integer i = 0
            call .StringSettings()
            set DLS = LSA [LightningString]
            set GroupFilter = Condition(function thistype.groupfilter)
            set AbilityFilter = Condition(function thistype.Create)
            loop
            exitwhen i >= bj_MAX_PLAYER_SLOTS
                call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
                set i = i + 1
            endloop
            call TriggerAddCondition(t,AbilityFilter)
            set t = null
        endmethod
//==========================================================================\\
    endstruct
//==========================================================================\\
//========================== End of the Spell ==============================\\
//==========================================================================\\
endscope

Keywords:
hammer, dawn, lightning, lightnings, gears of war, gears, war, satalite, sky, electricity, OMGLOL
Contents

Spell Test Map (Map)

Reviews
11:52, 21st Dec 2009 TriggerHappy: Review for Spell The coding fixes are minor. The BJ event is perfectly fine. You should convert your start function to use GetSpellTargetX/Y. It's probably also possible to use the create method...

Moderator

M

Moderator

11:52, 21st Dec 2009
TriggerHappy:

Review for Spell

The coding fixes are minor.
  • The BJ event is perfectly fine.
  • You should convert your start function to use GetSpellTargetX/Y.
    It's probably also possible to use the create method directly as the
    action since you will have access to all the starting vars.
  • FirstOfGroup loops are the slowest method of going through a unit
    group AFAIK.

Status

Feel free to message me here if you have any issues with
my review or if you have updated your resource and want it reviewed again.

Approved
 
Hmm ok Gears of War rulezz^^
well its not the same hammer of dawn like in gears, but a very good idea though.
i think now that i'm going to create a more gears like version^^

very well coded and for first try i think it's awesome!!
very good documantation and many things to modify make this spell even better!!
credits are given and it's easy to import so 5/5

go on like this :thumbs_up:

oh btw: first^^
 
Level 16
Joined
Oct 12, 2008
Messages
1,570
Updated, it now should be able to be opened by normal WE, (first version was, but the 1.11 wasnt, should now be fixed)

Thanks for all good feedbacks! ^^,,

1 known bug: When on lvl 3, the main lightning isnt in the total middle of the sign,,
Trying to fix now,,
 
  • Like
Reactions: Rmx
Level 28
Joined
Mar 25, 2008
Messages
2,955
JASS:
private function DamageF takes integer level returns real
        return 0.4 * I2R(level) + 0.3
    endfunction

wouldn't it be easier to say
JASS:
set DamageF = 0.4*level+0.3

?

Same goes for every function in the setup

Tell me if I'm wrong but I think it would work with just inlining the factors..
 
Level 16
Joined
Oct 12, 2008
Messages
1,570
Squiggy, you are right, inlining is the best to do, but this is to make the modification of the spell as high as possible. If I hide those calculations within the struct, it will be less easy to find and modify them,,
And it would indeed still work when inlined,,

D4RK_G4ND4LF, i dont know how that happens, neither do i know what causes it, but i sometimes also have that, when there are alot of lightnings within an area, i get model movement and such.
You are not the only one, but i have to say, your computer is gotta be kinda bad, because mine is also xD
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
I've got a Dual Core Cpu running on 3,5 GHZ and a Geforce 9800 GT + 4 Gb of ram (ok... Windows XP...so only 3 GB of it) and I don't think this is "bad"

and I found out that this bug occurs when casting it next to destructibles and only when the lightnings are on top of the screen (stuff vanishes when seeing everything in the middle of the screen)
 
Level 9
Joined
May 30, 2008
Messages
430
When i cast the spell multiple times some of the lighting doesn't disappear.
And yes the trees and other things are moving around becouse of the 2 much special effect that wc3 engine can't handle "not our PC" (if i am not wrong)
 
Pretty cool.

  • Why does everyone seem to inline the any unit event BJ. Theres nothing wrong with that BJ.
  • GetSpellTargetLoc(), C'mon use GetSpellTargetX/Y and inline that function. Then inside the create method, just use TempLoc as the Z reference.
  • I think you forgot to remove call BJDebugMsg(I2S(lvl)).
  • ATTACK_TYPE_NORMAL, DAMAGE_TYPE_LIGHTNING, WEAPON_TYPE_WHOKNOWS need to be configurable.
  • You don't need set AbilityFilter = Condition(function Conditions), just inline it inside the TriggerAddCondition function.
  • Nulling triggers is unneeded, though it's harmless.
 
Top