Spell Rupture - Dota

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
Rupture
Made by Blitz.
Idea by Icefrog :p.




  • [*]vJass
    [*]Mui
    [*]Leakless
    [*]Lagless​


Requires
  • NewGen
  • TimerUtils Blue
  • TimerUtils v1.23 no 'b'

Description:

Deals a mighty blow to the enemy causing any movement to result in bleeding and loss of life.

Level 1 - 150 initial damage and 20% of the distance in damage.
Level 2 - 250 initial damage and 40% of the distance in damage.
Level 3 - 350 initial damage and 60% of the distance in damage.

Screenshot

rupture.jpg


Code
The code is not that big, 100 lines of code.​
JASS:

//TESH.scrollpos=57
//TESH.alwaysfold=0
scope Rupture initializer Init
    globals
        private constant integer SPELL_ID = 'A000' //Id of the Spell.
        private constant integer DUMMY_ID = 'buff' //Id of the dummy unit.
        private constant integer BUFFER_ID = 'A001' //Id of the spell that gives the buff.
        private constant string BLOOD_EFFECT = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl"
        //What the blood look-like.
        private constant attacktype AT = ATTACK_TYPE_HERO //Attack type of the damage.
        private constant damagetype DT = DAMAGE_TYPE_UNIVERSAL //Damage type of the damage.
        private constant weapontype WT = WEAPON_TYPE_WHOKNOWS //Weapon type.
        private constant integer ADJUST = 30 //Modify the damage dealed when the units move.
        private constant real HAPPENNING = 0.02 //Periodic event, if you want.
        private constant real PERCENT = 20 //Base percent of bonus per level.
        private constant real INITIALDMG_V1 = 100.00 //Base dmg, whatever is the ability level.
        private constant real INITIALDMG_V2 = 50.00 //Add this value to base dmg per level.
        private constant integer INITIAL_COUNT = 100 //Base, the MULTI_COUNT will be added and multiplied to this.
        private constant integer MULTI_COUNT = 150 //Multiplied by level and added to INITIAL_COUNT.
    endglobals
//=======================================================================================
//===============DO NOT TOUCH BELOW UNLESS YOU KNOW WHAT YOU DO!!=====================
//=======================================================================================
private struct data
    unit caster
    unit target
    timer tim
    integer execs
    integer maxcounts
    real cx
    real cy
    real nx
    real ny
    real percent
endstruct

private function Cond takes nothing returns boolean
    return GetSpellAbilityId() == SPELL_ID
endfunction

private function Period takes nothing returns nothing
    local data d = GetTimerData(GetExpiredTimer())
    local real dx
    local real dy
    local real value
    local real dmg
    set d.execs = d.execs + 1
    set d.nx = GetUnitX(d.target)
    set d.ny = GetUnitY(d.target)
    set dx = d.cx - d.nx
    set dy = d.cy - d.ny
    set value = SquareRoot(dx * dx + dy * dy)
    if value > 0.00 then
        set dmg = value / d.percent
        call UnitDamageTarget(d.caster, d.target, dmg, true, false, AT, DT, WT)
        call DestroyEffect(AddSpecialEffect(BLOOD_EFFECT, d.nx, d.ny))
    endif
    set d.cx = GetUnitX(d.target)
    set d.cy = GetUnitY(d.target)
    if d.execs == d.maxcounts then
        call ReleaseTimer(GetExpiredTimer())
    endif
endfunction

