• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Help with changing these Custom Abilities?

Status
Not open for further replies.
Level 30
Joined
Jan 31, 2010
Messages
3,551
Hey there!
I need help with changing these abilities for my project, the Legendary War. I have made tooltips as simplest as possible, and what I want as short and sharp I wanted them.

1. Inner Rage: Pushes away nearby enemies and deals damage to them.
What I want: It should pull enemies towards the caster, not push them outwards.

2. Deviousness: Each attack against enemy Heroes steals Agility, which is restored back in few seconds. Stacks with itself, but each strike has it's own timer (won't reset with each new hit).
What I want: It should use some sort of damage detection system, since I want it to have no cooldown. If I remove the wait functions in my triggers, the spell can be abused by canceling attacks, which I want to prevent.

3. Phase Cycle: Caster gains movement increase and full transparency. Additionally, upon cast and at the end of the duration, lunar blasts will damage EVERYTHING nearby.
What I want: I want to keep the movement gain, but I also want it to give unitwalking/zero collision while it lasts. I don't want transparency. I also want only one blast of energy, at the end of duration, which won't damage mechanical units, allies or self. Just enemies.

4. Punitive Surge: Caster moves forward targeted point, casting her shadows around herself that deal damage to enemies she encounters.
What I want: This spell has only one "problem", it uses pathing item, meaning that if you hit a building, cliff or doodad/destructible, you will stop. If you try to cast it while next to one of mentioned objects, the spell will go to waste without effects. I want to have no pathing in this spell, meaning that caster can travel through cliffs, buildings and doodads.
  • Inner Rage
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Inner Rage [FP]
    • Actions
      • Set KB_Point[0] = (Position of (Triggering unit))
      • Set KB_Group = (Units within 300.00 of KB_Point[0] matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) belongs to an ally of (Owner of (Triggering unit))) Equal to False) and ((((Matching unit) is A flying unit) Equal to False) and (((Matching
      • Unit Group - Pick every unit in KB_Group and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • KB_Skip Equal to 0
            • Then - Actions
              • Trigger - Turn on Knockback System <gen>
            • Else - Actions
          • Set KB_Skip = (KB_Skip + 1)
          • Set KB_Times = (KB_Times + 1)
          • Set KB_Off[KB_Times] = True
          • Set KB_Target[KB_Times] = (Picked unit)
          • Set KB_Point[1] = (Position of (Picked unit))
          • Set KB_Angle[KB_Times] = (Angle from KB_Point[1] to KB_Point[0])
          • Set KB_Speed[KB_Times] = 20.00
          • Set KB_Spam[KB_Times] = 5
          • Set KB_Distance[KB_Times] = 300.00
          • Custom script: call RemoveLocation(udg_KB_Point[1])
      • Custom script: call RemoveLocation(udg_KB_Point[0])
      • Custom script: call DestroyGroup(udg_KB_Group)
  • Knockback System
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • For each (Integer KB) from 1 to KB_Times, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • KB_Off[KB] Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • KB_Distance[KB] Less than or equal to 0.00
                • Then - Actions
                  • Set KB_Off[KB] = False
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • KB Less than KB_Times
                    • Then - Actions
                      • Set KB_Off[KB] = KB_Off[KB_Times]
                      • Set KB_Target[KB] = KB_Target[KB_Times]
                      • Set KB_Distance[KB] = KB_Distance[KB_Times]
                      • Set KB_Speed[KB] = KB_Speed[KB_Times]
                      • Set KB_Spam[KB] = KB_Spam[KB_Times]
                      • Set KB_Angle[KB] = KB_Angle[KB_Times]
                    • Else - Actions
                  • Set KB = (KB - 1)
                  • Set KB_Skip = (KB_Skip - 1)
                  • Set KB_Times = (KB_Times - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • KB_Times Equal to 0
                    • Then - Actions
                      • Trigger - Turn off Knockback System <gen>
                    • Else - Actions
                • Else - Actions
                  • Set KB_Point[2] = (Position of KB_Target[KB])
                  • Set KB_Point[3] = (KB_Point[2] offset by KB_Speed[KB] towards KB_Angle[KB] degrees)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Terrain pathing at KB_Point[3] of type Walkability is off) Equal to True
                      • ((Playable map area) contains KB_Point[3]) Not equal to True
                    • Then - Actions
                      • Set KB_Distance[KB] = 0.00
                    • Else - Actions
                      • Destructible - Pick every destructible within 100.00 of KB_Point[3] and do (Actions)
                        • Loop - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • ((Picked destructible) is alive) Equal to True
                            • Then - Actions
                              • Set KB_Point[4] = (Position of (Picked destructible))
                              • Unit - Create 1 Casual Dummy for Neutral Passive at KB_Point[4] facing Default building facing degrees
                              • Unit - Add a 0.01 second Generic expiration timer to (Last created unit)
                              • Unit - Add Harvest (Ghouls Lumber) to (Last created unit)
                              • Unit - Order (Last created unit) to Harvest (Picked destructible)
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • (Current order of (Last created unit)) Equal to (Order(harvest))
                                • Then - Actions
                                  • Destructible - Kill (Picked destructible)
                                • Else - Actions
                              • Custom script: call RemoveLocation(udg_KB_Point[4])
                            • Else - Actions
                      • Custom script: call SetUnitX(udg_KB_Target[udg_KB], GetLocationX(udg_KB_Point[3]))
                      • Custom script: call SetUnitY(udg_KB_Target[udg_KB], GetLocationY(udg_KB_Point[3]))
                  • Set KB_Distance[KB] = (KB_Distance[KB] - KB_Speed[KB])
                  • Set KB_Spam[KB] = (KB_Spam[KB] + 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • KB_Spam[KB] Greater than or equal to 5
                    • Then - Actions
                      • Set KB_Spam[KB] = 0
                      • Special Effect - Create a special effect at KB_Point[3] using Abilities\Spells\Human\FlakCannons\FlakTarget.mdl
                      • Special Effect - Destroy (Last created special effect)
                    • Else - Actions
                  • Custom script: call RemoveLocation(udg_KB_Point[2])
                  • Custom script: call RemoveLocation(udg_KB_Point[3])
            • Else - Actions
  • Deviousness
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Level of Deviosness [EX] for (Attacking unit)) Greater than 0
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Deviosness [EX] for (Attacking unit)) Equal to 1
          • ((Attacked unit) is A Hero) Equal to True
        • Then - Actions
          • Hero - Modify Agility of (Attacking unit): Add 3
          • Special Effect - Create a special effect attached to the head of (Attacking unit) using Abilities\Spells\Orc\Bloodlust\BloodlustTarget.mdl
          • Special Effect - Destroy (Last created special effect)
          • Hero - Modify Agility of (Attacked unit): Subtract 3
          • Trigger - Turn off (This trigger)
          • Wait 1.00 seconds
          • Trigger - Turn on (This trigger)
          • Wait 19.00 seconds
          • Hero - Modify Agility of (Attacking unit): Subtract 3
          • Hero - Modify Agility of (Attacked unit): Add 3
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Deviosness [EX] for (Attacking unit)) Equal to 2
              • ((Attacked unit) is A Hero) Equal to True
            • Then - Actions
              • Hero - Modify Agility of (Attacking unit): Add 4
              • Special Effect - Create a special effect attached to the head of (Attacking unit) using Abilities\Spells\Orc\Bloodlust\BloodlustTarget.mdl
              • Special Effect - Destroy (Last created special effect)
              • Hero - Modify Agility of (Attacked unit): Subtract 4
              • Trigger - Turn off (This trigger)
              • Wait 1.00 seconds
              • Trigger - Turn on (This trigger)
              • Wait 29.00 seconds
              • Hero - Modify Agility of (Attacking unit): Subtract 4
              • Hero - Modify Agility of (Attacked unit): Add 4
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Level of Deviosness [EX] for (Attacking unit)) Equal to 3
                  • ((Attacked unit) is A Hero) Equal to True
                • Then - Actions
                  • Hero - Modify Agility of (Attacking unit): Add 5
                  • Special Effect - Create a special effect attached to the head of (Attacking unit) using Abilities\Spells\Orc\Bloodlust\BloodlustTarget.mdl
                  • Special Effect - Destroy (Last created special effect)
                  • Hero - Modify Agility of (Attacked unit): Subtract 5
                  • Trigger - Turn off (This trigger)
                  • Wait 1.00 seconds
                  • Trigger - Turn on (This trigger)
                  • Wait 39.00 seconds
                  • Hero - Modify Agility of (Attacking unit): Subtract 5
                  • Hero - Modify Agility of (Attacked unit): Add 5
                • Else - Actions
JASS:
function RavynWaitPS takes real duration returns nothing
    //Timer wait like thing
    local timer t
    local real  timeRemaining
    if (duration > 0) then
        set t = CreateTimer()
        call TimerStart(t, duration, false, null)
        loop
            set timeRemaining = TimerGetRemaining(t)
            exitwhen (timeRemaining <= 0)
           if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) then
                call TriggerSleepAction(0.1 * timeRemaining)
            else
                call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
            endif
        endloop
        call DestroyTimer(t)
    endif
