Spellpack Hero: Tiny, the Stone Giant

soulreaping

New Member
Reaction score
17
Hey,

Here is one of my favorite heroes in DotA Allstars, Tiny.

I wrote Avalanche, Craggy Exterior and Grow! scripts myself, though they are very simple.

Thanks for emjlr3 for approving me using his script here, big credit goes for him!

All triggers are leakless as far as I checked.

This requires TT system by cohadar imported to your map.
Also, this requires vJass (JASSHelper or NewGen).

So here they are:

BTNGolemStormBolt.gif


Avalanche

Bombards an area with rocks stunning and damaging enemy land units.

Level 1 - 100 damage.
Level 2 - 180 damage.
Level 3 - 260 damage.
Level 4 - 300 damage.

Screenshot:
tiny1jq6.jpg

Script:
JASS:

scope Avalanche

globals
    private constant integer abil_id = 'A000'
    private constant integer dum_id = 'u001'
    private constant integer dum_abil_id = 'A001'
endglobals

private function Conditions takes nothing returns boolean
    return (GetSpellAbilityId() == abil_id)
endfunction

private function Actions takes nothing returns nothing
    local unit u
    local unit uu = GetTriggerUnit()
    local location loc = GetUnitLoc(uu)
    set u = CreateUnitAtLoc(GetOwningPlayer(uu), dum_id, loc, bj_UNIT_FACING)
    call RemoveLocation(loc)
    set loc = GetSpellTargetLoc()
    call UnitApplyTimedLife(u, 'BTLF', 5.)
    call UnitAddAbility(u,dum_abil_id)
    call SetUnitAbilityLevel(u, dum_abil_id, GetUnitAbilityLevel(uu, abil_id))
    call IssuePointOrderLoc(u, "clusterrockets", loc)
    call RemoveLocation(loc)
    set u = null
    set uu = null
    set loc = null
endfunction


public function InitTrig takes nothing returns nothing
    local trigger myTrig = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(myTrig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(myTrig, Condition(function Conditions))
    call TriggerAddAction(myTrig, function Actions)
endfunction

endscope

BTNattackground.gif


Toss

JASS:

scope Toss

//******************************************************************************************
//*
//*  Toss - By emjlr3, Original seen in DotA Allstars
//*
//*  Toss a friend or foe from here to there by targeting on a unit, and grabbing
//*  a random target in the area, launching them towards the targeted area.
//* 
//*  Requires:
//*    - "TT" trigger copied to your map, if not already there
//*    - The "Toss" ability copied to your map
//*    - A vJASS Preprocessor
//*
//******************************************************************************************

globals
    // Config Globals:
    private constant integer abil_id = 'A002' // Toss ability rawcode
    private constant integer fly_id = 'Amrf' // Rawcode of ability to use for fly trick, if you have not touched Crow Form, this doesn't need changing
    private constant real impact_damage = .20 // Percent of toss damage dealt to tossed unit
    private constant real time = 1. // Flight time for tossed unit (seconds)
    private constant string end_sfx = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl" // Effect created on target at end of toss
    private constant boolean kill_trees = true // Whether trees are destroyed upon target landing
    private constant attacktype attack_type = ATTACK_TYPE_NORMAL // Attack type used for damage
    private constant damagetype damage_type = DAMAGE_TYPE_DEMOLITION // Damage type used for damage
    
    // Needed Globals:
    private group G = CreateGroup()
    private unit U = null
    private rect R = null
    private location L = null
    public trigger Trigger = null // Output trigger will be Toss_Trigger, which can be used publically
endglobals
// Config. Functions:
private function Damage takes integer lvl returns real
    return 75.*lvl // Damage/lvl
endfunction
private function Area takes integer lvl returns real
    return 275. // Area within to grab units and damage units/lvl
endfunction

//========================================================================================
private struct data
    unit u
    unit targ
    player p
    real xt
    real yt
    real xl
    real yl
    real dist
    real ang
    real cos
    real sin
    real speed
    real hc
    integer lvl
    integer count = 1
    
    static method FiltIsEnemy takes nothing returns boolean
        return IsUnitEnemy(GetFilterUnit(), bj_groupEnumOwningPlayer) and GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>.405
    endmethod 
    static method DamageGroup takes unit damager, real radius, real x, real y, real amount returns nothing
        local unit u
    
        set bj_groupEnumOwningPlayer = GetOwningPlayer(damager)
        call GroupClear(G)
        call GroupEnumUnitsInRange(G, x, y, radius, Condition(function data.FiltIsEnemy)) 
        loop
            set u = FirstOfGroup(G)
            exitwhen u == null
            call GroupRemoveUnit(G,u)
            call UnitDamageTarget(damager,u,amount,false,false,attack_type,damage_type,null)
        endloop
    endmethod
    static method KillTrees_Child takes nothing returns nothing
        call KillDestructable(GetEnumDestructable())    
    endmethod
    static method KillTrees takes real x, real y, real radius returns nothing
        set R = Rect(x - radius,y - radius,x + radius,y + radius)
    
        call EnumDestructablesInRect(R,null,function data.KillTrees_Child)
        call RemoveRect(R)
        set R = null
    endmethod
    method onDestroy takes nothing returns nothing
        call SetUnitFlyHeight(.targ,GetUnitDefaultFlyHeight(.targ),0.)
		call PauseUnit(.targ,false)
		call SetUnitPathing(.targ,true)
        call UnitDamageTarget(.u,.targ,Damage(.lvl)*impact_damage,false,false,attack_type,damage_type,null)
		call DestroyEffect(AddSpecialEffectTarget(end_sfx,.targ,"origin"))
		call data.DamageGroup(.u,Area(.lvl),.xl,.yl,Damage(.lvl))
        if kill_trees then
            call data.KillTrees(.xl,.yl,Area(.lvl))
        endif
    endmethod
endstruct

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == abil_id
endfunction
private function Filt takes nothing returns boolean
    return GetFilterUnit()!=U and GetWidgetLife(GetFilterUnit())>.405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(),UNIT_TYPE_FLYING)