private function Act takes nothing returns nothing
    local data d = data.create()
    local real damage = INITIALDMG_V1 * I2R(GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID)) + INITIALDMG_V2
    local real x = GetUnitX(GetSpellTargetUnit())
    local real y = GetUnitY(GetSpellTargetUnit())
    local real count = PERCENT * I2R(GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID))
    local unit u
    
    set d.caster = GetTriggerUnit()
    set d.target = GetSpellTargetUnit()
    set d.execs = 0
    set d.maxcounts = INITIAL_COUNT * GetUnitAbilityLevel(d.caster, SPELL_ID) + MULTI_COUNT
    set d.cx = x
    set d.cy = y
    set d.percent = (100.00 - count) / I2R(ADJUST)
    call UnitDamageTarget(d.caster, d.target, damage, true, false, AT, DT, WT)
    call DestroyEffect(AddSpecialEffect(BLOOD_EFFECT, x, y))
    set d.tim = NewTimer()
    call TimerStart(d.tim, HAPPENNING, true, function Period)
    call SetTimerData(d.tim, d)
    
    set u = CreateUnit(GetOwningPlayer(d.caster), DUMMY_ID, d.cx, d.cy, 0.00)
    call UnitAddAbility(u, BUFFER_ID)
    call SetUnitAbilityLevel(u, BUFFER_ID, GetUnitAbilityLevel(d.caster, SPELL_ID))
    call IssueTargetOrder(u, "purge", d.target)
    call UnitApplyTimedLife(u, 'BTLF', 1.00)
    set u = null
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Cond))
    call TriggerAddAction(t, function Act)
endfunction
endscope

TestMap
There's unit that contsantly spawn, you have to rupt them, they keep running and they die!!
 

BlackRose

Forum User
Reaction score
239

Configurable please?

Also, do you destroy your struct when the spell ends at all?
JASS:
private constant integer ADJUST = 30 //Modify the damage dealed when the units move.


Better if it was a configurable function. I want per level stuff you see?
JASS:
call TimerStart(d.tim, 0.02, true, function Period)

Naughty 0.02. Configurable.

JASS:
    set u = CreateUnit(GetOwningPlayer(d.caster), DUMMY_ID, d.cx, d.cy, 0.00)
    call UnitAddAbility(u, BUFFER_ID)
    call SetUnitAbilityLevel(u, BUFFER_ID, GetUnitAbilityLevel(d.caster, SPELL_ID))
    call IssueTargetOrder(u, "purge", d.target)
    call UnitApplyTimedLife(u, 'BTLF', 1.00)
    set u = null

1 Global dummy unit that does all the purging instead?

EDIT: Yes I tested it, please add tooltips, and make the Rupture not be able to cast on yourself Lol!
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
Useless, there's only one unit to buff.

The rest will be patched in next version. :)
But unless configurables, no leak?

Have you tried it?
 

RaiJin

New Member
Reaction score
40
JASS:
    set u = CreateUnit(GetOwningPlayer(d.caster), DUMMY_ID, d.cx, d.cy, 0.00)
    call UnitAddAbility(u, BUFFER_ID)
    call SetUnitAbilityLevel(u, BUFFER_ID, GetUnitAbilityLevel(d.caster, SPELL_ID))
    call IssueTargetOrder(u, "purge", d.target)
    call UnitApplyTimedLife(u, 'BTLF', 1.00)
    set u = null

1 Global dummy unit that does all the purging instead?

i don't think that would work


JASS:
local real count = 20.00 * I2R(GetUnitAbilityLevel(d.caster, SPELL_ID))


d.caster isn't set to anything yet
 

BlackRose

Forum User
Reaction score
239
Why wouldn't it work? Animation time set to 0.00, casting time set to 0.00. Just move around and change owner. Though I am having problems with this in a loop.

JASS:
    local real damage = 100 * I2R(GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID)) + 50
    local real x = GetUnitX(GetSpellTargetUnit())
    local real y = GetUnitY(GetSpellTargetUnit())
    local real count = 20.00 * I2R(GetUnitAbilityLevel(d.caster, SPELL_ID))

Though GetTriggerUnit() is supposedly a really fast native, why use it then set it again.

Also, save function call by setting level into a struct member.
Remember to destroy the struct afterwards.
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
O rly.
Just one thing. How would you make a private function configurable?

Why wouldn't it work? Animation time set to 0.00, casting time set to 0.00. Just move around and change owner. Though I am having problems with this in a loop.

Anyways, it would be useless. Only 1 dude to buff.
 

BlackRose

Forum User
Reaction score
239
DAMMIT. RaiJin beat me :D

