Moderator
M
Moderator
01:21, 31st Dec 2012
Magtheridon96: Approved.
This is a useful resource.
Magtheridon96: Approved.
This is a useful resource.
scope SpellSteal initializer onInit//by edo494 v1.1
/*
*
* This spell requires(all of those are provided in the test map):
*
* TimerUtils - http://www.wc3c.net/showthread.php?t=101322
*
* GetLastCastAbility - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-getlastcastability-220717/
*
* RegisterSpellEffectEvent - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193/
*
*
/=============================================================
*
*
* configurables in the spell: - time which you have the stolen spell(on each level)
* - damage when the missile lands(on each level)
* - attack type of the damage
* - damage type of the damage
* - ID of the spell
* - effect the missile uses
* - effect upon impact
* - whether we want 3 effects for missile or just one
*
/==============================================================
*
* globals
*
*
* private real array time
*
* private real array damage
*
* both of them are configurable right under the globals block in function Settings
*
*
* private constant attacktype ATT_TYPE
*
* private constant damagetype DMG_TYPE
*
* attack and damage types of the spell
*
*
* private constant integer SPELLRC
*
* spells ID
*
*
* private constant string MISSILE_EFFECT
*
* private constant string EXPLOSION_EFFECT
*
* effects used as missile and explosion - happens when missile gets closer then 50 to the target unit
* at that time also spell steal happens
*
*
* private constant boolean WANT_3_EFFS
*
* if you want to use huge missile, basically if we are creating 3(true) effects for missile or 1(false)
*
* endglobals
*/
globals
private real array time
private real array damage
private constant attacktype ATT_TYPE = ATTACK_TYPE_HERO
private constant damagetype DMG_TYPE = DAMAGE_TYPE_MAGIC
private constant integer SPELLRC = 'A000'
private constant string MISSILE_EFFECT = "Abilities\\Weapons\\GreenDragonMissile\\GreenDragonMissile.mdl"
private constant string EXPLOSION_EFFECT = "Units\\NightElf\\Wisp\\WispExplode.mdl"
private constant boolean WANT_3_EFFS = true
endglobals
private function Settings takes nothing returns nothing
set time[1] = 60
set time[2] = 75
set time[3] = 90 /*
use index which is equivalent to the level, so if I had 4th level
I would use time[4]
*/
set damage[1] = 20
set damage[2] = 50
set damage[3] = 90 /*
the same applies here
*/
call LastAbilityAddFilter(SPELLRC)
/*
Why would we want to steal spell steal?
*/
endfunction
private struct spsteal
private unit stealer
private integer stolen
private real startx
private real starty
private unit target
private effect explosion
static method decay takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = GetTimerData(t)
call UnitRemoveAbility(stealer, stolen)
call ReleaseTimer(t)
set stealer = null
set target = null
call DestroyEffect(explosion) //yes, 60 seconds delay from creation but oh well, at least
//we are not requesting another timer from TimerUtils
set explosion = null
set t = null
call deallocate()
endmethod
private static method seffect takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = GetTimerData(t)
local real dx = startx - GetUnitX(target)
local real dy = starty - GetUnitY(target)
local real angle = 0
if (dx*dx + dy*dy) > 2500 then
set angle = Atan2(GetUnitY(target) - starty, GetUnitX(target) - startx)
set startx = startx + 35 * Cos(angle)
set starty = starty + 35 * Sin(angle)
call DestroyEffect(AddSpecialEffect(MISSILE_EFFECT, startx, starty))
static if WANT_3_EFFS then //this is on purpose moved so you can see it clearly
call DestroyEffect(AddSpecialEffect(MISSILE_EFFECT, startx-10, starty-10))
call DestroyEffect(AddSpecialEffect(MISSILE_EFFECT, startx+10, starty+10))
endif
call TimerStart(t, 0.05, false, function thistype.seffect)
else
set explosion = AddSpecialEffect(EXPLOSION_EFFECT, GetUnitX(target), GetUnitY(target))
call UnitAddAbility(stealer, stolen)
call SetUnitAbilityLevel(stealer, stolen, GetUnitAbilityLevel(target, stolen))
call TimerStart(t, time[GetUnitAbilityLevel(target, stolen)], false, function thistype.decay)
call UnitDamageTarget(stealer, target, damage[GetUnitAbilityLevel(stealer, SPELLRC)], true, false, ATT_TYPE, DMG_TYPE, null)
endif
set t = null
endmethod
static method create takes unit u, integer tosteal, unit utarget returns thistype
local thistype this = .allocate()
set stealer = u
set stolen = tosteal
set target = utarget
set startx = GetUnitX(u)
set starty = GetUnitY(u)
//intial effect
call DestroyEffect(AddSpecialEffect(MISSILE_EFFECT, startx, starty))
static if WANT_3_EFFS then
call DestroyEffect(AddSpecialEffect(MISSILE_EFFECT, startx-10, starty-10))
call DestroyEffect(AddSpecialEffect(MISSILE_EFFECT, startx+10, starty+10))
endif
//other effects
call TimerStart(NewTimerEx(this), 0.05, false, function thistype.seffect)
return this
endmethod
endstruct
private function body takes nothing returns nothing
local spsteal steal = spsteal.create(GetTriggerUnit(),GetUnitLastCastAbility(GetSpellTargetUnit()), GetSpellTargetUnit())
endfunction
private function onInit takes nothing returns nothing
call ExecuteFunc(SCOPE_PRIVATE+"Settings") //this is still onInit and is to ensure that
//the function will not crash onInit thread with too many
//values
call RegisterSpellEffectEvent(SPELLRC, function body)
endfunction
endscope
library GetLastCastAbility uses Table, RegisterPlayerUnitEvent, UnitIndexer
/* by edo494 version 1.8d
*
*============================================================================
*
* Requires:
*
* Table by Bribe - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*
* RegisterPlayerUnitEvent by Magtheridon96 - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/
*
* UnitIndexer by Nestharus - http://www.hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
*
*============================================================================
*
* This library includes:
*
* - Allows you to retrieve last cast spells ID(returns integer)
* - Allows you to retrieve last cast spells target
* - Allows you to retrieve last cast spells caster
* - Allows you to retrieve last cast spells X and Y coordiantions
* - Allows you to retrieve last cast spells ID by specific unit
* - Allows you to retrieve target of cast spell by specific unit
* - Allows you to retrieve X and Y coordinates of last cast spell by specific unit
* - Additionally this allows you to pass unit's index and returns the unit's last cast ability
*
* This also features "BAN/UNBAN" SPELL which you can add spells into it
* If units cast those spells it will not get registered.
*
* This feature can be used for things like Spell Steal for either
* not registering the spell steal(because you dont want to steal that dont you?)
* or for spells that you dont want to be spell stealed.
*
* Also if you want to catch only heros spells, there is texted if in MainBody function which
* you can use.
*
*============================================================================
*
* Issues:
* You cant register passives for instance Bash because they
* technically never fire the event Unit - a Unit starts the effect of an ability.
*
* Also if you cast spell with no target the GetLastCastAbilityX, Y and
* GetLastCastSpellTarget will return 0, 0, null
*
*============================================================================
*
* The API is:
*
* function GetLastCastAbility takes nothing returns integer
* function GetLastCastAbilityTarget takes nothing returns unit
* function GetLastCastAbilityUnit takes nothing returns unit
* function GetLastCastAbilityX takes nothing returns real
* function GetLastCastAbilityY takes nothing returns real
*
* Based on Unit:
*
* function GetUnitLastCastAbility takes unit returns integer
* function GetUnitLastCastAbilityTarget takes unit returns unit
* function GetUnitLastCastAbilityX takes unit returns real
* function GetUnitLastCastAbilityX takes unit returns real
*
* Based on Unit's index:
*
* function GetUnitLastCastAbilityById takes integer returns integer
* function GetUnitLastCastAbilityTargetById takes integer returns unit
* function GetUnitLastCastAbilityXById takes integer returns real
* function GetUnitLastCastAbilityXById takes integer returns real
*
* Ban API:
*
* function LastAbilityAddFilter takes integer returns nothing
* function LastAbilityRemoveFilter takes integer returns nothing
*
*============================================================================
*
* Change Log:
*
* 1.0 - Intial Release
*
* 1.1 - Added BanAbility
* - Added UnbanAbility
* - Added Get(Unit)LastCastAbilityX and Y
* - Changed GetLastCast***what***ByUnit to GetUnitLastCast***what***
*
* 1.2 - Added TempBanAbility function
* - Removed Get(Unit)LastCastAbility and Get(Unit)LastCastAbilityLoc
*
* 1.3 - Changed AbilityId to Ability
* - Added support for Table
*
* 1.4 - Changed Size of myTab from 0x1000000(lol this wont work anyways) to 0x200
*
* 1.5 - Resized the Table from 0x200 to 5
* - Removed TempBan function
*
* 1.6 - Changed Ban/Unban Ability to LastAbilityAddFilter/LastAbilityRemoveFilter
* - Implemented support for RegisterPlayerUnitEvent Library
* - changed Scope Initializer to Module Initializer
*
* 1.7 - Added "Deinxeding" when unit dies
*
* 1.7a - Improved speed a very little bit
*
* 1.8 - Remade the idea of GetUnitLastCastAbility
*
* 1.8a - Removed Useless stuff
* - Changed the way how the nulling variables works(Special thanks to Bribe)
*
* 1.8b - TableArray -> Table (special thanks to Yixx)
*
* 1.8b.1 - Changed how GetLastCast***what*** works(thanks to Magtheridon96)
* - Removed local unit u from Deindex function
*
* 1.8b.2 - unit lastCastAbilityUnit -> integer lastCastAbilityCaster
*
* 1.8c - Reorganized the structure of the header
* - Added GetUnitLastCast ability taking unit's index instead of actual unit
* - Changed names of textmacroes(added GetLastCastAbility_ to their name)
*
* 1.8d - removed local integer from mainbody function
*
*============================================================================
*/
globals
private integer lastCastAbilityCaster = 0
/*
* table for Filter/UnFilter
*/
private Table myTab
/*
* variables for GetUnitLastCast
*/
private integer array lastCastUnitAbility
private unit array lastCastUnitTarget
private real array lastCastUnitX
private real array lastCastUnitY
endglobals
//! textmacro GetLastCastAbility_GETLAST takes Name, RSName, RName
function GetLastCast$Name$ takes nothing returns $RSName$
return $RName$
endfunction
//! endtextmacro
//! runtextmacro GetLastCastAbility_GETLAST("Ability", "integer", "lastCastUnitAbility[lastCastAbilityCaster]")
//! runtextmacro GetLastCastAbility_GETLAST("AbilityUnit", "unit", "GetUnitById(lastCastAbilityCaster)")
//! runtextmacro GetLastCastAbility_GETLAST("AbilityTarget", "unit", "lastCastUnitTarget[lastCastAbilityCaster]")
//! runtextmacro GetLastCastAbility_GETLAST("AbilityX", "real", "lastCastUnitY[lastCastAbilityCaster]")
//! runtextmacro GetLastCastAbility_GETLAST("AbilityY", "real", "lastCastUnitY[lastCastAbilityCaster]")
//! textmacro GetLastCastAbility_GETUNITLAST takes name, return, what
function GetUnitLastCast$name$ takes unit u returns $return$
return lastCastUnit$what$[GetUnitUserData(u)]
endfunction
//! endtextmacro
//! runtextmacro GetLastCastAbility_GETUNITLAST("Ability", "integer", "Ability")
//! runtextmacro GetLastCastAbility_GETUNITLAST("X", "real", "X")
//! runtextmacro GetLastCastAbility_GETUNITLAST("Y", "real", "Y")
//! runtextmacro GetLastCastAbility_GETUNITLAST("Target", "unit", "Target")
//! textmacro GetLastCastAbility_GETUNITLASTBYID takes name, return, what
function GetUnitLastCast$name$ById takes integer index returns $return$
return lastCastUnit$what$[index]
endfunction
//! endtextmacro
//! runtextmacro GetLastCastAbility_GETUNITLASTBYID("Ability", "integer", "Ability")
//! runtextmacro GetLastCastAbility_GETUNITLASTBYID("X", "real", "X")
//! runtextmacro GetLastCastAbility_GETUNITLASTBYID("Y", "real", "Y")
//! runtextmacro GetLastCastAbility_GETUNITLASTBYID("Target", "unit", "Target")
function LastAbilityAddFilter takes integer abilcode returns nothing
set myTab[abilcode] = 1
endfunction
function LastAbilityRemoveFilter takes integer abilcode returns nothing
set myTab[abilcode] = 0
endfunction
private function MainBody takes nothing returns nothing
//if IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) then
if myTab[GetSpellAbilityId()] != 1 then
set lastCastAbilityCaster = GetUnitId(GetTriggerUnit())
set lastCastUnitAbility[lastCastAbilityCaster] = GetSpellAbilityId()
set lastCastUnitTarget[lastCastAbilityCaster] = GetSpellTargetUnit()
set lastCastUnitX[lastCastAbilityCaster] = GetSpellTargetX()
set lastCastUnitY[lastCastAbilityCaster] = GetSpellTargetY()
endif
//endif
endfunction
private module GetLastAbility
private static method onInit takes nothing returns nothing
/*
* for ban list
*/
set myTab = Table.create()
/*
* Registering the starts the effect of an ability to the function
*/
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function MainBody)
endmethod
endmodule
private struct GetLast
implement GetLastAbility
endstruct
//***************************************************************
//***************************************************************
//When unit dies, null the numbers
private function DiesFunc takes nothing returns boolean
local integer i = GetIndexedUnitId()
set lastCastUnitAbility[i] = 0
set lastCastUnitTarget[i] = null
set lastCastUnitX[i] = 0
set lastCastUnitY[i] = 0
return false
endfunction
//***************************************************************
private module DiesInit
private static method onInit takes nothing returns nothing
call RegisterUnitIndexEvent(Condition(function DiesFunc), UnitIndexer.DEINDEX)
endmethod
endmodule
private struct DIES
implement DiesInit
endstruct
endlibrary