• 🏆 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!

Terror Rising v1.5

Hi everybody,

Today I upload a spell that uses my FearSystem.
This spell is Terror Rising (thanks to kakuzu for the name !).

The description of the spell : The caster create a electricity bolt that travels 425/600/775 units and every 175 units the bolt launch a explosion that deal 25/50/75 damages to enemy units and fear those units during 1.2/1.4/1.6 second.

The fear and the damage stacks if the unit take many explosion of the bolt meaning that a unit taking two explosions will be feared during (1.2-0.5)+1.2 = 1.9 second and will take 25+25 = 50 damages for the level 1 of the spell.
Note : There is a -0.5 because there is an explosion every 0.5 second.

This system requires the FearSystem, it is not optional.

Here is the code of the spell :
JASS:
library TerrorRising requires FearSystem/*By me*/, BoundSentinel //By Vex
/*
FearSystem : http://www.hiveworkshop.com/forums/spells-569/fear-system-v-2-7-a-243755/
BoundSentinel : http://www.wc3c.net/showthread.php?t=102576
*/
//CONFIGURATION
    globals
        private constant real FPS = 0.0312500
        //The distance between two explosions.
        private constant real BETWEEN_UNITS = 175.
        //The time between two explosions.
        private constant real TIME_BETWEEN = 0.5
        //It means that the speed of the orb is BETWEEN_UNITS/TIME_BETWEEN
        private constant integer SPELL_ID = 'U000'
        private constant integer DUMMY_ID = 'd000'
        private constant real AOE = 175.
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_MAGIC
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
        //The path of the special effect attached to fear status
        private constant string FEAR_PATH = "Abilities\\Spells\\Undead\\Curse\\CurseTarget.mdl"
        private constant string FEAR_ATTACH = "overhead"
        //The path of the effect that will spawn on the units when it takes damage
        private constant string UNIT_PATH = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl"
        private constant string UNIT_ATTACH = "origin"
        private constant string EXPLOSION_PATH = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
    endglobals
    
    private constant function Damage takes integer level returns real
        return 25.*level
    endfunction
    
    private constant function Explosion_Number takes integer level returns integer
        return 2+level
    endfunction
    
    private constant function Time_Fear takes integer level returns real
        return 1. + 0.2*level
    endfunction
    
    private function Unit_Filter takes player source, unit targ returns boolean
        return (not IsUnitType(targ, UNIT_TYPE_MAGIC_IMMUNE)) and (UnitAlive(targ)) and IsUnitEnemy(targ, source)
    endfunction
