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 haven't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. Rubbed the right way, the genie is out of its lamp! The 12th Concept Art Contest Results have been announced.
    Dismiss Notice
  5. The Lich King has a new champion. The results for the 19th Icon Contest are here!
    Dismiss Notice
  6. Race against the odds and Reforge, Don't Refund. The 14th Techtree Contest has begun!
    Dismiss Notice
  7. 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.

Tentacle Attack v1.10

Submitted by Squiggy
This bundle is marked as substandard. It may contain bugs, not perform optimally or otherwise be in violation of the submission rules.
Tentacle Attack
[​IMG]
The target gets impaled by a tentacle - multiple other tentacles spawn and attack the victim until the spell is over.
If the victim dies, the tentacles attack random units nearby

Damage: 3 per hit
Range: 800
Type: Active
Cooldown: 8s


*Spell needs JNGP and TimerUtils
*Spell is mui and coded in vjass
*Note: This spell uses a custom value which is applied to ONE unit - the target.

Changelog
v1.0
-nothing yet

v1.1
-Put the buffid in a constant
-Removed the init-leak (thx ^^)
-Added some timer to check for the target's status to bring it down if it dies


Spellcode
Code (vJASS):
//==Tentacle Attack==
//2oo9 by Squiggy
//Spell needs jngp and TimerUtils
//Credits go to HINDYhat for teaching me jass
//The next spell will include methods, yes yes D:

scope TentacleAttack initializer Init

    globals
        private constant integer SPELLID = 'A000'        //This is the spell's id
        private constant string EFFPATH = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl"
        private constant string EFFPATH2 = "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"
        private constant integer DUMMYID = 'n000'        //Here, we aet the dummy WITHOUT the attack which impales the enemy
        private constant integer DUMMYID2 = 'n001'       //Now we set the dummy WITH attack which rapes the target
        private constant integer BUFFID = 'B000'         //And the integer for the buff is set here
        private constant real DURATION = 7               //Here goes the duration of the spell
        private constant real FLYHEIGHT = 350            //Flying height to which the target is changed
        private constant real RANDOM_MIN_X = 0           //Those are the random values for the tentacles' placement
        private constant real RANDOM_MAX_X = 400
        private constant real RANDOM_MIN_Y = 0
        private constant real RANDOM_MAX_Y = 400
        private constant real RANDOM_MIN_ANG = 0
        private constant real RANDOM_MAX_ANG = 360
        private constant real FALLRATE = 4000            //And here's the speed at which the target falls down
    endglobals

    private struct tentacle //We define all values which we need for the second part of the spell
        unit caster
        unit target
        integer i
        real tx
        real ty
        integer index
        player p
    endstruct
   
    private function Conditions takes nothing returns boolean   //First, we check which ability is being cast
        return GetSpellAbilityId() == SPELLID
    endfunction

    private function Conditions2 takes nothing returns boolean
        return GetUnitTypeId(GetTriggerUnit()) == DUMMYID       //This is the condition for the second trigger - it checks the type of the dying unit
    endfunction

    private function grpenu takes nothing returns boolean       //Group filter to your left checking for the buff 'rape'
        return GetUnitAbilityLevel(GetFilterUnit(), BUFFID)>0
    endfunction
   
    private function Tentacles takes nothing returns nothing    //Here we deal with everything aftert the first tentacle is created
        local real rndx
        local real rndy
        local real rnda
        local unit u2
        local tentacle tc = tentacle(GetTimerData(GetExpiredTimer()))   //we get the data
        set rndx = GetRandomReal(RANDOM_MIN_X, RANDOM_MAX_X)            //Now we create the dummy
        set rndy = GetRandomReal(RANDOM_MIN_Y, RANDOM_MAX_Y)
        set rnda = GetRandomReal(RANDOM_MIN_ANG, RANDOM_MAX_ANG)
        set u2 = CreateUnit(tc.p, DUMMYID2, (tc.tx + rndx*Cos((rnda)*bj_DEGTORAD)), tc.ty + rndy*Sin((rnda)*bj_DEGTORAD), rnda)
        call IssueTargetOrder(u2, "attack", tc.target)                  //We order it to attack the target
        call UnitApplyTimedLife(u2, 'BTLF', DURATION)
        call DestroyEffect(AddSpecialEffect(EFFPATH2, GetUnitX(u2), GetUnitY(u2)))            //And add an effect
        set tc.index = tc.index+1                                       //To limit the number of dummies, we set the maximum to lvl*3
        if tc.i == tc.index then
            call ReleaseTimer(GetExpiredTimer())
            set u2 = null
        endif
    endfunction
   
    private function status takes nothing returns nothing
        local tentacle tc = tentacle(GetTimerData(GetExpiredTimer()))
        if GetUnitState(tc.target, UNIT_STATE_LIFE) < 4 then
            call SetUnitUserData(tc.target, GetUnitUserData(tc.target)-1)               //Now as the instance is over, we substract 1 of the custom value
            if GetUnitUserData(tc.target) == 0 then                                     //And if there are no instances running (cv == 0),
                call SetUnitFlyHeight(tc.target, 0, FALLRATE/2)                         //we bring it down
                call tc.destroy()
            endif
            call ReleaseTimer(GetExpiredTimer())
        endif
    endfunction
   
    private function Actions takes nothing returns nothing               //Here's the first part which creates the impaling tentacle
        local unit caster = GetTriggerUnit()
        local unit u
        local real x = GetUnitX(caster)
        local real y = GetUnitY(caster)
        local timer t = NewTimer()
        local timer t2 = NewTimer()
        local tentacle tc = tentacle.create()
        call SetTimerData(t, integer(tc))
        call SetTimerData(t2, integer(tc))
        set tc.target = GetSpellTargetUnit()
        set tc.tx = GetUnitX(tc.target)
        set tc.ty = GetUnitY(tc.target)
        set tc.i = GetUnitAbilityLevel(caster, SPELLID)*3
        set tc.index = 0
        set tc.p = GetOwningPlayer(caster)
        set u = CreateUnit(tc.p, DUMMYID, tc.tx, tc.ty, 90)
        call UnitApplyTimedLife(u, 'BTLF', DURATION+1.2)
        call UnitAddAbility(tc.target, 'Amrf')                           //We add and remove 'crow form' to the target
        call UnitRemoveAbility(tc.target, 'Amrf')
        call SetUnitFlyHeight(tc.target, FLYHEIGHT, FLYHEIGHT*3)                 //And make it raise
        call DestroyEffect(AddSpecialEffectTarget(EFFPATH, tc.target, "origin"))
        call TimerStart(t, 0.2, true, function Tentacles)               //We start both timers to create the tentacles
        call TimerStart(t2, 0.03, true, function status)                 //And to check for the target's health
        call SetUnitAnimation(u, "birth")                                //Now we make the tentacle appear out of the ground and set it's animation speed to 0
        call SetUnitFlyHeight(u, 0, FLYHEIGHT*3)
        call SetUnitTimeScale(u, 0)
        call SetUnitUserData(tc.target, GetUnitUserData(tc.target)+1)    //Adding a custom value will prevent the target from falling dow too soon
        set caster = null
        set u = null
    endfunction
   
    private function Death takes nothing returns nothing                 //The third and last part is to bring the target back to the ground when the first tentacle dies
        local unit u = GetTriggerUnit()
        local unit gru
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local group g = CreateGroup()
        call SetUnitTimeScale(u, 1)
        call GroupEnumUnitsInRange(g, x, y, 100, Filter(function grpenu))   //We pick the nearby target which still has the buff 'rape'
        loop
            set gru = FirstOfGroup(g)
            exitwhen gru == null
            call SetUnitUserData(gru, GetUnitUserData(gru)-1)               //Now as the instance is over, we substract 1 of the custom value
            if GetUnitUserData(gru) == 0 then                               //And if there are no instances running (cv == 0),
                call SetUnitFlyHeight(gru, 0, FALLRATE)                     //we bring it down
            endif
            call GroupRemoveUnit(g, gru)
        endloop
        call DestroyGroup(g)
        set u = null
    endfunction
   
    private function AntiLeak takes nothing returns boolean
        return true
    endfunction
   
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local trigger t2 = CreateTrigger()
        local filterfunc f = Filter(function AntiLeak)
        local integer i = 0
        loop
            exitwhen i >= 16
            call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, f)
            call TriggerRegisterPlayerUnitEvent(t2, Player(i), EVENT_PLAYER_UNIT_DEATH, f)
            set i = i + 1
        endloop
        call TriggerAddCondition(t, Condition(function Conditions))
        call TriggerAddCondition(t2, Condition(function Conditions2))
        call TriggerAddAction(t, function Actions)
        call TriggerAddAction(t2, function Death)
        call DestroyFilter(f)
        set f = null
    endfunction