endfunction

function PSeffects takes real distance, location uloc returns nothing
    //The eye candy, Creates the effect each effect is 30 degrees apart up to the 360 degree mark
    //i.e. 360/30 = 18 Therefore 18 effects are created.
    local unit u = GetTriggerUnit()
    local real x = 0
    local string effectstring = "Abilities\\Spells\\Undead\\DeathPact\\DeathPactTarget.mdl"    
    loop
        set x = x + 60
        call AddSpecialEffectLoc( effectstring, PolarProjectionBJ(uloc, distance, x))
        exitwhen x >= 360
    endloop
    set x = 0
    set u = null
    set effectstring = ""            
endfunction


function PSnova takes real aoesize returns nothing
    //The damaging effect of the ability, Creates the effects by calling the effect trigger
    //and damages units around the caster.
    local integer x = 0
    local integer abilityid = 'A03F'    
    local unit u = GetTriggerUnit()
    local location uloc = GetUnitLoc(GetTriggerUnit())
    local real damage = GetUnitAbilityLevel(u, abilityid) * 15
    loop
        set x = x + R2I(aoesize)/4
        call UnitDamagePoint( u, 0, aoesize, GetLocationX(uloc), GetLocationY(uloc), damage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )    
        call PSeffects(x, uloc)
        call RavynWaitPS(0.01)
        exitwhen(x >= aoesize)
    endloop
    set x = 0 
    set u = null 
    set abilityid = 0 
    call RemoveLocation(uloc)