endfunction
private function GetSpeed takes real dist returns real
    return dist/(1./TT_PERIOD)
endfunction
private function GetCountConversion takes integer count returns real
    return (50./(time/TT_PERIOD))*count
endfunction
private function Movement takes nothing returns boolean
    local data d = TT_GetData()
    local real conv
    local real height
	local real speed 
    local real x 
    local real y 
    
    if d.count<=time/TT_PERIOD then
        set conv = GetCountConversion(d.count)
        set height = (conv-25.)*(conv-25.)
        set speed = d.count*d.speed
        set x = d.xt+speed*d.cos
        set y = d.yt+speed*d.sin
        call SetUnitX(d.targ,x)
        call SetUnitY(d.targ,y)
		call SetUnitFlyHeight(d.targ,775.-height,0.)
		set d.count = d.count + 1
        return false
	else
        call d.destroy()
        return true
    endif
endfunction
private function Actions takes nothing returns nothing
    local data d = data.create()
    
    set d.u = GetTriggerUnit()
    set d.p = GetOwningPlayer(d.u)
    set d.lvl = GetUnitAbilityLevel(d.u,abil_id)
    
    call GroupClear(G)
    set U = d.u
    call GroupEnumUnitsInRange(G,GetUnitX(d.u),GetUnitY(d.u),Area(d.lvl),Condition(function Filt))
    set d.targ = GroupPickRandomUnit(G)
    if d.targ==null then
        call d.destroy()
        return
    endif
    
    set d.xt = GetUnitX(d.targ)
    set d.yt = GetUnitY(d.targ)
    set L = GetSpellTargetLoc()
    set d.xl = GetLocationX(L)
    set d.yl = GetLocationY(L)
    set d.ang = Atan2(d.yl-d.yt,d.xl-d.xt)
    set d.cos = Cos(d.ang)
    set d.sin = Sin(d.ang)
    set d.dist = SquareRoot((d.xt-d.xl)*(d.xt-d.xl) + (d.yt-d.yl)*(d.yt-d.yl))
    set d.speed = GetSpeed(d.dist)
    
    call PauseUnit(d.targ,true)
    call SetUnitPathing(d.targ,false)
    call UnitAddAbility(d.targ,fly_id)
    call UnitRemoveAbility(d.targ,fly_id)
    
    call TT_Start(function Movement,d)
    
    call RemoveLocation(L)
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    set Trigger = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( Trigger, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( Trigger, Condition( function Conditions ) )
    call TriggerAddAction( Trigger, function Actions )
endfunction

endscope
Credit for emjlr3 for his script.

PASBTNResistantSkin.gif


Craggy Exterior

Tiny's body is made of solid granite, causing great pain to those who attack it. Whenever a melee unit attacks Tiny, there is a chance that they will be stunned for 1.2 seconds.

Level 1 - 6% chance, 25 stun damage.
Level 2 - 12% chance, 35 stun damage.
Level 3 - 18% chance, 45 stun damage.
Level 4 - 24% chance, 55 stun damage.

I can't really post a screenshot of that, sorry.

Script:
JASS:

scope CraggyExterior

globals
    private constant integer abil_id = 'A003'
    private constant integer dum_id = 'u001'
    private constant integer dum_abil_id = 'A004'
endglobals

private function Conditions takes nothing returns boolean
    return ((GetUnitAbilityLevel(GetTriggerUnit(), abil_id) > 0) and (IsUnitType(GetAttacker(), UNIT_TYPE_MELEE_ATTACKER) == true))
endfunction

private function Actions takes nothing returns nothing
    local integer i = GetRandomInt(0, 100)
    local unit u = GetTriggerUnit()
    local unit uu
    local location loc = GetUnitLoc(GetAttacker())
    local integer lvl = GetUnitAbilityLevel(u, abil_id)
    
    if (i <= 6 * lvl) then
        set uu = CreateUnitAtLoc(GetOwningPlayer(u), dum_id, loc, bj_UNIT_FACING)
        call UnitAddAbility(uu, dum_abil_id)
        call SetUnitAbilityLevel(uu, dum_abil_id, lvl)
        call UnitApplyTimedLife(uu, 'BTLF', 3.)
        call IssueTargetOrder(uu, "thunderbolt", GetAttacker())
    endif
    set u = null
    set uu = null
    call RemoveLocation(loc)
    set loc = null
endfunction

public function InitTrig takes nothing returns nothing
    local trigger myTrig = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(myTrig, EVENT_PLAYER_UNIT_ATTACKED)
    call TriggerAddCondition(myTrig, Condition(function Conditions))
    call TriggerAddAction(myTrig, function Actions)
endfunction

endscope

PASBTNTinyGrow.gif


Grow!

Greatly increases Tiny's power and size, but does so at the cost of his attack speed. Improves toss damage and slightly increases move speed.

Level 1 - 40 bonus damage, 20% reduced attack speed.
Level 2 - 80 bonus damage, 35% reduced attack speed.
Level 3 - 120 bonus damage, 50% reduced attack speed.

Screenshot:
tiny3kn5.jpg

Script:
JASS:

scope Grow

globals
    private constant integer abil_id = 'A005'
    private constant integer upg_id = 'R000'
endglobals

struct Grow
    unit u
endstruct

private function Check takes nothing returns nothing
    local Grow g = Grow.create()
    local integer lvl = GetUnitAbilityLevel(g.u, abil_id)
    if (GetWidgetLife(g.u) > .405) then
        call SetUnitScale(g.u, .5 + .25*lvl, .5 + .25*lvl, .5 + .25*lvl)
    endif
    call g.destroy()
endfunction

private function Conditions takes nothing returns boolean
    return (GetLearnedSkill() == abil_id)
endfunction

private function Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local trigger myTrig = CreateTrigger()
    local integer lvl = GetUnitAbilityLevel(u, abil_id)
    local Grow g = Grow.create()
    call SetPlayerTechResearched(GetOwningPlayer(u), upg_id, lvl)
    call SetUnitScale(u, .5 + .25*lvl, .5 + .25*lvl, .5 + .25*lvl)
    if (lvl == 1) then
        set g.u = u
        call TriggerRegisterTimerEvent(myTrig, 1., true)
        call TriggerAddAction(myTrig, function Check)
    endif    
    set u = null
    call g.destroy()
endfunction

public function InitTrig takes nothing returns nothing
    local trigger myTrig = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(myTrig, EVENT_PLAYER_HERO_SKILL)
    call TriggerAddCondition(myTrig, Condition(function Conditions))
    call TriggerAddAction(myTrig, function Actions)
endfunction

endscope

As you see, except Toss, the spells are pretty simple to code.

Have fun with it, and if you find any bug / leak I didn't, just post it here.

Thanks to Tinki3 for his spell template map.

Please comment.View attachment 14365
 

Attachments

  • TinyHero.w3x
    83.6 KB · Views: 735

Tom Jones

N/A
Reaction score
437
On attack if I'm not mistaken.

*Edit*
Locations should also be nulled.

Is that emilj3rs Toss? If so please respect the guideline/rule about not submitting other peoples work.

Keep it up.
 

hell_knight

Playing WoW
Reaction score
126
No , dota doesn't use an attack detection system it just uses the normal BJ where it gets whena unit is attacked.

Proof?
Spirit Breaker - Enpowering Haste - Damage done BEFORE you actually swing.
Ursa - Same story.
Craggy Exterior - same story
 

vypur85

Hibernate
Reaction score
803
I think for the Grow! ability, there is some periodic trigger (not sure) that makes sure that Tiny's size is correct. Because there is some bug that makes the Tiny's size reduced when being Frost Nova. Or when it dies and revived. Same applies to Phantom Assassin's Blur. But I say this from my observation when playing DotA, I'm not really sure about it trigger-wise.
 

emjlr3

Change can be a good thing
Reaction score
395
my spell is here, without permission....even though credit is given, that is not right
 

Tom Jones

N/A
Reaction score
437
No , dota doesn't use an attack detection system it just uses the normal BJ where it gets whena unit is attacked.

Proof?
Spirit Breaker - Enpowering Haste - Damage done BEFORE you actually swing.
Ursa - Same story.
Craggy Exterior - same story
Not true, and the swing in Empowering Haste is triggered. Dota does indeed use a damage detection system, think of Impetus, Arcane Orb, Glaives of Wisdom, etc.
 

--Thanatos--

New Member
Reaction score
33
But Jones, yeah, Impetus, Arcane Orb, Glaives of Wisdom, and etc. you said uses damage detection system. However, it wasn't for Backstab and Greater Bash.
IceFrog uses Damage Detection System only for Orb Abilities.
 

soulreaping

New Member
Reaction score
17
Ok a few clarifications here:

1 - Craggy prevents the entire attack, from my experience with Tiny so I coded it that way.
2 - emjlr3, since you published it I thought it was ok, it's just another way to sort of advertise your spell. If you are not right with that, I'll remove it.
3 - About the Grow!, there is sense in what you are saying, vypur85, I'll update that.
 

soulreaping

New Member
Reaction score
17
Ok so I removed the Toss ability, and I added the Grow! suggestion for the periodic trigger.

And sorry emjlr3 for not asking for permission.
 

waaaks!

Zinctified
Reaction score
255
So where is ur own made toss ability

also...all the spells can be made in GUI....and more people like GUI than jass
and also, u used vjass for it, which makes people need to use newgen pack just to use the scripts

i suggest making it WE friendly scripts
 

soulreaping

New Member
Reaction score
17
My own Toss ability will come when I'll have the time.

I made it JASS because I hate GUI. It uses all those nasty BJs which we should all try to avoid.

I know most of the people here are GUIers, but JASS is so much better and flexible, and because these spells are pretty simple, it's good to learn from them.

And if people do use these spells, means they do use JASS and should have JASSHelper since it's much better than the WE normal compiler.
 

Cohadar

master of fugue
Reaction score
209
Dota does indeed use a damage detection system, think of Impetus, Arcane Orb, Glaives of Wisdom, etc.

nope, there is no such thing in dota.
I have looked at unprotected dota code and all those spells register unit_damaged event on cast.
 

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
Reaction score
180
>>Dota does indeed use a damage detection system, think of Impetus, Arcane Orb, Glaives of Wisdom, etc.
>>and all those spells register unit_damaged event on cast.
Aren't they are mostly same? It just need to trigger the trigger when a unit is damaged. (Or maybe attacked...when damaged is dealt)
 

emjlr3

Change can be a good thing
Reaction score
395
you can use Toss, just don't make assumptions next time around, the Tiny hero is not exactly completel without Toss is he
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top