//END CONFIGURATION -> DONUT TOUCH ANYTHING BELOW

    private struct Explosion extends array
        unit u
        unit caster
        player owner
        integer steps
        real temp
        real fear
        real X
        real Y
        real dmg
        thistype prev
        thistype next
        static integer count
        static timer period
        static group g
        
        method destroy takes nothing returns nothing
            if this.next != 0 then
                set this.next.prev = this.prev
            endif
            set this.prev.next = this.next
            set this.prev = thistype(0).prev
            set thistype(0).prev = this
            if thistype(0).next == 0 then
                call PauseTimer(period)
            endif
            call UnitApplyTimedLife(u, 'BTLF', 0.01)
            set this.u = null
            set this.caster = null
            set this.owner = null
        endmethod
        
        static method periodic takes nothing returns nothing
            local Fear F
            local thistype this = thistype(0).next
            local unit v
            local real x
            local real y
            loop
                exitwhen this == 0
                set this.temp = this.temp - FPS
                set x = GetUnitX(this.u) + this.X
                set y = GetUnitY(this.u) + this.Y
                call SetUnitX(this.u, x)
                call SetUnitY(this.u, y)
                if this.temp <= 0 then
                    call DestroyEffect( AddSpecialEffect(EXPLOSION_PATH, x, y) )
                    call GroupEnumUnitsInRange(g, x, y, AOE, null)
                    loop
                        set v = FirstOfGroup(g)
                        exitwhen v==null
                        call GroupRemoveUnit(g, v)
                        if Unit_Filter(this.owner, v) then
                            call DestroyEffect( AddSpecialEffectTarget(UNIT_PATH,v,UNIT_ATTACH) )
                            if Fear.isFeared(v) then
                                set F = Fear.get(v)
                                set F.time = this.fear + F.time
                            else
                                set F = Fear.create()
                                set F.targ = v
                                set F.path = FEAR_PATH
                                set F.attach = FEAR_ATTACH
                                set F.time = this.fear
                                call F.start()
                                call F.destroy()
                            endif
                            call UnitDamageTarget(this.caster, v, this.dmg, true, false, ATTACK_TYPE, DAMAGE_TYPE, null)
                        endif
                    endloop
                    set this.steps = this.steps - 1
                    set this.temp = TIME_BETWEEN
                endif
                if this.steps == 0 then
                    call this.destroy()
                endif
                set this = this.next
            endloop
        endmethod
        
        static method cond takes nothing returns boolean
            local thistype this
            local real angle
            local real tx
            local real ty
            local integer i
            if GetSpellAbilityId() == SPELL_ID then
                //Allocate
                if thistype(0).prev == 0 then
                    set count = count + 1
                    set this = count
                else
                    set this = thistype(0).prev
                    set thistype(0).prev = thistype(0).prev.prev
                endif
                if thistype(0).next == 0 then
                    call TimerStart(period, FPS, true, function thistype.periodic)
                else
                    set thistype(0).next.prev = this
                endif
                set this.next = thistype(0).next
                set thistype(0).next = this
                set this.prev = thistype(0)
                //End Allocate
                set this.caster = GetTriggerUnit()
                set i = GetUnitAbilityLevel(this.caster,SPELL_ID)
                set tx = GetSpellTargetX()
                set ty = GetSpellTargetY()
                set angle = Atan2(ty-GetUnitY(this.caster), tx-GetUnitX(this.caster))
                set this.owner = GetTriggerPlayer()
                set this.u = CreateUnit(this.owner, DUMMY_ID, tx, ty, angle*bj_RADTODEG)
                set this.steps = Explosion_Number(i)
                set this.temp = TIME_BETWEEN
                set this.fear = Time_Fear(i)
                set this.X = BETWEEN_UNITS*Cos(angle)*FPS
                set this.Y = BETWEEN_UNITS*Sin(angle)*FPS
                set this.dmg = Damage(i)
            endif
            return false
        endmethod
        
        static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(t, Condition(function thistype.cond))
            call Preload(FEAR_PATH)
            call Preload(EXPLOSION_PATH)
            call Preload(UNIT_PATH)
            set period = CreateTimer()
            set count = 0
            set g = CreateGroup()
            set t = null
        endmethod
    endstruct
endlibrary

How to import :
- You will first need JNGP.
- Copy the three library inside the folder Requirements.
Note : You can use Table by Bribe or no Table at all too (even if I recommend to use one).
Actually I have trouble with Table by Bribe just use Table by Vex and nothing more if you can at the moment.
- Copy the trigger called TerrorRising
- Copy the abilities linked to the FearSystem called 'BEAR FORM FEAR' and 'MORPH FEAR' and 'DISABLE_ATTACK'. Then change the id inside the code of the FearSystem.
- Copy the dummy unit called 'DUMMY_EXPLOSION' and change the id inside the spell.
- Copy the ability FearExplosion. Then change the id inside the code of the spell.
- You're ready to go :)

Credits to :
- Vexorian -> Table, JassHelper, BoundSentinels
- Bribe -> Table
- Maker -> Help in FearSystem
- Chobibo -> Help in FearSystem
- Kakuzu -> Help for the name :3

Give me credits and to the other if you use ;)

v1.0 :
- Initial Release

v1.1 :
- Implemented BoundSentinels
- Struct members optimized.

v1.2 :
- Trigger optimization.

v1.3 :
- Added the Unit_Filter function
- Trigger optimization.

v1.4 :
- I don't remember what I've done sorry ;)

v1.5 :
- A good name finally !


Keywords:
Explosion, vJASS, JESP, Fear, Terror, Rising, Terror Rising, Malhorne
Contents

Just another Warcraft III map (Map)

Reviews
20:49, 3rd Jan 2014 BPower: Changes made, approved. One minor thing: The dummy unit still uses upgrades. (old)review: http://www.hiveworkshop.com/forums/spells-569/fearexplosion-v1-3-a-244427/index4.html#post2466426
Level 18
Joined
Sep 14, 2012
Messages
3,413
For the static members I hate instanciate them in their declaration because it is exactly the same.

For the avoid of native call I said I wouldn't do it ^^

