Moderator
M
Moderator
09:28, 2nd Oct 2010
TriggerHappy:
Thanks for updating your spell.
TriggerHappy:
Thanks for updating your spell.
scope Rupture // requires xebasic, xedamage, T32 optional SimError
//
//
// *Rupture*
// by baassee
//
// *Requirements*
// *xebasic by Vexorian
// *xedamage by Vexorian
// *T32 by Jesus4Lyf
// *JASSHelper version 0.A.2.B or later by Vexorian
// *Optional*
// if the NOSTACK constant is set to true, this will be needed, else not.
// *SimError by Vexorian
//
// http://www.wc3c.net/showthread.php?t=101150 - xe 0.8
// http://www.thehelper.net/forums/showthread.php/132538-Timer32 - T32
// http://www.wc3c.net/showthread.php?t=88142 - JASSHelper
// http://www.wc3c.net/showthread.php?t=101260 - SimError
//
// *WARNING AND NOTICE!*
// This map uses a renamed dummy model by Vexorian
// please download the proper one or just export this
// one, if you already have xe implented then you
// wont have to worry about this.
//
// Also the spell uses the dummy id of the xedummy so
// remember to correct it!
//
// *Changelog*
// v1.0 - Released
// v1.1 - -Fixed spelling errors Rupture instead of Rapture.
// -Fixed preloading.
// -Added a struct member lvl to the struct.
// -Fixed bug with adding unit to group when nostack == false.
// -Changed ApplyLife with RemoveUnit
// -.count is initially 0.
// -Removed creating effect and added it on damage with the xe.
// v1.2 - -Removed the showunit command
// -Now the trigger doesn't initialize 2 triggers but creates one more with NOSTACK
// -Added another check to check if the unit is dead according to TH
// -Added locals to the conditions according to TH
// v1.2b -Fixed nulling -.-
// -Removed a action.
// v1.2c -Fixed an unnecessary function call
// -Fixed Error message.
// -Now when error message shows up the caster can choose a new target.
// v1.2d -Removed a static if.
// v1.2e -Fixed another static if with the globals. nostack is now set at the init.
// v1.2f -Made the spell run with T32. Fixed a few lines.
//
//
// *Standard Information*
// This spell was totally inspired by the spell Rupture in DOTA.
// It probably dont function the same way as in DOTA but this is
// my own version of it. I made it as the tooltip says at
// http://www.playdota.com/heroes/bloodseeker/
//
// Please don't beg me to do other DOTA spells and don't complain
// about its not-originality. I didn't find any Rapture at THW when
// searching so I thought it might have been useful to someone.
//
// Implent it as the how to import tutorial says and enjoy the spell!
// Please give proper credit to Vexorian for the libraries and me for
// this spell.
//
// Yes I use GetWidgetLife() instead of the JASSHelper native UnitAlive
// because UnitAlive bugs the optimizer by the same author so to prevent
// that bug I use GetWidgetLife(), also it's faster.
//
//
// *How to import*
//
// 1. Copy the dummy unit or just copy the one from the xe with the model included!
//
// 2. Copy the abilities, Rupture and Rupture Buff.
//
// 3. Copy the buff Rupture. Remember to set the buff of the spell Rupture Buff to
// this one.
//
// 4. Make sure you have xebasic and damage in your map with proper dummy
// and dummy model. Also import T32 or just copy the T32 Trigger.
//
// 5. Copy over this trigger called Rupture.
//
// 6. Follow the setup part which will explain all values and correct the ability
// ids and the buff id.
//
// 7. Add the spell to a unit, credit proper authors and enjoy!
//
//
// *SETUP PART*
//
//
globals
//
// The ability ID of the main spell. Select it in the object editor, press
// ctrl + d and you can see the ID.
//
private constant integer ABILID = 'A000'
//
// The ability id of the buff adding spell. How to get the id, check above.
//
private constant integer DUMMYID = 'A001'
//
// The buff id. Do as with the main ABILID but in the buff section.
//
private constant integer BUFFID = 'B000'
//
// The blood effect when a unit takes damage.
//
private constant string BLOODFX = "Objects\\Spawnmodels\\Human\\HumanBlood\\HumanBloodPeasant.mdl"
//
// The attachment point where the blood fx will be attached too.
// I would recommend chest, hands or head. Leave it as it is, no
// need to change.
//
private constant string ATTACH = "chest"
//
// If you want to preload the blood fx and the ability to remove
// first cast lagg set this to true. You might suffer a longer
// loading time if you do but it will prevent first cast lagg as
// said. I would recommend it set to true.
//
private constant boolean PRELOAD = true
//
// The error message that shows up with NOSTACK (below) is true
//
private constant string MESSAGE = "Target Unit has already Rupture"
//
// The hotkey of the spell
//
private constant string HOTKEY = "R"
//
// If the damage should be 100% pure then set this to true
// else if you want to make your own damage stuff, set it to false.
//
private constant boolean PURE = true
//
// Do you want the ability to stack at the same unit?
// This can bug the spell if set to false. Use at your own risk
// The bug it can make is that the buff wont show but it will damage
// proper.
//
private constant boolean NOSTACK = true
endglobals
//
// *FUNCTIONS* (Part of the setup part)
//
//
// The duration function, takes the level of the spell.
// The buff will last as long as the duration. Also
// the movement damage.
//
private function dur takes integer lvl returns real
return 3. + 2. * lvl
endfunction
//
// The initial hit damage. Set as you want.
//
private function fdmg takes integer lvl returns real
return 50. + 100. * lvl
endfunction
//
// The movement damage in percent. As it is now it will
// damage 20% * the level of the ability * the movement
// during the period in damage.
//
private function mdmg takes integer lvl returns real
return 0.2 * lvl
endfunction
//
// The max damage function. Functions with the interval
// function below the max damage function.
//
private function maxdmg takes integer lvl returns real
return 200. + 0 * lvl
endfunction
//
// The interval for the maximum damage. It will only
// be possible to make above damage during the interval.
// If the unit moves so much that it will take more damage,
// this will prevent it. Refreshes every set amount.
//
private function maxdmginterval takes integer lvl returns real
return 0.25 + 0 * lvl
endfunction
//
// The damage options, they're explained inside the function.
// This function is useless if you have set the PURE constant
// to true. Use the function below this one for the PURE constant
// true stuff.
//
private function xeoptions takes xedamage d returns nothing
// the damage type of the spell
// this wont be affected if forcedamage
// is set to true.
set d.dtype = DAMAGE_TYPE_UNIVERSAL
// the attack type of the spell
// this wont be affected if forcedamage
// is set to true.
set d.atype = ATTACK_TYPE_CHAOS
//
// the weapon type the spell will use, affilcts the
// sound when damaged, in this case, no sound
// when damaged but I made it configurable anyway
set d.wtype = WEAPON_TYPE_WHOKNOWS
// if the damage should be ranged,
// works different when AI's hit,
// usally makes the unit move as
// it got attacked. Perfect for
// Rapture.
set d.ranged = true
// if the spell should damage enemies
// quite obvious
set d.damageEnemies = true
// if the spell should damage neutrals if
// they are targeted.
set d.damageNeutral = true
// this one below is quite special
// I use the feature of xedamage to
// try to make the pure damage as close
// as possible to the amount.
// if set to true, it will be pure
// damage, if false then the damage
// type and attack type will matter
// if this is set to false and
// damage type to universal and
// attack type to chaos, it will act
// as pure damage, if you havent mixed
// with the gameplay constants.
set d.forceDamage = true
call d.useSpecialEffect(BLOODFX, ATTACH)
endfunction
//
// The second xedamage options, just basic the same as above so
// wont explain them further but these are used when the PURE
// constant is set to true.
//
private function xepureoptions takes xedamage d returns nothing
set d.wtype = WEAPON_TYPE_WHOKNOWS
set d.ranged = true
set d.damageEnemies = true
set d.damageNeutral = true
call d.useSpecialEffect(BLOODFX, ATTACH)
endfunction
//
// *END OF SETUP*
//
globals
private xedamage xed // the xedamage instance
private group nostack //nostack group, only declared
endglobals
private struct Rupture // the struct
unit c //casting unit
unit u //target unit
integer lvl
real dmg//the movement percent
real maxdmg//the max damage per interval
real check//the interval check
real count = 0.//counter to count the interval
real X//current x of the target
real Y//current y of the target
real dur//duration of the spell
//
// creation method takes unit caster, unit target, real x of target, real y of target
//
static method create takes unit c, unit u, real x, real y returns Rupture
local Rupture this = Rupture.allocate()
set .c = c
set .u = u
set .lvl = GetUnitAbilityLevel(c, ABILID)
set .dmg = mdmg(.lvl)
set .maxdmg = maxdmg(.lvl)
set .check = maxdmginterval(.lvl)
set .X = x
set .Y = y
set .dur = dur(.lvl)
static if PURE then
call xed.damageTargetForceValue(c, u, fdmg(.lvl))
else
call xed.damageTarget(c, u, fdmg(.lvl))
endif
call UnitAddAbility(u, DUMMYID)//adds the buff spell
call UnitMakeAbilityPermanent(u, true, DUMMYID)
static if NOSTACK then
call GroupAddUnit(nostack, u)
endif
call .startPeriodic()
return this
endmethod
//
// the method loop
//
private method periodic takes nothing returns nothing
local real dx = GetUnitX(.u) - .X //these are distance stuff
local real dy = GetUnitY(.u) - .Y //to see if the unit has moved
local real sq = SquareRoot(dx * dx + dy * dy) //distance function
if .dur > 0. and GetWidgetLife(.u) > 0.405 and not IsUnitType(.u, UNIT_TYPE_DEAD)then //check if the spell has ended
//or the target is already dead
set .dur = .dur - T32_PERIOD //reduce the duration
if sq > 0. then //check if the unit has moved any distance
//next if is to check if the interval has been reached and
//the max damage hasn't been reached and also that the
//damage that is about to happen isn't greater than the maxdmg
if .count < .check and .maxdmg > 0. and (sq * .dmg) <= .maxdmg then
// we do the damage
static if PURE then
call xed.damageTargetForceValue(.c, .u, (sq * .dmg))
else
call xed.damageTarget(.c, .u, (sq * .dmg))
endif
set .maxdmg = .maxdmg - (sq * .dmg)
set .count = .count + T32_PERIOD
set .X = GetUnitX(.u)//set the new coordinates of the unit
set .Y = GetUnitY(.u)//same as above
if .count >= .check then
set .count = 0.
set .maxdmg = maxdmg(.lvl)
endif
endif
endif
else
//instance have ended then we clear leaks and removes the ability and also the buff
call .stopPeriodic()
call UnitMakeAbilityPermanent(.u, false, DUMMYID)
call UnitRemoveAbility(.u, DUMMYID)
call UnitRemoveAbility(.u, BUFFID)
static if NOSTACK then
call GroupRemoveUnit(nostack, .u)
endif
call .destroy()
endif
endmethod
static method Conditions takes nothing returns boolean
local real x
local real y
local unit c
local unit u
if GetSpellAbilityId() == ABILID then
set c = GetTriggerUnit()
set u = GetSpellTargetUnit()
set x = GetUnitX(u)
set y = GetUnitY(u)
call Rupture.create(c, u, x, y)
endif
set c = null
set u = null
return false
endmethod
static method Conditions2 takes nothing returns boolean
local unit c
local unit u
if GetSpellAbilityId() == ABILID then
set c = GetTriggerUnit()
set u = GetSpellTargetUnit()
if IsUnitInGroup(u, nostack) == true then
call IssueImmediateOrder(c, "stop")
call SimError(GetTriggerPlayer(), MESSAGE)
if GetLocalPlayer() == GetTriggerPlayer() then
call ForceUIKey(HOTKEY)
endif
endif
endif
set c = null
set u = null
return false
endmethod
static method onInit takes nothing returns nothing
//start of the trigger
local trigger t = CreateTrigger()
local trigger trg
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
// to prevent mana and cooldown loss if the constant NOSTACK is on
static if NOSTACK then
set trg = CreateTrigger()
set nostack = CreateGroup()
call TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddCondition(trg, Condition(function Rupture.Conditions2))
endif
//conditions are faster than actions? so I've heard
call TriggerAddCondition(t, Condition(function Rupture.Conditions))
//xe damage stuff
set xed = xedamage.create()
static if PURE then //checks the pure constant
call xepureoptions(xed)
else
call xeoptions(xed)
endif
//preload
static if PRELOAD then
call Preload(BLOODFX)
set bj_lastCreatedUnit = CreateUnit(Player(15), XE_DUMMY_UNITID, 0., 0., 0.)
call UnitAddAbility(bj_lastCreatedUnit, DUMMYID)
call RemoveUnit(bj_lastCreatedUnit)
endif
endmethod
implement T32x
endstruct
endscope