View my Glaive Bounce functions.
JASS:
    // Damage. It is level * 20 right now, so its 20/40/60/80
    private function GetDamage takes integer Level returns real
        return Level * 20.
    endfunction
    
    // Speed of the missile moving.
    private function GetSpeed takes integer Level returns real
        return Level * 30.
    endfunction
    
    // How many bounces there are.
    private function GetBounces takes integer Level returns real
        return Level * 5.
    endfunction
    
    // Or how long will the spell last.
    private function GetTime takes integer Level returns real
        return Level * 4.
    endfunction
 

gameman

It's been a long, long time.
Reaction score
96
I think this is a wonderful spell, my only critique is that it should slow you as well.
 

BlackRose

Forum User
Reaction score
239
JASS:
UnitDamageTarget(d.caster, d.target, dmg, true, false, AT, DT, WEAPON_TYPE_WHOKNOWS)

You have the global WT, but still you using this.

JASS:
if d.execs == d.maxcounts then
    call ReleaseTimer(GetExpiredTimer())
endif

I'm pretty sure you don't destroy the struct.

Also, it is DotA, not Dota.
And, you do know of |n instead of " " in your tooltips. Where is the learn tooltip as well?

thats all about prefrences doing that would change the whole spell and slowing would completely kill the whole idea of this skill, because if the farther he travels damages him, why would you slow him?
Gameplay, don't slow him, real life, yes.
 

RaiJin

New Member
Reaction score
40
I think this is a wonderful spell, my only critique is that it should slow you as well.

thats all about prefrences doing that would change the whole spell and slowing would completely kill the whole idea of this skill, because if the farther he travels damages him, why would you slow him?
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
thats all about prefrences doing that would change the whole spell and slowing would completely kill the whole idea of this skill, because if the farther he travels damages him, why would you slow him?

Didn't tought about that but that f?%? true lol!
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
I found a bug. If you ruptures that guy and it teleports to other place, it will instant die.
 

Romek

Super Moderator
Reaction score
963
> TimerUtils Blue
It doesn't matter which flavour you use.

I'm worried about someone submitting a spell when they've only known Jass for such a short time. I often tell people to learn before they submit.
Then again, I haven't read the code yet. So I don't know how it is. :p

Ignore this:
JASS:
/*Testing The comments
For a few lines
And more*/ local agent a

call BJD/*Hello*/ebugMsg("Testing /*Comments in here*/ Lol")
// Comparison
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
I found a bug. If you ruptures that guy and it teleports to other place, it will instant die.
Any clues with this?

Could I put "if rangee is lower than 1000 and greater than 0" for example?
 

Kenny

Back for now.
Reaction score
202
Could I put "if rangee is lower than 1000 and greater than 0" for example?

I'm pretty sure Dota usesa value of around 200.00. If a unit can travel 200 distance in 0.02 seconds, it is probably not "moving" but "blinking".

You should also make some configurable functions, especially for damage. Something like:

JASS:
private constant function INITIAL_DAMAGE takes integer level returns real
    return 50.00 + (100.00 * level)
endfunction


JASS:
private constant function PERC_DAMAGE takes integer level returns real
    return 0.20 * level
endfunction


Makes it easier to read and configure.

I also see that you never you destroy the struct instance, just release the timer. Also whats up the the maxcount thing? Your should be using a real value for time, and setting it to a duration then count down to 0.00.
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
you can't convert integer to real in a private constant function...

Better now?

JASS:

scope Rupture initializer Init
    globals
        private constant integer SPELL_ID = 'A000' //Id of the Spell.
        private constant integer DUMMY_ID = 'buff' //Id of the dummy unit.
        private constant integer BUFFER_ID = 'A001' //Id of the spell that gives the buff.
        private constant string BLOOD_EFFECT = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl"
        //What the blood look-like.
        private constant attacktype AT = ATTACK_TYPE_HERO //Attack type of the damage.
        private constant damagetype DT = DAMAGE_TYPE_UNIVERSAL //Damage type of the damage.
        private constant weapontype WT = WEAPON_TYPE_WHOKNOWS //Weapon type.
        private constant integer ADJUST = 30 //Modify the damage dealed when the units move.
        private constant real HAPPENNING = 0.02 //Periodic event, if you want.
        private constant integer INITIAL_COUNT = 100 //Base, the MULTI_COUNT will be added and multiplied to this.
        private constant integer MULTI_COUNT = 150 //Multiplied by level and added to INITIAL_COUNT.
    endglobals
    