endfunction

function Trig_Phase_Shift_Actions takes nothing returns nothing
    //The main function for Phase Shift, it determines whether or not the correct ability is case 
    //And moves through the main functions for Phase Shift. It creates the nova, the continues to 
    //double the units movement and make it invulnerable and quite transperant. It then sets
    //the units visability back quickly at first then slower as A = A - (A/X) therefore as A gets 
    //smaller A decreses by smaller amounts. After that it creates another nova asswell it sets the 
    //unit back to its orignal visual state and removes the invulnerability
    local integer x
    local integer abilityid = 'A03F' 
    local real y
    local real alpha 
    local unit u
    local real aoesize = 256      
    if ( GetSpellAbilityId() == abilityid ) then
        set u = GetTriggerUnit()
        set alpha = 0
        set x = 3
        set y = GetUnitAbilityLevel(u, abilityid) * 1
        call PSnova(aoesize)
        call SetUnitVertexColor(u, 255, 255, 255, 5)
        call SetUnitMoveSpeed(u, GetUnitMoveSpeed(u) * 1.5)
        call RavynWaitPS(y)      
        set y = y / 20
        loop    
            call RavynWaitPS(y)
            set x = x - 1
            set alpha = alpha - (alpha/x)
            call SetUnitVertexColorBJ(u, 100, 100, 100, alpha )        
            exitwhen(x == 1)
        endloop 
        call PSnova(aoesize)     
        call SetUnitMoveSpeed(u, GetUnitDefaultMoveSpeed(u))  
        call SetUnitVertexColor(u, 255, 255, 255, 255 )        
        set x = 0
        set y = 0
        set abilityid = 0
        set alpha = 0
        set u = null
        set aoesize = 0   
    endif
endfunction