endscope


Keywords:
tentacle, attack, blood, jass, vjass, squiggy, epic, lulz
Contents

Tentacle Attack (Map)

Reviews
Moderator
17:43, 24th Sep 2009 Hanky: You need to update the map since it's not working with 1.24b right now.
  1. 17:43, 24th Sep 2009
    Hanky:
    You need to update the map since it's not working with 1.24b right now.
     
  2. Andreja

    Andreja

    Joined:
    Dec 28, 2007
    Messages:
    575
    Resources:
    0
    Resources:
    0
    First!
     
  3. Kwah

    Kwah

    Joined:
    May 9, 2007
    Messages:
    3,391
    Resources:
    8
    Icons:
    5
    Maps:
    1
    Tutorials:
    2
    Resources:
    8
    "attack"
     
  4. Deuterium

    Deuterium

    Joined:
    Mar 17, 2009
    Messages:
    1,301
    Resources:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    2
    Well, I don't like tentacle spells since they tend to get crowded... the triggering is all well, but since it's well done, I guess this deserves to be done:
    Leakless Init
    Code (vJASS):
        private function AntiLeak takes nothing returns boolean
            return true
        endfunction
       
        private function Init takes nothing returns nothing
            local trigger t = CreateTrigger()
            local trigger t2 = CreateTrigger()
            local filterfunc f = Filter(function AntiLeak)
            local integer i = 0
            loop
                call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, f)
                call TriggerRegisterPlayerUnitEvent(t2, Player(i), EVENT_PLAYER_UNIT_DEATH, f)
                set i = i + 1
                exitwhen i >= 16
            endloop
            call TriggerAddCondition(t, Condition(function Conditions))
            call TriggerAddCondition(t2, Condition(function Conditions2))
            call TriggerAddAction(t, function Actions)
            call TriggerAddAction(t2, function Death)
            call DestroyFilter(f)
            set f = null
        endfunction


    I know 32 leaks are nothing, but they're easy to remove :p

    Umm, I saw you say you will include methods in next versions, no need to do that if everything functions correctly.

    Keep it up Squig...
     
  5. Squiggy

    Squiggy

    Joined:
    Mar 25, 2008
    Messages:
    2,627
    Resources:
    18
    Maps:
    2
    Spells:
    15
    Tutorials:
    1
    Resources:
    18
    I'll just have a deeper look at them - if they're useful for some kinds of spells, I will use them fo sho' ^^
     
  6. Deuterium

    Deuterium

    Joined:
    Mar 17, 2009
    Messages:
    1,301
    Resources:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    2
    Well they are useful in the sense that you can make your own functions inside of a struct... example you can make a vector method, then outside of the struct you go like:

    call SetUnitVector(d.x, d.y, d.z)

    But it's not like it does impossible stuff :p
     
  7. Kingz

    Kingz

    Joined:
    Jun 5, 2008
    Messages:
    2,470
    Resources:
    6
    Spells:
    5
    Tutorials:
    1
    Resources:
    6
    Methods are fine.
    Besides nice to see that we got a new jasser.
    Keep it up, you are getting better :D
     
  8. -Berz-

    -Berz-

    Joined:
    Mar 5, 2008
    Messages:
    3,203
    Resources:
    123
    Icons:
    111
    Packs:
    1
    Skins:
    1
    Spells:
    10
    Resources:
    123
    RAAAEEEEAAAAAAPPPPP!!!111 xP

    Will check it latter :D
     
  9. Kingz

    Kingz

    Joined:
    Jun 5, 2008
    Messages:
    2,470
    Resources:
    6
    Spells:
    5
    Tutorials:
    1
    Resources:
    6
    Tested the spell and it looks nice, the idea is also nice and the impale effect is great.
    Just dunno why or how the fire hapens in this spell :p
    Still you got a strange aproach to spells(i personaly don't like too much effects) which is unique to you.
    All in all a good spell which deserves a recommeneded rating.
    Possible improvements:
    • replace the looping through the group with ForGroup() function
    • make the buff ID a constant
    • prevent the stacking of ability effect(buff check in the condition maybe?) as i don't really see this spell being able to stack
    • maybe make the tentacles smaller? currently their size is rather big
    • set the conditionfunc you use for GroupEnumUnitsInRange() into a variable so you can destroy it afterwards

    These are rather minor improvements/suggestions that i hope helps you.
    Gj and keep it up!
     
  10. Squiggy

    Squiggy

    Joined:
    Mar 25, 2008
    Messages:
    2,627
    Resources:
    18
    Maps:
    2
    Spells:
    15
    Tutorials:
    1
    Resources:
    18
    prevent the stacking of ability effect(buff check in the condition maybe?) as i don't really see this spell being able to stack

    That is actually wanted - if it wouldn't stack plus the ability having a cooldown of three seconds, the target wouldn't get impaled by the second instance if casted multiple times on the same unit.

    maybe make the tentacles smaller? currently their size is rather big

    I tried with scale 1.0.. what happened?
    http://www.hiveworkshop.com/forums/...height-how-the-effff-is-this-possible-134858/

    So I just enlarged them and left the height as-is.

    Might be true that I forgot to set the buffid to a constant - I'll make an update soon, anyway ^.^
     
  11. Cheezeman

    Cheezeman

    Joined:
    Aug 19, 2008
    Messages:
    488
    Resources:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    2
    The only major bug I could find (since I don't know structs yet) was that units who dies stays in the air when they die.
    This gets really annoying when killing Heroes like that Innocent Lady

    Why am I the only one who've discovered this?
     
  12. Squiggy

    Squiggy

    Joined:
    Mar 25, 2008
    Messages:
    2,627
    Resources:
    18
    Maps:
    2
    Spells:
    15
    Tutorials:
    1
    Resources:
    18
    Nope - I'll again try to fix that in the next version - the thing is that I can't refer via a buff-comparison to the target, therefore I didn't get the specifix death-event, yet
     
  13. -Berz-

    -Berz-

    Joined:
    Mar 5, 2008
    Messages:
    3,203
    Resources:
    123
    Icons:
    111
    Packs:
    1
    Skins:
    1
    Spells:
    10
    Resources:
    123
    GetUnitState(,<unit>, UNIT_STATE_LIFE) <= 0.405)

    This line might help you, it detects if unit is dead. Dunno Dark_Dragon told me that ^^
     
  14. Squiggy

    Squiggy

    Joined:
    Mar 25, 2008
    Messages:
    2,627
    Resources:
    18
    Maps:
    2
    Spells:
    15
    Tutorials:
    1
    Resources:
    18
    Why would you check if the units hp are 0.4? o_O
     
  15. -Berz-

    -Berz-

    Joined:
    Mar 5, 2008
    Messages:
    3,203
    Resources:
    123
    Icons:
    111
    Packs:
    1
    Skins:
    1
    Spells:
    10
    Resources:
    123
    Because it's the point where unit is 100% dead ^^
     
  16. Squiggy

    Squiggy

    Joined:
    Mar 25, 2008
    Messages:
    2,627
    Resources:
    18
    Maps:
    2
    Spells:
    15
    Tutorials:
    1
    Resources:
    18
    And 0.00 isn't? :D
     
  17. -Berz-

    -Berz-

    Joined:
    Mar 5, 2008
    Messages:
    3,203
    Resources:
    123
    Icons:
    111
    Packs:
    1
    Skins:
    1
    Spells:
    10
    Resources:
    123
    Look, dunno, it's how I've been told xP
     
  18. Cheezeman

    Cheezeman

    Joined:
    Aug 19, 2008
    Messages:
    488
    Resources:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    2
    A unit dies first when it reaches 0.405 hit points. Don't ask me how Blizzard designed that, but that's how it works. This is very useful because dead units can have more than 0.0 hit points.
    And you should be careful too, if a dead unit is healed with triggers it will still gain hit points, which can exceed 0.405 (yes, dead units can have 1000 hit points, but it will still be dead and decay).

    I also suggest you replace GetUnitState() with GetWidgetLife() since it's more reliable and faster (you skip that state argument too)
     
  19. Squiggy

    Squiggy

    Joined:
    Mar 25, 2008
    Messages:
    2,627
    Resources:
    18
    Maps:
    2
    Spells:
    15
    Tutorials:
    1
    Resources:
    18
    I'm always using < 0