///////////////////////////////////////////////////////////////////////////////////////////////////
// ============================================================================================= //
// ========================== *** **** *** **** * * **** =========================== //
// ========================== * * * * * * * ** ** * =========================== //
// ========================== *** *** ***** * * * * * *** =========================== //
// ========================== * * * * * * * * * * =========================== //
// ========================== * * **** * * **** * * **** =========================== //
// ============================================================================================= //
///////////////////////////////////////////////////////////////////////////////////////////////////
// //
// *************************** //
// * Mark of Punishment v1.3 * //
// * by: AGD * //
// *************************** //
// //
// //
// How to Import (In Order): //
// //
// 1. Copy the dummy in object editor //
// 2. Copy the "Mark of Punishment" ability //
// 3. Copy the "Mark of Punishment by AGD" trigger category //
// //
// But first, check the "Automatically create unknown variables when pasting trigger data" //
// in the preference menu so you dont have to create the global variables one by one. //
// This will help you in future importing as well. //
// //
// Note: //
// Please give credits to the author if you use this resource in your map. //
// //
// //
// Spell Summary: //
// //
// The spell will create a dummy unit with similar model as the caster at its location. The //
// spell will then create a circular border and will mark every target in its area. These marked //
// units will be restricted to go out of the border. The caster will then be teleporting to a //
// random one unit from the marked targets and will damage it and then its mark will be //
// removed and thus, allowing it go out of the border. Units within a certain radius from //
// that target will then receive percentage damage from the damage done to that target. The //
// caster will then continue to execute this action until all marks will be removed. After then, //
// the caster will move back to the dummy's location and the special effects of the circular //
// border will disappear as well. //
// //
// //
///////////////////////////////////////////////////////////////////////////////////////////////////
// ============================================================================================= //
// ============================================================================================= //
// ============================================================================================= //
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////
//***************************//
//** Configuration Section **//
//***************************//
///////////////////////////////
////////////////////////////////////////////////////////////////
// Determines the rawcode of the activation spell //
////////////////////////////////////////////////////////////////
constant function MOP_SpellID takes nothing returns integer
return 'MOP1'
endfunction
////////////////////////////////////////////////////////////////
// Determines the unitID of the remnant //
////////////////////////////////////////////////////////////////
constant function MOP_DummyID takes nothing returns integer
return 'mop2'
endfunction
////////////////////////////////////////////////////////////////
// Determines the hero jump interval //
// ( Suggested value (x): 0.08 < x < 0.12 ) //
////////////////////////////////////////////////////////////////
constant function MOP_JumpInterval takes nothing returns real
return 0.10
endfunction
////////////////////////////////////////////////////////////////
// Determines the loop interval in units imprisonment //
////////////////////////////////////////////////////////////////
constant function MOP_LoopInterval takes nothing returns real
return 0.03125
endfunction
////////////////////////////////////////////////////////////////
// Determines if the bonus strength is accounted for when //
// computing spell stats dependent on hero attributes //
////////////////////////////////////////////////////////////////
constant function MOP_IncludeBonusStr takes nothing returns boolean
return true
endfunction
////////////////////////////////////////////////////////////////
// Determines if the bonus agility is accounted for when //
// computing spell stats dependent on hero attributes //
////////////////////////////////////////////////////////////////
constant function MOP_IncludeBonusAgi takes nothing returns boolean
return true
endfunction
////////////////////////////////////////////////////////////////
// Determines if the bonus intelligence is accounted for when //
// computing spell stats dependent on hero attributes //
////////////////////////////////////////////////////////////////
constant function MOP_IncludeBonusInt takes nothing returns boolean
return true
endfunction
////////////////////////////////////////////////////////////////
// Determines the AOE of the spell //
////////////////////////////////////////////////////////////////
constant function MOP_AOE takes integer level returns real
return 200.00 + 100.00*level
endfunction
////////////////////////////////////////////////////////////////
// Determines the base damage done by the spell to the main //
// targets (Excluding damage bonuses due to hero attributes) //
////////////////////////////////////////////////////////////////
constant function MOP_DamageBonus takes integer level returns real
return 30.00 + 20.00*level
endfunction
////////////////////////////////////////////////////////////////
// Determines the damage bonus per attribute point //
////////////////////////////////////////////////////////////////
constant function MOP_DamageDueAttr takes integer str, integer agi, integer int returns real
return 0.00*str + 1.20*agi + 0.00*int
endfunction
////////////////////////////////////////////////////////////////
// Determines the AOE of the cleaving damage (Excluding //
// cleave AOE bonuses due to hero attributes) //
////////////////////////////////////////////////////////////////
constant function MOP_CleaveAOEBase takes nothing returns real
return 125.00
endfunction
////////////////////////////////////////////////////////////////
// Determines the cleave AOE per attribute point //
////////////////////////////////////////////////////////////////
constant function MOP_CleaveAOEDueAttr takes integer str, integer agi, integer int returns real
return 0.80*str + 0.00*agi + 0.00*int
endfunction
////////////////////////////////////////////////////////////////
// Determines the percentage of the cleaving damage //
// (Excluding cleaving damage bonuses due to hero attributes) //
////////////////////////////////////////////////////////////////
constant function MOP_CDFBase takes nothing returns real
return 30.00
endfunction
////////////////////////////////////////////////////////////////
// Determines the cleave damage percentage bonus per //
// attribute point //
////////////////////////////////////////////////////////////////
constant function MOP_CDFDueAttr takes integer str, integer agi, integer int returns real
return 0.10*str + 0.00*agi + 0.00*int
endfunction
////////////////////////////////////////////////////////////////
// Determines the distance of the caster to its target when //
// moving (Instantly) to its location //
////////////////////////////////////////////////////////////////
constant function MOP_MoveDistance takes nothing returns real
return 65.00
endfunction
////////////////////////////////////////////////////////////////
// Determines how far each border special effect is to each //
// other //
////////////////////////////////////////////////////////////////
constant function MOP_BorderEffectDistance takes nothing returns real
return 80.00
endfunction
////////////////////////////////////////////////////////////////
// Determines the attack type when hitting the main targets //
////////////////////////////////////////////////////////////////
constant function MOP_AttackType1 takes nothing returns attacktype
return ATTACK_TYPE_NORMAL
endfunction
////////////////////////////////////////////////////////////////
// Determines the attack type when hitting the cleave targets //
////////////////////////////////////////////////////////////////
constant function MOP_AttackType2 takes nothing returns attacktype
return ATTACK_TYPE_NORMAL
endfunction
////////////////////////////////////////////////////////////////
// Determines the damage type of the damage dealt to the main //
// targets //
////////////////////////////////////////////////////////////////
constant function MOP_DamageType1 takes nothing returns damagetype
return DAMAGE_TYPE_NORMAL
endfunction
////////////////////////////////////////////////////////////////
// Determines the damage type of the cleaving damage //
////////////////////////////////////////////////////////////////
constant function MOP_DamageType2 takes nothing returns damagetype
return DAMAGE_TYPE_NORMAL
endfunction
////////////////////////////////////////////////////////////////
// Determines the weapon type when hitting the main targets //
////////////////////////////////////////////////////////////////
constant function MOP_WeaponType1 takes nothing returns weapontype
return null
endfunction
////////////////////////////////////////////////////////////////
// Determines the weapon type when hitting the cleave targets //
////////////////////////////////////////////////////////////////
constant function MOP_WeaponType2 takes nothing returns weapontype
return null
endfunction
////////////////////////////////////////////////////////////////
// Determines the model used to mark the target units until //
// the spell finishes //
////////////////////////////////////////////////////////////////
constant function MOP_EffectModel1 takes nothing returns string
return "Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl"
endfunction
////////////////////////////////////////////////////////////////
// Determines the model used to attach to the caster when //
// moving around its targets //
////////////////////////////////////////////////////////////////
constant function MOP_EffectModel2 takes nothing returns string
return "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
endfunction
////////////////////////////////////////////////////////////////
// Determines the model used to mark around the area of the //
// spell //
////////////////////////////////////////////////////////////////
constant function MOP_EffectModel3 takes nothing returns string
return "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl"
endfunction
////////////////////////////////////////////////////////////////
// Determines the model upon damaging targets //
////////////////////////////////////////////////////////////////
constant function MOP_EffectModel4 takes nothing returns string
return "Abilities\\Spells\\Human\\Feedback\\SpellBreakerAttack.mdl"
endfunction
////////////////////////////////////////////////////////////////
// Determines the attachment point of MOP_EffectModel1 //
////////////////////////////////////////////////////////////////
constant function MOP_EffectAttachPoint1 takes nothing returns string
return "overhead"
endfunction
////////////////////////////////////////////////////////////////
// Determines the attachment point of MOP_EffectModel2 //
////////////////////////////////////////////////////////////////
constant function MOP_EffectAttachPoint2 takes nothing returns string
return "weapon"
endfunction
////////////////////////////////////////////////////////////////
// Set to false if you don't want to change the caster's //
// transparency //
////////////////////////////////////////////////////////////////
constant function MOP_TransparencySwitch1 takes nothing returns boolean
return true
endfunction
////////////////////////////////////////////////////////////////
// Set to false if you don't want to change the remnant's //
// transparency //
////////////////////////////////////////////////////////////////
constant function MOP_TransparencySwitch2 takes nothing returns boolean
return true
endfunction
////////////////////////////////////////////////////////////////
// Determines the transparency of the caster //
////////////////////////////////////////////////////////////////
constant function MOP_Transparency1 takes nothing returns real
return 65.00
endfunction
////////////////////////////////////////////////////////////////
// Determines the transparency of the remnant //
////////////////////////////////////////////////////////////////
constant function MOP_Transparency2 takes nothing returns real
return 45.00
endfunction
////////////////////////////////////////////////////////////////
// The following set of functions determines the type of //
// units to be allowed as the spell's target //
////////////////////////////////////////////////////////////////
//============================================================//
//== Allies ==//
constant function MOP_Allies takes nothing returns boolean
return false
endfunction
//============================================================//
//== Air Units ==//
constant function MOP_Air takes nothing returns boolean
return true
endfunction
//============================================================//
//== Structures ==//
constant function MOP_Structure takes nothing returns boolean
return false
endfunction
//============================================================//
//== Mechanical ==//
constant function MOP_Mechanical takes nothing returns boolean
return false
endfunction
//============================================================//
//== Ethereal ==//
constant function MOP_Ethereal takes nothing returns boolean
return false
endfunction
//============================================================//
//== Illusion ==//
constant function MOP_Illusion takes nothing returns boolean
return true
endfunction
//============================================================//
////////////////////////////////////////////////////////////////
//////////////////////////////
//**************************//
//** End of Configuration **//
//**************************//
//////////////////////////////
//////////////////////
//******************//
//** Loop Section **//
//******************//
//////////////////////
function MOP_AddGroup takes nothing returns nothing
call GroupAddUnit( udg_MOP_TempGroup, GetEnumUnit() )
endfunction
function MOP_GetRandomUnit takes nothing returns nothing
set udg_MOP_Iterated = udg_MOP_Iterated + 1
if GetRandomInt( 1, udg_MOP_Iterated ) == 1 then
set udg_MOP_RandomUnit = GetEnumUnit()
endif
endfunction
function MOP_MainAction takes nothing returns nothing
// Local variables setup
local timer t = GetExpiredTimer()
local unit u = LoadUnitHandle( udg_MOP_Hash, GetHandleId( t ), 1 )
local integer key = GetHandleId( u )
local integer a = 0
local real angle = bj_DEGTORAD*GetRandomReal( 0, 360 )
local real origX = LoadReal( udg_MOP_Hash, key, 3 )
local real origY = LoadReal( udg_MOP_Hash, key, 4 )
local real targetX
local real targetY
local real tempX
local real tempY
local unit cleavetarget
local unit target
// Main target
set udg_MOP_Iterated = 0
set udg_MOP_RandomUnit = null
call ForGroup( LoadGroupHandle( udg_MOP_Hash, key, 9 ), function MOP_GetRandomUnit )
set target = udg_MOP_RandomUnit
if target != null then
set targetX = GetUnitX( target )
set targetY = GetUnitY( target )
call GroupEnumUnitsInRange( udg_MOP_TempGroup, targetX, targetY, LoadReal( udg_MOP_Hash, key, 14 ), null )
set tempX = targetX + MOP_MoveDistance()*Cos( angle )
set tempY = targetY + MOP_MoveDistance()*Sin( angle )
call SetUnitX( u, tempX )
call SetUnitY( u, tempY )
call SetUnitFacing( target, bj_RADTODEG*Atan2( targetY - tempY, targetX - tempX ) )
call UnitDamageTarget( u, target, LoadReal( udg_MOP_Hash, key, 13 ), true, false, MOP_AttackType1(), MOP_DamageType1(), MOP_WeaponType1() )
call DestroyEffect( AddSpecialEffect( MOP_EffectModel4(), targetX, targetY ) )
call DestroyEffect( LoadEffectHandle( udg_MOP_Hash, key, GetHandleId( target ) ) )
// Cleave targets
loop
set cleavetarget = FirstOfGroup( udg_MOP_TempGroup )
exitwhen cleavetarget == null
call GroupRemoveUnit( udg_MOP_TempGroup, cleavetarget )
if ( cleavetarget != target ) and ( IsUnitEnemy( cleavetarget, LoadPlayerHandle( udg_MOP_Hash, key, 8 ) ) or MOP_Allies() ) and ( not IsUnitType( cleavetarget, UNIT_TYPE_FLYING ) or MOP_Air() ) and ( not IsUnitType( cleavetarget, UNIT_TYPE_STRUCTURE ) or MOP_Structure() ) and ( not IsUnitType( cleavetarget, UNIT_TYPE_MECHANICAL) or MOP_Mechanical() ) and ( not IsUnitType( cleavetarget, UNIT_TYPE_ETHEREAL ) or MOP_Ethereal() ) and ( not IsUnitIllusion( cleavetarget ) or MOP_Illusion() ) and ( not IsUnitType( cleavetarget, UNIT_TYPE_DEAD ) ) and ( not IsUnitHidden( cleavetarget ) ) then
call UnitDamageTarget( u, cleavetarget, LoadReal( udg_MOP_Hash, key, 15 ), true, false, MOP_AttackType2(), MOP_DamageType2(), MOP_WeaponType2() )
endif
endloop
call GroupRemoveUnit( LoadGroupHandle( udg_MOP_Hash, key, 9 ), target )
else
// Clean ups
if MOP_TransparencySwitch1() then
call SetUnitVertexColor( u, 255, 255, 255, 255 )
endif
call DestroyEffect( LoadEffectHandle( udg_MOP_Hash, key, 10 ) )
call RemoveUnit( LoadUnitHandle( udg_MOP_Hash, key, 2 ) )
call SetUnitTimeScale( u, 1 )
call SetUnitInvulnerable( u, false )
call SetUnitX( u, origX )
call SetUnitY( u, origY )
call IssueImmediateOrder( u, "stop" )
call SetUnitFacing( u, bj_RADTODEG*Atan2( LoadReal( udg_MOP_Hash, key, 6 ) - origY, LoadReal( udg_MOP_Hash, key, 5 ) - origX ) )
// Removing border special effects
loop
set a = a + 1
call DestroyEffect( LoadEffectHandle( udg_MOP_Hash, key, StringHash( "Border" + I2S( a ) ) ) )
exitwhen a > LoadReal( udg_MOP_Hash, key, 16 )
endloop
call DestroyGroup( LoadGroupHandle( udg_MOP_Hash, key, 9 ) )
call DestroyGroup( LoadGroupHandle( udg_MOP_Hash, key, 17 ) )
call DestroyTimer( LoadTimerHandle( udg_MOP_Hash, key, 1 ) )
call DestroyTimer( t )
call FlushChildHashtable( udg_MOP_Hash, key )
endif
// Nullifying variables
set u = null
set t = null
endfunction
function MOP_LockUnits takes nothing returns nothing
// Local variables setup
local timer t = GetExpiredTimer()
local unit u = LoadUnitHandle( udg_MOP_Hash, GetHandleId( t ), 1 )
local integer key = GetHandleId( u )
local real AOE = LoadReal( udg_MOP_Hash, key, 12 )
local real centerX = LoadReal( udg_MOP_Hash, key, 5 )
local real centerY = LoadReal( udg_MOP_Hash, key, 6 )
local real dx
local real dy
local unit picked
local real angle
// Setting maximum distance for the marked units, preventing them from going outside the spell borders
call ForGroup( LoadGroupHandle( udg_MOP_Hash, key, 9 ), function MOP_AddGroup )
loop
set picked = FirstOfGroup( udg_MOP_TempGroup )
exitwhen picked == null
call GroupRemoveUnit( udg_MOP_TempGroup, picked )
set dx = GetUnitX( picked ) - centerX
set dy = GetUnitY( picked ) - centerY
set angle = Atan2( dy, dx )
if dx*dx + dy*dy > AOE*AOE then
call SetUnitX( picked, centerX + AOE*Cos( angle ) )
call SetUnitY( picked, centerY + AOE*Sin( angle ) )
endif
// Filtering marked units
// If one of these conditions return false, remove picked unit from the group and remove its mark
if not ( ( IsUnitEnemy( picked, LoadPlayerHandle( udg_MOP_Hash, key, 8 ) ) or MOP_Allies() ) and ( not IsUnitType( picked, UNIT_TYPE_FLYING ) or MOP_Air() ) and ( not IsUnitType( picked, UNIT_TYPE_STRUCTURE ) or MOP_Structure() ) and ( not IsUnitType( picked, UNIT_TYPE_MECHANICAL) or MOP_Mechanical() ) and ( not IsUnitType( picked, UNIT_TYPE_ETHEREAL ) or MOP_Ethereal() ) and ( not IsUnitIllusion( picked ) or MOP_Illusion() ) and ( not IsUnitType( picked, UNIT_TYPE_DEAD ) ) and ( not IsUnitHidden( picked ) ) ) then
call GroupRemoveUnit( LoadGroupHandle( udg_MOP_Hash, key, 9 ), picked )
call DestroyEffect( LoadEffectHandle( udg_MOP_Hash, key, GetHandleId( picked ) ) )
endif
endloop
// Nullifying variables
set u = null
set t = null
endfunction
/////////////////////////////
//*************************//
//** Spell Setup Section **//
//*************************//
/////////////////////////////
function MOP_Setup takes nothing returns boolean
// Local variables setup
local unit u
local unit dummy
local unit picked
local player pl
local group targetgroup
local integer key
local integer level
local integer str
local integer agi
local integer int
local integer targetcount = 0
local integer a = 0
local real origX
local real origY
local real centerX
local real centerY
local real AOE
local real damage
local real b
local real angle
local timer t1
local timer t2
if GetSpellAbilityId() == MOP_SpellID() then
// Setup
set u = GetTriggerUnit()
set pl = GetOwningPlayer( u )
set key = GetHandleId( u )
set level = GetUnitAbilityLevel( u, MOP_SpellID() )
set str = GetHeroStr( u, MOP_IncludeBonusStr() )
set agi = GetHeroAgi( u, MOP_IncludeBonusAgi() )
set int = GetHeroInt( u, MOP_IncludeBonusInt() )
set origX = GetUnitX( u )
set origY = GetUnitY( u )
set centerX = GetSpellTargetX()
set centerY = GetSpellTargetY()
set AOE = MOP_AOE( level )
set damage = MOP_DamageBonus( level ) + MOP_DamageDueAttr( str, agi, int )
set b = 2*bj_PI*AOE/MOP_BorderEffectDistance()
set t1 = CreateTimer()
set t2 = CreateTimer()
set dummy = CreateUnit ( pl, MOP_DummyID(), origX, origY, bj_RADTODEG*Atan2( centerY - origY, centerX - origX ) )
set targetgroup = CreateGroup()
call GroupEnumUnitsInRange( udg_MOP_TempGroup, centerX, centerY, AOE, null )
// Setting remnant properties
if MOP_TransparencySwitch2() then
call SetUnitVertexColor( dummy, 255, 255, 255, R2I( 2.55*MOP_Transparency2() ) )
endif
call SetUnitAnimation( dummy, "stand" )
call SetUnitPathing( dummy, false )
call SaveGroupHandle( udg_MOP_Hash, key, 17, CreateGroup() )
// Marking units
loop
set picked = FirstOfGroup( udg_MOP_TempGroup )
exitwhen picked == null
call GroupRemoveUnit( udg_MOP_TempGroup, picked )
if ( IsUnitEnemy( picked, pl ) or MOP_Allies() ) and ( not IsUnitType( picked, UNIT_TYPE_FLYING ) or MOP_Air() ) and ( not IsUnitType( picked, UNIT_TYPE_STRUCTURE ) or MOP_Structure() ) and ( not IsUnitType( picked, UNIT_TYPE_MECHANICAL) or MOP_Mechanical() ) and ( not IsUnitType( picked, UNIT_TYPE_ETHEREAL ) or MOP_Ethereal() ) and ( not IsUnitIllusion( picked ) or MOP_Illusion() ) and ( not IsUnitType( picked, UNIT_TYPE_DEAD ) ) and ( not IsUnitHidden( picked ) ) then
call GroupAddUnit( targetgroup, picked )
call GroupAddUnit( LoadGroupHandle( udg_MOP_Hash, key, 17 ), picked )
call SaveEffectHandle( udg_MOP_Hash, key, GetHandleId( picked ), AddSpecialEffectTarget( MOP_EffectModel1(), picked, MOP_EffectAttachPoint1() ) )
set targetcount = targetcount + 1
call SaveUnitHandle( udg_MOP_Hash, key, targetcount, picked )
endif
endloop
// Preparing caster
call SetUnitTimeScale( u, 10 )
if MOP_TransparencySwitch1() then
call SetUnitVertexColor( u, 255, 255, 255, R2I( 2.55*MOP_Transparency1() ) )
endif
call SetUnitInvulnerable( u, true )
// Creating border special effects
loop
set a = a + 1
set angle = 2*bj_PI*a/b
call SaveEffectHandle( udg_MOP_Hash, key, StringHash( "Border" + I2S( a ) ), AddSpecialEffect( MOP_EffectModel3(), centerX + AOE*Cos( angle ), centerY + AOE*Sin( angle ) ) )
exitwhen a > b
endloop
// Saving data to hashtable
call SaveUnitHandle( udg_MOP_Hash, GetHandleId( t1 ), 1, u )
call SaveUnitHandle( udg_MOP_Hash, GetHandleId( t2 ), 1, u )
call SaveTimerHandle( udg_MOP_Hash, key, 1, t2 )
call SaveUnitHandle( udg_MOP_Hash, key, 2, dummy )
call SaveReal( udg_MOP_Hash, key, 3, origX )
call SaveReal( udg_MOP_Hash, key, 4, origY )
call SaveReal( udg_MOP_Hash, key, 5, centerX )
call SaveReal( udg_MOP_Hash, key, 6, centerY )
call SaveInteger( udg_MOP_Hash, key, 7, targetcount )
call SavePlayerHandle( udg_MOP_Hash, key, 8, pl )
call SaveGroupHandle( udg_MOP_Hash, key, 9, targetgroup )
call SaveEffectHandle( udg_MOP_Hash, key, 10, AddSpecialEffectTarget( MOP_EffectModel2(), u, MOP_EffectAttachPoint2() ) )
// Saving spell stats
call SaveInteger( udg_MOP_Hash, key, 11, level )
call SaveReal( udg_MOP_Hash, key, 12, AOE )
call SaveReal( udg_MOP_Hash, key, 13, damage )
call SaveReal( udg_MOP_Hash, key, 14, MOP_CleaveAOEBase() + MOP_CleaveAOEDueAttr( str, agi, int ) )
call SaveReal( udg_MOP_Hash, key, 15, damage*( MOP_CDFBase() + MOP_CDFDueAttr( str, agi, int ) )*0.01 )
call SaveReal( udg_MOP_Hash, key, 16, b )
// Running loop functions
call TimerStart( t1, MOP_JumpInterval(), true, function MOP_MainAction )
call TimerStart( t2, MOP_LoopInterval(), true, function MOP_LockUnits )
// Nullifying variables
set u = null
set dummy = null
set targetgroup = null
set t1 = null
set t2 = null
endif
return false
endfunction
/////////////////////////////////
//*****************************//
//** Initialization Function **//
//*****************************//
/////////////////////////////////
function InitTrig_Mark_of_Punishment takes nothing returns nothing
local trigger t = CreateTrigger()
set udg_MOP_Hash = InitHashtable()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( t, Filter( function MOP_Setup ) )
endfunction
//////////////////////
//******************//
//** End of Spell **//
//******************//
//////////////////////