//===========================================================================
function InitTrig_Phase_Cycle takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST )
    call TriggerAddAction( t, function Trig_Phase_Shift_Actions )
    set t = null
endfunction
JASS:
// * Punitive Surge v1.01 by Maker            *
// * Spell idea by Apheraz Lucent             *

// * The caster rushes to the targeted point  *
// * executing a spinning attack damaging     *
// * enemies. The caster leaves a quickly     *
// * fading "tail" of shadows of himself.     *


scope PunitiveSurge initializer Punitive_Surge

    globals

        // How fast the unit moves at the beginning
        private constant real INITIAL_SPEED = 12.
        // Speed multiplier between loops, how fast the unit accelerates
        private constant real ACCELERATION = 1.08
        // Maximum charge speed
        private constant real MAX_SPEED = 30.
        // Damage per ability level
        private constant real DAMAGE = 75.
        // Damage bonus per ability level, not applied at level 1
        private constant real BONUS_DAMAGE = 75
        // Update interval for moving loops. 1/loopTime = Frames per second
        private constant real LOOP_TIME = 0.03125
        // AoE of the spell
        private constant real RADIUS = 150.
        // Animation speed for the attack ( 1.00 = normal speed )
        private constant real ANIMATION_SPEED = 0.75
        
        
        
        // Raw code of the ability
        private constant integer ABILITYCODE = 'A03G'
        // The dummy's raw code
        private constant integer DUMMYCODE = 'E005'
        // The pathing item's raw code
        private constant integer ITEMCODE = 'I01O'
        
        // How transparent the dummies are at beginning, 255 means 100% visible, 177,5 = 50% visible
        private constant integer DUMMY_INITIAL_FADE = 175
        // How fast the dummies fade
        private constant integer FADE_RATE = 10
        // ^Play around with those values to get to desired^
        // ^tail fade time and tail length^
        
        // Vertex color values for dummy. Default caster color = 255, 255, 255
        // 0 , 0 , 0 = completely black
        private constant integer RED = 100
        private constant integer GREEN = 100
        private constant integer BLUE = 100
        
        // The animation that the dummies play
        private constant integer ANIMATION = 6
        // Attack type of the ability
        private constant attacktype ATTACK_TYPE = ATTACK_TYPE_HERO
        // Damage type of the attack
        private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
        // Effect on targets hit
        private constant string HIT_EFFECT = "Objects\\Spawnmodels\\Human\\HumanBlood\\HumanBloodFootman.mdl"
        // Effect on caster
        private constant string CASTER_WEAPON_EFFECT = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"
        // Effect attachment points for caster
        private constant string ATTACH_1 = "weapon"
        private constant string ATTACH_2 = "right hand"
        // Effect attachment point for targets
        private constant string ATTACH_3 = "chest"
        // How many different sound effects are used
        private constant integer SOUNDS = 0
        // How loud the sounds will be. 255 = 100% volume, 0 = 0% volume
        private constant integer SOUND_VOLUME = 0
        
        //** DONT CHANGE THE VARIABLES BELOW **//
        
        private unit U
        private real R
        private player P
        private group UG
        
        private sound array sounds
        
        private integer casters = 0
        private integer dummies = 0
        
        private timer casterTimer = CreateTimer()
        private timer dummyTimer = CreateTimer()
        
        private group casterGroup = CreateGroup()
        private group dummyGroup = CreateGroup()
        
        private item itemPathing
        
        private hashtable rageHash = InitHashtable()
        
    endglobals
    

    // Retuns the damage done by the spell
    private constant function getDamage takes integer i returns real
        return DAMAGE + BONUS_DAMAGE * (i - 1)
    endfunction
    
    // Returns distance between two points
    private function getDistance takes real x1 , real x2 , real y1 , real y2 returns real
        local real dx = x2 - x1
        local real dy = y2 - y1
        return SquareRoot(dx * dx + dy * dy )
    endfunction
    
    // Returns an angle between two points
    private function getAngle takes real x1 , real x2 , real y1 , real y2 returns real
        return Atan2(y2 - y1 , x2 - x1 )
    endfunction
    
    // Playes a sound on unit
    function playSoundOnUnit takes unit u , sound soundHandle returns nothing
        call AttachSoundToUnit( soundHandle , u )
        call SetSoundVolume( soundHandle , SOUND_VOLUME )
        call StartSound( soundHandle )
    endfunction
    
    // Filters unwanted units from getting damaged
    // Damages targets and applies sound and sfx
    private function unitFilter takes nothing returns boolean
        local unit v = GetFilterUnit()
        local sound s = sounds[GetRandomInt(1 , SOUNDS)]
        
        if not(IsUnitType( v , UNIT_TYPE_DEAD )) and IsUnitEnemy( v , P ) and not(IsUnitInGroup(v, UG )) and not (IsUnitType( v, UNIT_TYPE_STRUCTURE ) ) then
            call UnitDamageTarget( U , v , R , false , false , ATTACK_TYPE , DAMAGE_TYPE , WEAPON_TYPE_WHOKNOWS )
            call DestroyEffect(AddSpecialEffectTarget( HIT_EFFECT , v , "ATTACH_3" ) )
            call GroupAddUnit( UG , v )
            call playSoundOnUnit( v , s )
        endif
            
        set v = null
        set s = null
        return  true
    endfunction
    
    // Fades out and removes dummies
    private function dummyLoop takes nothing returns nothing
        local unit u = GetEnumUnit()
        local integer i1 = GetHandleId(u)
        local integer i2 = LoadInteger(rageHash , i1 , StringHash("fade") )
        if i2 > 0 then
            set i2 = i2 - FADE_RATE
            call SetUnitVertexColor(u , RED , GREEN , BLUE , i2 )
            call SaveInteger(rageHash , i1 , StringHash("fade") , i2 )
        else
            set dummies = dummies - 1
            call GroupRemoveUnit( dummyGroup , u )
            call FlushChildHashtable(rageHash , i1)
            call RemoveUnit(u)
            
            if dummies == 0 then
                call PauseTimer(dummyTimer)
            endif
        endif
        set u = null
    endfunction
    
    private function dummyTimerExpire takes nothing returns nothing
        call ForGroup( dummyGroup , function dummyLoop )
    endfunction
    
    // Moves caster and checks collision
    private function casterLoop takes nothing returns nothing
        local unit u = GetEnumUnit()
        local unit v
        local integer i1 = GetHandleId(u)
        local integer i2
        local boolean b = LoadBoolean(rageHash , i1 , StringHash("boolean") )
        local group g = CreateGroup()
        local real r1 = GetUnitX(u)
        local real r2 = GetUnitY(u)
        local real r3 = LoadReal(rageHash , i1 , StringHash("x") )
        local real r4 = LoadReal(rageHash , i1 , StringHash("y") )
        local real r5 = getDistance( r1 , r3 , r2 , r4 )
        local real r6
        local real r7
        local real r8
        
        // Checks that the caster isn't dead and that the caster isn't close to
        // the cast target point yet
        if not (IsUnitType( u , UNIT_TYPE_DEAD) ) and r5 > MAX_SPEED and b == true then
        
            set r5 = LoadReal(rageHash , i1 , StringHash("speed") ) * ACCELERATION
            set r6 = LoadReal(rageHash , i1 , StringHash("angle") )
            
            // Limits max speed
            if r5 > MAX_SPEED then
                set r5 = MAX_SPEED
            endif
            
            call SaveReal(rageHash , i1 , StringHash("speed") , r5 )
            
            // Pathability is done by moving an item to the point the caster
            // is supposed to move to. If the item's coordinates after moving it
            // do not match the move to point's coordinates, the point is unpathable.
            // If the point is pathable, move the caster there.
            // If not, stop the spell.
            // Prevents the caster from passing strcutures, trees, cliffs, pathing
            // blockers and going off the map.
            set r7 = r1 + r5 * Cos(r6)
            set r8 = r2 + r5 * Sin(r6)
            
            call SetItemVisible( itemPathing , true )
            call SetItemPosition( itemPathing , r7 , r8 )
            
            set r5 = GetItemX(itemPathing)
            set r6 = GetItemY(itemPathing)
            call SetItemVisible( itemPathing , false )
            
            if r7 == r5 and r8 == r6 then
                
                call SetUnitX(u , r7)
                call SetUnitY(u , r8)
                
                // Set globals so they can be passed used in the filter function
                set U = u
                set R = getDamage(GetUnitAbilityLevel( u , ABILITYCODE ))
                set P = GetOwningPlayer(u)
                set UG = LoadGroupHandle(rageHash , i1 , StringHash("group") )
                
                call GroupEnumUnitsInRange( g , r7 , r8 , RADIUS , function unitFilter )
                
                // Create a fading "tail" dummy
                set v = CreateUnit( Player(15) , DUMMYCODE , r1 , r2 , GetUnitFacing(u) )
                set i2 = GetHandleId(v)
                set dummies = dummies + 1
                
                call GroupAddUnit( dummyGroup , v )
                call SetUnitColor( v , GetPlayerColor( P ) )
                call SetUnitTimeScale( v , ANIMATION_SPEED )
                call SetUnitAnimationByIndex( v , ANIMATION )
                call SetUnitVertexColor( v , RED , GREEN , BLUE , DUMMY_INITIAL_FADE )
                
                call SaveInteger(rageHash , i2 , StringHash("fade") , DUMMY_INITIAL_FADE )
            
                if dummies == 1 then
                    call TimerStart( dummyTimer , LOOP_TIME , true , function dummyTimerExpire )
                endif
                
                set v = null
                
            else
                call SaveBoolean(rageHash , i1 , StringHash("boolean") , false )
            endif
        else
            set casters = casters - 1
            call GroupRemoveUnit( casterGroup , u )
            call DestroyGroup(LoadGroupHandle(rageHash, i1 , StringHash("group") ) )
            call DestroyEffect(LoadEffectHandle(rageHash , i1 , StringHash("wEffect1") ) )
            call DestroyEffect(LoadEffectHandle(rageHash , i1 , StringHash("wEffect2") ) )
            call FlushChildHashtable(rageHash , i1)
            
            if casters == 0 then
                call PauseTimer(casterTimer)
            endif
        endif
        
        call DestroyGroup(g)
        
        set u = null
        set g = null
        
    endfunction
    
     private function casterTimerExpire takes nothing returns nothing
        call ForGroup( casterGroup , function casterLoop )
    endfunction

    // This runs when the caster begins casting the ability.
    // Begins casting -event is chose over Starts the effect - event
    // since there's casting delay betweeb those events (default = 0.5 seconds).
    // Begins castin -event fires sooner. It does not bug even if the unit gets a stop
    // order during the ast time.
    private function Actions takes nothing returns nothing
    
        local unit u = GetTriggerUnit()
        local integer i = GetHandleId(u)
        local integer i2 = GetUnitAbilityLevel( u , ABILITYCODE ) 
        local real x1 = GetUnitX(u)
        local real y1 = GetUnitY(u)
        local real x2 = GetSpellTargetX()
        local real y2 = GetSpellTargetY()
        local real r1 = getDamage(i2)
        local real r2
        local real r3
        local real r4
        
        // Checks that the target point is pathable.
        // If not, use the nearest pathable point as the new
        // target point.
        call SetItemVisible( itemPathing , true )
        call SetItemPosition( itemPathing , x2 , y2 )
        
        set r3 = GetItemX(itemPathing)
        set r4 = GetItemY(itemPathing)
        
        if r3 == x2 and r4 == y2 then
            set r2 = getAngle( x1 , x2 , y1 , y2 )
        else
            set r2 = getAngle( x1 , r3 , y1 , r4 )
            set x2 = r3
            set y2 = r4
        endif
        
        call SetUnitTimeScale( u , ANIMATION_SPEED )
        call SetItemVisible( itemPathing , false )
        call GroupAddUnit(casterGroup , u)
        
        set casters = casters + 1
        set UG = CreateGroup()
        
        call SaveReal(rageHash , i , StringHash("x") , x2 )
        call SaveReal(rageHash , i , StringHash("y") , y2 )
        call SaveReal(rageHash , i , StringHash("angle") , r2 )
        call SaveReal(rageHash , i , StringHash("damage") , r1 )
        call SaveReal(rageHash , i , StringHash("speed") , INITIAL_SPEED )
        call SaveGroupHandle(rageHash , i , StringHash("group") , UG )
        call SaveBoolean(rageHash , i , StringHash("boolean") , true )
        call SaveEffectHandle(rageHash , i , StringHash("wEffect1") , AddSpecialEffectTarget(CASTER_WEAPON_EFFECT , u , ATTACH_1 ) )
        call SaveEffectHandle(rageHash , i , StringHash("wEffect2") , AddSpecialEffectTarget(CASTER_WEAPON_EFFECT , u , ATTACH_2 ) )
        
        if casters == 1 then
            call TimerStart( casterTimer , LOOP_TIME , true , function casterTimerExpire )
        endif
        
        set u = null
    endfunction
    
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == ABILITYCODE
    endfunction

    private function Punitive_Surge takes nothing returns nothing
        local trigger t = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_CAST )
        call TriggerAddCondition( t , Condition( function Conditions ) )
        call TriggerAddAction( t , function Actions )
        
        set itemPathing = CreateItem( ITEMCODE , 0 , 0 )
        call SetItemVisible( itemPathing , false )
        
        set t = null
    endfunction

