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. Race against the odds and Reforge, Don't Refund. The 14th Techtree Contest has begun!
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Trigger Viewer

Tentacle.Attack.v1.0-S.w3x
Variables
Tentacle.Attack.v1.0-S
Read Me
TentacleAttack
TimerUtils
Other stuff
lvl
Kartenspezifischen eigenen Skript-Code unten eingeben. Dieser Text wird in das Karten-Skript nach der Deklaration der Variablen und vor jeglichem Auslöser-Code eingefügt.

		
Name Type Is Array Initial Value
i integer Yes
Integer integer Yes
To make this spell work properly, export:
*This category (Tentacle.Attack.v1.0-S) including all triggers
*The buff 'rape'
*The ability 'Tentacle Attack
*Both dummy units 'TC_dummy' and 'TC_dummy2'

The comments behind the script walk you thtough the different parts of the spell - therefore I only added a short description in the spelltrigger.
If you have a creep respawn system, remember to exclude the two dummies from being resurrected

Have fun,
Squiggy
So.. here's a short summary on how the spell works:
Using a change of the flyheight, I create a tentacle under the target to make it look like it's impaled.
After, lvl*3 tentacles are spawned around the target which are ordered to attack the target for 7 seconds - after, they're killed and the target brought back to the ground.

Note: This spell uses a custom value which is applied to ONE unit - the target.
//TESH.scrollpos=47
//TESH.alwaysfold=0
//==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 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(), 'B000')>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
            call tc.destroy()
        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))
        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)
        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 Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local trigger t2 = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_DEATH)
        call TriggerAddCondition(t, Condition(function Conditions))
        call TriggerAddCondition(t2, Condition(function Conditions2))
        call TriggerAddAction(t, function Actions)
        call TriggerAddAction(t2, function Death)
    endfunction
endscope
//TESH.scrollpos=13
//TESH.alwaysfold=0
library_once TimerUtils
//*********************************************************************
//* TimerUtils (Blue flavor)
//* ----------
//*
//*  To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//*  To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass)   More scripts: htt://www.wc3campaigns.net
//*
//* For your timer needs:
//*  * Attaching
//*  * Recycling (with double-free protection)
//*
//* set t=NewTimer()      : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t)       : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2)     : Attach value 2 to timer
//* GetTimerData(t)       : Get the timer's value.
//*                         You can assume a timer's value is 0
//*                         after NewTimer.
//*
//* Blue Flavor: Slower than the red flavor, it got a 408000 handle id
//*             limit, which means that if more than 408000 handle ids
//*             are used in your map, TimerUtils might fail, this
//*             value is quite big and it is much bigger than the
//*             timer limit in Red flavor.
//*
//********************************************************************

//================================================================
    globals
        private constant integer MAX_HANDLE_ID_COUNT = 40800
        // values lower than 8191: very fast, but very unsafe.
        // values bigger than 8191: not that fast, the bigger the number is the slower the function gets
        // Most maps don't really need a value bigger than 50000 here, but if you are unsure, leave it
        // as the rather inflated value of 408000
    endglobals

    //=================================================================================================
    private function H2I takes handle h returns integer
        return h
        return 0
    endfunction

    //==================================================================================================
    globals
        private integer array data[MAX_HANDLE_ID_COUNT]
        private constant integer MIN_HANDLE_ID=0x100000
    endglobals

    //It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
    function SetTimerData takes timer t, integer value returns nothing
        debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
        debug     call BJDebugMsg("SetTimerData: Handle id too big, increase the max handle id count or use gamecache instead")
        debug endif
        set data[H2I(t)-MIN_HANDLE_ID]=value
    endfunction

    function GetTimerData takes timer t returns integer
        debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
        debug     call BJDebugMsg("GetTimerData: Handle id too big, increase the max handle id count or use gamecache instead")
        debug endif
        return data[H2I(t)-MIN_HANDLE_ID]
    endfunction

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

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

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

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

endlibrary


 
lvl
  Events
    Player - Player 1 (Red) types a chat message containing -lvlmax (stringnoformat) as An exact match
  Conditions
  Actions
    Hero - Set Mutation 0000 <gen> Hero-level to 10, Show level-up graphics