Moderator
M
Moderator
Rush v1.05 | Reviewed by Maker | 17th Aug 2013 | ||||
APPROVED | ||||
|
//Configurables
integer Rush = 'A000' //This is the ability id the spell uses. Change it after copying the trigger.
real Speed = 1150 //This is the speed of the caster when he uses the spell.
real Interval = .03 //How often you want the timer to run.
real Range = 175 //How close units should be to be damaged by the spell.
boolean UnitOrSfx = false //This decides if you want to use a dummy unit or sfx as the well...sfx of the spell. False for sfx, true for dummy unit.
integer Transparency = 80 //How transparent you want the dummy to be.
integer RushDummy = 'e001' // This is the id of the dummy unit created.
real Lifespan = 0.5 // Life span of the dummy.
string Sfx = "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageCaster.mdl" //The sfx that appears when the caster dashes.
string Animation = "stand ready" //What animation plays when the caster dashes.
real DamageBase = 75 //This is the base damage which will be multiplied by the ability level.
integer R = 255 //This is the red value for the dummy unit.
integer G = 255 //This is the blue value for the dummy unit.
integer B = 255 //This is the green value for the dummy unit.
real AbilDist = 200 //This is the distance that scales per level of ability. Set BonusDist to 0 if you want a pure level based distance.
real BonusDist = 200 // This is the bonus distance. Set AbilDist to 0 if you want constant distant.
attacktype AttackType = ATTACK_TYPE_CHAOS //The attack type.
damagetype DamageType = DAMAGE_TYPE_UNIVERSAL //The damage type. They're both currently set to these configurations to allow easy testing.
Dash forward with an ungodly speed, dealing damage to enemy units in a line. Distance moved increases with each level of the ability. LEVELS Level 1: Deals 75 damage. Level 2: Deals 150 damage. Level 3: Deals 225 damage. |
library TerrainPathability initializer Init
//******************************************************************************
//* BY: Rising_Dusk
//*
//* This script can be used to detect the type of pathing at a specific point.
//* It is valuable to do it this way because the IsTerrainPathable is very
//* counterintuitive and returns in odd ways and aren't always as you would
//* expect. This library, however, facilitates detecting those things reliably
//* and easily.
//*
//******************************************************************************
//*
//* > function IsTerrainDeepWater takes real x, real y returns boolean
//* > function IsTerrainShallowWater takes real x, real y returns boolean
//* > function IsTerrainLand takes real x, real y returns boolean
//* > function IsTerrainPlatform takes real x, real y returns boolean
//* > function IsTerrainWalkable takes real x, real y returns boolean
//*
//* These functions return true if the given point is of the type specified
//* in the function's name and false if it is not. For the IsTerrainWalkable
//* function, the MAX_RANGE constant below is the maximum deviation range from
//* the supplied coordinates that will still return true.
//*
//* The IsTerrainPlatform works for any preplaced walkable destructable. It will
//* return true over bridges, destructable ramps, elevators, and invisible
//* platforms. Walkable destructables created at runtime do not create the same
//* pathing hole as preplaced ones do, so this will return false for them. All
//* other functions except IsTerrainWalkable return false for platforms, because
//* the platform itself erases their pathing when the map is saved.
//*
//* After calling IsTerrainWalkable(x, y), the following two global variables
//* gain meaning. They return the X and Y coordinates of the nearest walkable
//* point to the specified coordinates. These will only deviate from the
//* IsTerrainWalkable function arguments if the function returned false.
//*
//* Variables that can be used from the library:
//* [real] TerrainPathability_X
//* [real] TerrainPathability_Y
//*
globals
private constant real MAX_RANGE = 10.
private constant integer DUMMY_ITEM_ID = 'wolg'
endglobals
globals
private item Item = null
private rect Find = null
private item array Hid
private integer HidMax = 0
public real X = 0.
public real Y = 0.
endglobals
function IsTerrainDeepWater takes real x, real y returns boolean
return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
endfunction
function IsTerrainShallowWater takes real x, real y returns boolean
return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_BUILDABILITY)
endfunction
function IsTerrainLand takes real x, real y returns boolean
return IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY)
endfunction
function IsTerrainPlatform takes real x, real y returns boolean
return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_BUILDABILITY)
endfunction
private function HideItem takes nothing returns nothing
if IsItemVisible(GetEnumItem()) then
set Hid[HidMax] = GetEnumItem()
call SetItemVisible(Hid[HidMax], false)
set HidMax = HidMax + 1
endif
endfunction
function IsTerrainWalkable takes real x, real y returns boolean
//Hide any items in the area to avoid conflicts with our item
call MoveRectTo(Find, x, y)
call EnumItemsInRect(Find ,null, function HideItem)
//Try to move the test item and get its coords
call SetItemPosition(Item, x, y) //Unhides the item
set X = GetItemX(Item)
set Y = GetItemY(Item)
static if LIBRARY_IsTerrainWalkable then
//This is for compatibility with the IsTerrainWalkable library
set IsTerrainWalkable_X = X
set IsTerrainWalkable_Y = Y
endif
call SetItemVisible(Item, false)//Hide it again
//Unhide any items hidden at the start
loop
exitwhen HidMax <= 0
set HidMax = HidMax - 1
call SetItemVisible(Hid[HidMax], true)
set Hid[HidMax] = null
endloop
//Return walkability
return (X-x)*(X-x)+(Y-y)*(Y-y) <= MAX_RANGE*MAX_RANGE and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
endfunction
private function Init takes nothing returns nothing
set Find = Rect(0., 0., 128., 128.)
set Item = CreateItem(DUMMY_ITEM_ID, 0, 0)
call SetItemVisible(Item, false)
endfunction
endlibrary
//This part is where you can configure the spell.
globals
//Configurables
integer Rush = 'A000' //This is the ability id the spell uses. Change it after copying the trigger.
real Speed = 1150 //This is the speed of the caster when he uses the spell.
real Interval = .03 //How often you want the timer to run.
real Range = 175 //How close units should be to be damaged by the spell.
boolean UnitOrSfx = false //This decides if you want to use a dummy unit or sfx as the well...sfx of the spell. False for sfx, true for dummy unit.
integer Transparency = 80 //How transparent you want the dummy to be.
integer RushDummy = 'e001' // This is the id of the dummy unit created.
real Lifespan = 0.5 // Life span of the dummy.
string Sfx = "Abilities\\Spells\\Orc\\MirrorImage\\MirrorImageCaster.mdl" //The sfx that appears when the caster dashes.
string Animation = "stand ready" //What animation plays when the caster dashes.
real DamageBase = 75 //This is the base damage which will be multiplied by the ability level.
integer R = 255 //This is the red value for the dummy unit.
integer G = 255 //This is the blue value for the dummy unit.
integer B = 255 //This is the green value for the dummy unit.
real AbilDist = 200 //This is the distance that scales per level of ability. Set BonusDist to 0 if you want a pure level based distance.
real BonusDist = 200 // This is the bonus distance. Set AbilDist to 0 if you want constant distant.
attacktype AttackType = ATTACK_TYPE_CHAOS //The attack type.
damagetype DamageType = DAMAGE_TYPE_UNIVERSAL //The damage type. They're both currently set to these configurations to allow easy testing.
//Non-configurables
group RushGroup = CreateGroup() //Don't touch this. Don't null or destroy this.
real Offset = Speed * Interval //How far the caster moves per interval.
endglobals
//------Configurable functions------//
//Configure the conditions for group check here
function UnitCheck takes unit caster, unit u returns boolean
return IsUnitEnemy(u, GetOwningPlayer(caster)) and not (IsUnitType(u, UNIT_TYPE_DEAD) and GetUnitTypeId != 0) and IsUnitType(u, UNIT_TYPE_GROUND) and not IsUnitType(u, UNIT_TYPE_STRUCTURE)
endfunction
//The Damage formula for the ability.
function Damage takes unit caster, integer Rush, real BaseDamage returns real
return GetUnitAbilityLevel(caster, Rush) * BaseDamage
endfunction
//Formula for the maximum distance. If you only want the ability to affect distance, set BonusDist to 0.
function MaximumDistance takes unit caster, integer Rush, real AbilDist, real BonusDist returns real
return GetUnitAbilityLevel(caster, Rush) * AbilDist + BonusDist
endfunction
//---End of Configurable functions---//
function Rush_Periodic takes nothing returns nothing
//Local Variable Setup
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
local unit caster = LoadUnitHandle(udg_Rush_Hash, id, 0)
local real facing = LoadReal(udg_Rush_Hash, id, 1)
local real cur_dist = LoadReal(udg_Rush_Hash, id, 2)
local group g = LoadGroupHandle(udg_Rush_Hash, id, 3)
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real x1 = x + Offset * Cos(facing)
local real y1 = y + Offset * Sin(facing)
local player owner = GetOwningPlayer(caster)
local unit dummy
local unit u
local real damage = Damage(caster, Rush, DamageBase) //You can change this to whatever you want.
local real MaxDistance = MaximumDistance(caster, Rush, AbilDist, BonusDist) //This makes the distance you dash scale with the level.
if cur_dist < MaxDistance then
call SetUnitAnimation(caster, Animation)
if not UnitOrSfx then
call DestroyEffect(AddSpecialEffect(Sfx, x, y))
else
set dummy = CreateUnit(owner, RushDummy, x, y, facing)
call SetUnitAnimation(dummy, Animation)
call SetUnitVertexColor(dummy, R, G, B, Transparency)
call UnitApplyTimedLife(dummy, 'BTLF', Lifespan)
set dummy = null
endif
call GroupEnumUnitsInRange(RushGroup, x, y, Range, null)
loop //What we do here is check if the target is in g. If not, then we damage it and add it to g to prevent it from being damaged again.
set u = FirstOfGroup(RushGroup)
exitwhen u == null
if not IsUnitInGroup(u, g) and UnitCheck(caster, u) then
call UnitDamageTarget(caster, u, damage, false, false, AttackType, DamageType, null)
call GroupAddUnit(g, u)
endif
call GroupRemoveUnit(RushGroup, u)
endloop
if IsTerrainWalkable(x1, y1) then //If the terrain is passable the you'll dash, if not then trigger ends.
call SetUnitX(caster, x1)
call SetUnitY(caster, y1)
set cur_dist = cur_dist + Offset //This counts how many times you've moved.
call SaveReal(udg_Rush_Hash, id, 2, cur_dist)
else
call PauseTimer(t)
call DestroyTimer(t)
call DestroyGroup(g)
call SetUnitAnimation(caster, "stand") //Resets the animation.
call FlushChildHashtable(udg_Rush_Hash, id)
endif
else
call PauseTimer(t)
call DestroyTimer(t)
call DestroyGroup(g)
call SetUnitAnimation(caster, "stand") //Resets the animation.
call FlushChildHashtable(udg_Rush_Hash, id)
endif
//Nulling
set t = null
set caster = null
set g = null
endfunction
function Rush_Actions takes nothing returns nothing
//Local Variable Setup
local timer t = CreateTimer()
local integer id = GetHandleId(t)
local unit caster = GetTriggerUnit()
local real dx = GetSpellTargetX() - GetUnitX(caster)
local real dy = GetSpellTargetY() - GetUnitY(caster)
local real dist_check = (dx*dx) + (dy*dy)
local real facing
//A little distance check to avoid bugs when you cast the spell in your current position.
if dist_check <= 100 * 100 then
set facing = GetUnitFacing(caster) * bj_DEGTORAD
else
set facing = (Atan2(dy, dx))
endif
//Hashtable Setup
call SaveUnitHandle(udg_Rush_Hash, id, 0, caster)
call SaveReal(udg_Rush_Hash, id, 1, facing)
call SaveReal(udg_Rush_Hash, id, 2, 0)
call SaveGroupHandle(udg_Rush_Hash, id, 3, CreateGroup())
//End Hashtable Setup
call TimerStart(t, Interval, true, function Rush_Periodic)
//Nulling
set t = null
set caster = null
endfunction
function Rush_Conditions takes nothing returns boolean
if GetSpellAbilityId() == Rush then
call Rush_Actions()
endif
return false
endfunction
//===========================================================================
function InitTrig_Rush takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( t, Condition( function Rush_Conditions) )
set udg_Rush_Hash = InitHashtable()
set t = null
endfunction