endscope
 
for phase cycle:

I also want it to give unitwalking/zero collision while it lasts

Use
JASS:
SetUnitPathing(unit,boolean)
like this -

JASS:
...
    if ( GetSpellAbilityId() == abilityid ) then
        set u = GetTriggerUnit()
        call SetUnitPathing(u,false)
...

and this:

JASS:
...
        call SetUnitMoveSpeed(u, GetUnitDefaultMoveSpeed(u))  
        call SetUnitVertexColor(u, 255, 255, 255, 255 )
        call SetUnitPathing(u,true)  
        set x = 0
...

I don't want transparency.

Remove these lines:

JASS:
...
local real alpha
...
set alpha = alpha - (alpha/x)
call SetUnitVertexColorBJ(u, 100, 100, 100, alpha )
...

I also want only one blast of energy, at the end of duration, which won't damage mechanical units, allies or self. Just enemies.

Remove the first PSNova call by changing this:

JASS:
        set y = GetUnitAbilityLevel(u, abilityid) * 1
        call PSnova(aoesize)
        call SetUnitVertexColor(u, 255, 255, 255, 5)

to this:

JASS:
        set y = GetUnitAbilityLevel(u, abilityid) * 1
        call SetUnitVertexColor(u, 255, 255, 255, 5)

Second part will be more difficult but you have to change this line:

JASS:
call UnitDamagePoint( u, 0, aoesize, GetLocationX(uloc), GetLocationY(uloc), damage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )

to basically:

  1. declare global group and create it in globals block (have JassHelper?)
  2. enumerate units at that position with that range
  3. First of Group loop
  4. If FoG matches your conditions then (call UnitDamageTarget())
 
For Punitive Surge, all you need to do is:

Delete this: private item itemPathing

And these:

JASS:
call SetItemVisible( itemPathing , true )
call SetItemPosition( itemPathing , r7 , r8 )

set r5 = GetItemX(itemPathing)
set r6 = GetItemY(itemPathing)
call SetItemVisible( itemPathing , false )

And delete the checks here:

JASS:
if r7 == r5 and r8 == r6 then
    // the code that's in here should be kept
else
    call SaveBoolean(rageHash , i1 , StringHash("boolean") , false )
endif

In the Actions function, delete any line that contains the word "Item".
Meaning GetItemX, GetItemY, SetItemPosition, SetItemVisible, etc...

Also, change this:

JASS:
if r3 == x2 and r4 == y2 then
    set r2 = getAngle( x1 , x2 , y1 , y2 )
else
    set r2 = getAngle( x1 , r3 , y1 , r4 )
    set x2 = r3
    set y2 = r4
