Tom Jones
N/A
- Reaction score
- 437
Tornado.
Code: vJass.
JASS:
//#######################################################################################################
//#Tornado - By Tom Jones.
//#######################################################################################################
//#Requirements:
//#1) vJass.
//#2) Alternatively SAS.
//#
//#Implementation:
//#1) Copy/paste this trigger from this map to your map.
//#2) Copy/paste the SsaS trigger from this map to your map. Alternatively you could change the calls to
//# SsaS with your prefered struct passing system.
//#3) Copy/paste the relevant abilities, units, and buffs from this map to your map. Alternatively you
//# could create new abilities, units or buffs, or you could use existing ones.
//#4) Modifiy the variables in the Options section below. Variables expecting raw data is important, so
//# make sure the values match those from you map. You can view your map's raw data by pressing ctrl+d
//# in the object editor.
//#######################################################################################################
//#######################################################################################################
//#Options.
//#######################################################################################################
scope Tornado
globals
private integer SPELL_ID = 039;A000039; //Raw data for the base ability.
private string VFX_TARGET_HIT = "Abilities\\Spells\\Other\\Tornado\\Tornado_Target.mdl"
private string VFX_HIT_GROUND = "Abilities\\Spells\\Other\\Volcano\\VolcanoDeath.mdl"
private integer DUMMY_SPELL_ID = 039;A001039; //Raw data for the dummy ability.
private string DUMMY_SPELL_ORDER = "slow" //Orderstring for the dummy ability.
private integer MISSILE_UNIT_ID = 039;u001039; //Raw data for the missile unit.
private integer DUMMY_UNIT_ID = 039;u000039; //Raw data for the dummy unit.
private real MISSILE_SPEED = 600.
private real MISSILE_MAX_RANGE = 1111.
private real ROTATION_SPEED = 1000. //Effects the speed of both the rotation and the toss.
private real ROTATION_MAX_Z = 400. //Determines how high a unit will rotate before getting tossed.
private real ROTATION_ARC = 0.25 //Arc of the toss.
endglobals
//#######################################################################################################
//#Triggercode - Do not modify below here unless you know what you are doing.
//#######################################################################################################
//! runtextmacro SAS_Instance()
globals
private real INTERVAL = 0.01
endglobals
private struct victimdata
unit v
real dist
real angle
real x
real y
real z
real multiplier
effect vfx
boolean rotate
integer next
integer prev
method onDestroy takes nothing returns nothing
set .dist = 0
set .z = 0
set victimdata(.next).prev = .prev
set victimdata(.prev).next = .next
set .next = 0
set .prev = 0
call DestroyEffect(.vfx)
endmethod
endstruct
private struct data
unit u
unit d
player p
victimdata first
real angle
real dist
real x
real y
trigger trig
timer t
static method KillDestructable takes nothing returns nothing
call KillDestructable(GetEnumDestructable())
endmethod
static method onTick takes nothing returns nothing
local data this = GetFrom(GetExpiredTimer())
local victimdata enum = .first
local rect rectangle
local unit d
if .dist >= MISSILE_MAX_RANGE then
if IsUnitType(.d,UNIT_TYPE_DEAD) == true then
if .first == 0 then
call this.destroy()
return
endif
else
call KillUnit(.d)
call DestroyTrigger(.trig)
endif
else
set .dist = .dist+(MISSILE_SPEED*INTERVAL)
set .x = .x+(MISSILE_SPEED*INTERVAL)*Cos(.angle)
set .y = .y+(MISSILE_SPEED*INTERVAL)*Sin(.angle)
call SetUnitPosition(.d,.x,.y)
endif
loop
exitwhen enum == 0
if enum.rotate == true then
set enum.angle = enum.angle+(bj_DEGTORAD*(ROTATION_SPEED*(INTERVAL)))
set enum.dist = enum.dist+(ROTATION_SPEED*(INTERVAL*0.1))
set enum.x = .x+enum.dist*Cos(enum.angle)
set enum.y = .y+enum.dist*Sin(enum.angle)
set enum.z = enum.z+(ROTATION_SPEED*(INTERVAL*0.5))
call SetUnitFacing(enum.v,GetUnitFacing(enum.v)+150)
if enum.z >= ROTATION_MAX_Z or (.x-100 <= GetCameraBoundMinX() or .x+100 >= GetCameraBoundMaxX() or .y-100 <= GetCameraBoundMinY() or .y+100 >= GetCameraBoundMaxY()) then
set enum.rotate = false
set enum.multiplier = ROTATION_SPEED*INTERVAL
set enum.multiplier = (-(enum.multiplier)-SquareRoot(((enum.multiplier*enum.multiplier)-4*(-ROTATION_ARC)*ROTATION_MAX_Z)))/(2*-ROTATION_ARC)
if enum.multiplier <= 0 then
set enum.multiplier = ROTATION_SPEED*INTERVAL
set enum.multiplier = (-(enum.multiplier)+SquareRoot(((enum.multiplier*enum.multiplier)-4*(-ROTATION_ARC)*ROTATION_MAX_Z)))/(2*-ROTATION_ARC)
endif
set enum.angle = Atan2(.y-enum.y,.x-enum.x)
set enum.dist = 0
endif
else
set enum.dist = enum.dist+(enum.multiplier*INTERVAL*2)
set enum.x = enum.x+(ROTATION_SPEED*INTERVAL*1.5)*Cos(enum.angle)
set enum.y = enum.y+(ROTATION_SPEED*INTERVAL*1.5)*Sin(enum.angle)
set enum.z = ((-ROTATION_ARC)*(enum.dist*enum.dist))+((ROTATION_SPEED*(INTERVAL))*enum.dist)+ROTATION_MAX_Z
if enum.z <= 0. then
if enum == .first then
set .first = .first.next
endif
set rectangle = Rect(enum.x-200,enum.y-200,enum.x+200,enum.y+200)
call EnumDestructablesInRect(rectangle,null,function data.KillDestructable)
call PauseUnit(enum.v,false)
call SetUnitPathing(enum.v,true)
if IsUnitType(enum.v,UNIT_TYPE_HERO) == true then
if GetLocalPlayer() == GetOwningPlayer(enum.v) then
call SelectUnit(enum.v,true)
endif
endif
set d = CreateUnit(.p,DUMMY_UNIT_ID,enum.x,enum.y,0)
call UnitAddAbility(d,DUMMY_SPELL_ID)
call SetUnitAbilityLevel(d,DUMMY_SPELL_ID,GetUnitAbilityLevel(.u,SPELL_ID))
call IssueTargetOrder(d,DUMMY_SPELL_ORDER,enum.v)
call UnitApplyTimedLife(d,039;BTLF039;,1.5)
call DestroyEffect(AddSpecialEffect(VFX_HIT_GROUND,enum.x,enum.y))
call enum.destroy()
call RemoveRect(rectangle)
set rectangle = null
set d = null
endif
endif
call SetUnitPosition(enum.v,enum.x,enum.y)
call SetUnitFlyHeight(enum.v,enum.z,0)
set enum = enum.next
endloop
endmethod
static method onHit takes nothing returns boolean
local data this = GetFrom(GetTriggeringTrigger())
local unit v = GetTriggerUnit()
local victimdata enum = .first
loop
exitwhen enum == 0 or enum.v == v
set enum = enum.next
endloop
if IsUnitEnemy(v,.p) == true and enum == 0 then
set enum = victimdata.create()
set enum.rotate = true
set enum.v = GetTriggerUnit()
set enum.vfx = AddSpecialEffectTarget(VFX_TARGET_HIT,enum.v,"origin")
call UnitAddAbility(enum.v,039;Amrf039;)
call UnitRemoveAbility(enum.v,039;Amrf039;)
call PauseUnit(enum.v,true)
call SetUnitPathing(enum.v,false)
if .first == 0 then
set .first = enum
else
set .first.prev = enum
set enum.next = .first
set .first = enum
endif
endif
set v = null
return false
endmethod
static method onCast_Conditions takes nothing returns boolean
return GetSpellAbilityId() == SPELL_ID
endmethod
static method onCast takes nothing returns nothing
local data this = data.allocate()
local location loc = GetSpellTargetLoc()
set .u = GetTriggerUnit()
set .p = GetOwningPlayer(.u)
set .x = GetUnitX(.u)
set .y = GetUnitY(.u)
set .angle = Atan2(GetLocationY(loc)-.y,GetLocationX(loc)-.x)
set .d = CreateUnit(.p,MISSILE_UNIT_ID,.x,.y,0)
set .trig = CreateTrigger()
call AttachTo(.trig,this)
call TriggerRegisterUnitInRange(.trig,.d,100,null)
call TriggerAddCondition(.trig,Condition(function data.onHit))
if .t == null then
set .t = CreateTimer()
endif
call AttachTo(.t,this)
call TimerStart(.t,INTERVAL,true,function data.onTick)
call RemoveLocation(loc)
set loc = null
endmethod
method onDestroy takes nothing returns nothing
set .dist = 0
set .first = 0
call RemoveUnit(.d)
call PauseTimer(.t)
endmethod
static method onInit takes nothing returns nothing
local unit u = CreateUnit(Player(15),MISSILE_UNIT_ID,0,0,0)
call UnitAddAbility(u,SPELL_ID)
call UnitAddAbility(u,DUMMY_SPELL_ID)
call RemoveUnit(CreateUnit(Player(15),DUMMY_UNIT_ID,0,0,0))
call RemoveUnit(u)
set u = null
endmethod
endstruct
//#######################################################################################################
//#Initialization.
//#######################################################################################################
function InitTrig_Tornado takes nothing returns nothing
set gg_trg_Tornado = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(gg_trg_Tornado,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_Tornado,Condition(function data.onCast_Conditions))
call TriggerAddAction(gg_trg_Tornado, function data.onCast)
endfunction
endscope
Leakless: Yep.
Target: Point.
Description:
Sends forth a tornado that slows units' movespeed and attackspeed.
Level 1 - Slows attackspeed by 10% and movespeed by 30%.
Level 2 - Slows attackspeed by 15% and movespeed by 40%.
Level 3 - Slows attackspeed by 20% and movespeed by 50%.
Level 4 - Slows attackspeed by 25% and movespeed by 60%.
Please report any bugs or script errors.