private function Initial_Damage takes integer level returns real
    return 50 + 100 * I2R(level)
endfunction
private function Percent_Damage takes integer level returns real
    return 0.20 * I2R(level)
endfunction
//=======================================================================================
//===============DO NOT TOUCH BELOW UNLESS YOU KNOW WHAT YOU DO!!=====================
//=======================================================================================
private struct data
    unit caster
    unit target
    timer tim
    integer execs
    integer maxcounts
    real cx
    real cy
    real nx
    real ny
    real percent
endstruct

private function Cond takes nothing returns boolean
    return GetSpellAbilityId() == SPELL_ID
endfunction

private function Period takes nothing returns nothing
    local data d = GetTimerData(GetExpiredTimer())
    local real dx
    local real dy
    local real value
    local real dmg
    set d.execs = d.execs + 1
    set d.nx = GetUnitX(d.target)
    set d.ny = GetUnitY(d.target)
    set dx = d.cx - d.nx
    set dy = d.cy - d.ny
    set value = SquareRoot(dx * dx + dy * dy)
    if value > 0.00 and value < 200.00 then
        set dmg = value / d.percent
        call UnitDamageTarget(d.caster, d.target, dmg, true, false, AT, DT, WEAPON_TYPE_WHOKNOWS)
        call DestroyEffect(AddSpecialEffect(BLOOD_EFFECT, d.nx, d.ny))
    endif
    set d.cx = GetUnitX(d.target)
    set d.cy = GetUnitY(d.target)
    if d.execs == d.maxcounts then
        call ReleaseTimer(GetExpiredTimer())
    endif
endfunction

private function Act takes nothing returns nothing
    local data d = data.create()
    local real x = GetUnitX(GetSpellTargetUnit())
    local real y = GetUnitY(GetSpellTargetUnit())
    local integer i = GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ID)
    local real count = Percent_Damage(i)
    local real damage = Initial_Damage(i)
    local unit u
    
    set d.caster = GetTriggerUnit()
    set d.target = GetSpellTargetUnit()
    set d.execs = 0
    set d.maxcounts = INITIAL_COUNT * i + MULTI_COUNT
    set d.cx = x
    set d.cy = y
    set d.percent = (100.00 - count) / I2R(ADJUST)
    call UnitDamageTarget(d.caster, d.target, damage, true, false, AT, DT, WT)
    call DestroyEffect(AddSpecialEffect(BLOOD_EFFECT, x, y))
    set d.tim = NewTimer()
    call TimerStart(d.tim, HAPPENNING, true, function Period)
    call SetTimerData(d.tim, d)
    
    set u = CreateUnit(GetOwningPlayer(d.caster), DUMMY_ID, d.cx, d.cy, 0.00)
    call UnitAddAbility(u, BUFFER_ID)
    call SetUnitAbilityLevel(u, BUFFER_ID, i)
    call IssueTargetOrder(u, "purge", d.target)
    call UnitApplyTimedLife(u, 'BTLF', 1.00)
    set u = null
    call TriggerSleepAction(0.50)
    call SetUnitAnimationByIndex(d.caster, 3)
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Cond))
    call TriggerAddAction(t, function Act)
endfunction
endscope
 

Larcenist

REP: Respect, Envy, Prosperity?
Reaction score
211
JASS:
private function Initial_Damage takes integer level returns real
    return 50 + 100 * I2R(level)
endfunction
private function Percent_Damage takes integer level returns real
    return 0.20 * I2R(level)
endfunction


What's with those useless I2R() conversions?

Just make it like this instead:
JASS:
private function Initial_Damage takes integer level returns real
    return 50. + 100. * level
endfunction
private function Percent_Damage takes integer level returns real
    return 0.20 * level
endfunction


And make those damage amounts globals to begin with...
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top