endif

to this:

set r2 = getAngle( x1 , x2 , y1 , y2 )

edit
And don't forget to remove these from the Actions too :3

local real r3
local real r4

Finally, remove this from the Init function at the bottom:

JASS:
set itemPathing = CreateItem( ITEMCODE , 0 , 0 )
call SetItemVisible( itemPathing , false )
 
Level 11
Joined
Nov 15, 2007
Messages
781
After deleting the item pathing check from Surge, you should add a check to see if the location is within the playable map area. Otherwise a unit with this ability could move out of the map completely and crash the game.
 
Level 30
Joined
Jan 31, 2010
Messages
3,551
Yes, I switched to JNPG long time ago.

Inner Rage now won't work at all. I tried to look up at what's wrong, and I found out that several variables look like they don't even exist, but they're there. Corrupt spell, my guess, so I'll just request from someone to make it for me -.-

I haven't tested Punitive Surge nor Phase Cycle yet, since the first needs an anti-boundary system, and the other one I can't understand due to my low Jass knowledge T_T

Edit: Made Inner Rage work, by replacing a corrupt Integer KB with a newly made KB_Copy. Changed it in custom scripts as well. It works, but it pushes all units away in a same random direction (it looks like it has something to do with where's the Hero facing, but this happens on, like, 50% of the time). What's wrong?
 
Last edited:
Can you paste the line here in TRIGGER tags?

You should have used the function in GUI which I believe is called "Arithmetic".


---

Edit: I've created Deviousness for you. It needs 4 triggers to work how it's intended:

libraries:
structuredDD http://www.hiveworkshop.com/forums/...ddd-structured-damage-detection-vjass-216968/
temporaryHeroAttribute http://www.hiveworkshop.com/forums/submissions-414/snippet-tempmodifyheroattrib-vjass-216972/

initializer:
registerAllHeroes - this scope is a trigger that registers all heroes on the map (both at initialization and entering playable map rect). Make sure structuredDD_ADD_ALL_UNITS is false so that unit are not registered twice.

JASS:
//This is to register all the heroes with structuredDD. If ADD_ALL_UNITS is true, DON'T USE THIS, or each unit will be indexed twice.

scope registerAllHeroes initializer i
    private function c takes nothing returns boolean
        local unit tU=GetTriggerUnit()
        if IsUnitType(tU,UNIT_TYPE_HERO) then
            call structuredDD_ddBucket.add(tU)
        endif
        set tU=null
        return false
    endfunction
    
    private function i takes nothing returns nothing
        local group grp=CreateGroup()
        local region reg=CreateRegion()
        local trigger t=CreateTrigger()
        local unit FoG
        call GroupEnumUnitsInRect(grp,bj_mapInitialPlayableArea,null)
        loop
            set FoG=FirstOfGroup(grp)
            exitwhen FoG==null
            if IsUnitType(FoG,UNIT_TYPE_HERO) then
                call structuredDD_ddBucket.add(FoG)
            endif
            call GroupRemoveUnit(grp,FoG)
        endloop
        call DestroyGroup(grp)
        call RegionAddRect(reg,bj_mapInitialPlayableArea)
        call TriggerRegisterEnterRegion(t,reg,null)
        call TriggerAddCondition(t,Condition(function c))
        set grp=null
        set reg=null
        set t=null
    endfunction
endscope

ability:
siphonAgi - This is the scope that actually handles the ability. Make sure you replace STEAL_AGI_ID with your proper raw code.

JASS:
//This scope assumes all heroes are indexed with structuredDD.
//This scope requires structuredDD and temporaryHeroAttribute

scope siphonAgi initializer i
    globals
        private constant integer STEAL_AGI_ID='AHbh'
    endglobals
    
    private function c takes nothing returns boolean
        local unit attacker=GetEventDamageSource()
        local integer abilityLevel=GetUnitAbilityLevel(attacker,STEAL_AGI_ID)
        local integer statMod
        local real duration
        if abilityLevel>0 then
            set statMod=abilityLevel+2 //You can control here with math how much the stat should modify depending on ability level.
            set duration=10.+abilityLevel*10. //Again, use math to control how much to modify the stats by from ability level.
            call temporaryHeroAttribute_add(attacker,'A',statMod,duration)
            call temporaryHeroAttribute_add(GetTriggerUnit(),'A',-1*statMod,duration)
        endif
        set attacker=null
        return false
    endfunction
    
    private function i takes nothing returns nothing
        call structuredDD_ddBucket.addHandler(Condition(function c))
    endfunction
endscope
 
Last edited:
Status
Not open for further replies.
Top