Didn't so that one for the unit v sorry xD

Yep I should change it in the next version.

Anyway thanks for the review and happy headbanging christmas everybody
*Go back to headbang*
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Malhorne you are my first victim. :)

Review:

  • You have to change the settings of the dummy unit in the object editor. Currently It can't move because you set its movement speed to 0.
    There are some other fields which should be changed aswell like collision size. Use the particle/standart orb dummy as template.
  • Integrate the hotkey to the tooltip and add some color. i.e you can use the the default style from blizzard.
  • I think you should add a small value like 0.01 instead of TIME_BETWEEN. It looks better.
    JASS:
    call UnitApplyTimedLife(u, 'BTLF', TIME_BETWEEN)
  • Improve the description of your settings in the global block --> UNIT_PATH and FEAR_PATH those names are not self-explaining.
  • 250 AOE doesn't really fit to the chosen effect model. The footmans will start running like chickens while the effect is still far away.

Only the first is critical, but I would like to see you working on all mentioned issues. The coding looks good and the Fear System is already approved.
I'm going to move it to "Needs fix", but once you make those changes, it will be approvable.

You could add a static if for TimerUtils, since it can be found in most maps which use the vJass feature.

I'm curious. F.destroy() doesn't deallocate the instance so why did you chose this reserved method name?
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
Malhorne you are my first victim. :)

Review:

  • You have to change the settings of the dummy unit in the object editor. Currently It can't move because you set its movement speed to 0.
    There are some other fields which should be changed aswell like collision size. Use the particle/standart orb dummy as template.
  • Integrate the hotkey to the tooltip and add some color. i.e you can use the the default style from blizzard.
  • I think you should add a small value like 0.01 instead of TIME_BETWEEN. It looks better.
    JASS:
    call UnitApplyTimedLife(u, 'BTLF', TIME_BETWEEN)
  • Improve the description of your settings in the global block --> UNIT_PATH and FEAR_PATH those names are not self-explaining.
  • 250 AOE doesn't really fit to the chosen effect model. The footmans will start running like chickens while the effect is still far away.

Only the first is critical, but I would like to see you working on all mentioned issues. The coding looks good and the Fear System is already approved.
I'm going to move it to "Needs fix", but once you make those changes, it will be approvable.

You could add a static if for TimerUtils, since it can be found in most maps which use the vJass feature.

I'm curious. F.destroy() doesn't deallocate the instance so why did you chose this reserved method name?

actually, he deallocates the instance

notice the extends array, he uses his own "deallocation" and "allocation" method, but instead of using .allocate() and .deallocate() method calls, he "inlines" them
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
Wohhha what the fuck did I just miss :O ?
New moderator killing me with a rejected instead of needs fix. :(
Ok ok made me fear (that's the joke) xD

So first let me just say that TimerUtils is pretty useless in this resource.
I'm using one single timer in every of my resources.
As I'm using the less external resoucres as possible.

At last I shall do those little changements soon.


EDIT : sorry if I seem to be mad at the begginning at the message wasn't attempted to do so x)
 
Level 12
Joined
May 11, 2014
Messages
1,257
The spell efect is pretty good and it works fine , but how about to change the name in Rising of Terror ?
 
Level 35
Joined
Feb 5, 2009
Messages
4,558
The fear and the damage stacks if the unit take many explosion of the bolt meaning that a unit taking two explosions will be feared during (1.2-0.5)+1.2 = 1.9 second and will take 25+25 = 50 damages for the level 1 of the spell.
Note : There is a -0.5 because there is an explosion every 0.5 second.

Just wondering, but wouldn't it last for 0.5+1.2 = 1.7 seconds? I'm assuming it's +0.5 rather than +(1.2-0.5) because the unit would have the fear effect for 0.5 seconds before the next explosion, and assuming the unit gets hit by the second explosion it would reset the duration back to 1.2, effectively adding 0.5 seconds.

I might be wrong, hence why I am asking :O)
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
You get fear at t=0s. So you're current fear time is 1.2s.

Then you're feared during 0.5s, so we're at t=0.5s and your remaining fear time is 1.2 - 0.5 = 0.7s
You take another explosion since there is one explosion every 0.5s and you were at the wrong place at the wrong moment. So you get another 1.2s of fear. So you add 1.2s to your remaining fear time : 0.7 (remaining) + 1.2 = 1.9s

:)
 
Top