- Joined
- Feb 17, 2007

- Messages
- 368

JASS:

```
//Whippy Rope by Hanky aka OrkOfMordor aka MDZ-OrkOfMordor
scope WhippyRope initializer init
//===================================================================================================================
//Constants
globals
private constant integer SpellId ='A057' //Ability Rawcode: Thunder Clash
private constant integer DummyId ='e00G' //Unit Rawcode: Dummy
private constant string LightningType ="MBUR" //Lightning Rawcode
private constant real MissileStartZ =45. //The start z of the missile
private constant real MissileRange =90. //The collision range of the missile
private constant real CasterCollision =128. //The collision of the caster
private constant real MissileMaxHeight =210. //The maximal fly height of the missile
private constant real MissileSize =2. //Size of the MissileMdl
private constant string MissileMdl ="Abilities\\Weapons\\FaerieDragonMissile\\FaerieDragonMissile.mdl"//"Abilities\\Weapons\\WitchDoctorMissile\\WitchDoctorMissile.mdl"//The model of the missile
private constant string MissileMdlAtt ="origin"//The attach point of MissileMdl
private constant string DamageMdl ="Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl"//The model of the damage
private constant string DamageMdlAtt ="chest" //The attach point of DamageMdl
private constant string MoveMdl ="Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"//The model for the motion of the caster
private constant string MoveMdlAtt ="origin"//The attach point of MoveMdlAtt
private constant string HitGroundMdl ="Abilities\\Weapons\\WitchDoctorMissile\\WitchDoctorMissile.mdl"//The model which appear when the missile hit the ground
private constant real periodic =0.03 //The periodic motion time
private rect MaxArea =null //The maximal movearea of the missiles
endglobals
private constant function RopeSpeed takes integer lvl returns real
//The speed of the rope
return 8.00+8.00*lvl
endfunction
private constant function CasterSpeed takes integer lvl returns real
//The speed of the caster
return 8.00+10.50*lvl
endfunction
private constant function Damage takes integer lvl returns real
//The damage the enemy if it is hit by the rope
return 100.00*lvl
endfunction
private function UnitFilter takes unit caster,unit enum returns boolean
//The unit filter for all units who can be taken
if GetUnitState(enum,UNIT_STATE_LIFE) > 0.00 then
return GetUnitAbilityLevel(enum,'Avul')<=0
endif
return false
endfunction
//End Constants
//===================================================================================================================
//Conditions
private function Whippy_Rope_Conditions takes nothing returns boolean
return GetSpellAbilityId() == SpellId
endfunction
//Actions
private struct GroundHitData
unit caster
unit dummy
lightning rope
effect gfx
real distance
real maxdistance
real speed
real array x[3]
real array y[3]
real array z[2]
method motion takes nothing returns nothing
local real z
set .distance=.distance+.speed
if .distance>.maxdistance or GetUnitState(.caster,UNIT_STATE_LIFE)<=0.00 then
set .active=false
else
set .x[0]=.x[0]+.x[1]
set .y[0]=.y[0]+.y[1]
set z =GetZ(.x[0],.y[0])
call SetUnitX(.caster,.x[0])
call SetUnitY(.caster,.y[0])
call SetUnitFlyHeight(.caster,.z[0]-z,0.)
call MoveLightningEx(.rope,true,.x[0],.y[0],.z[0]+MissileStartZ+z,.x[2],.y[2],.z[1])
call DestroyEffect(AddSpecialEffectTarget(MoveMdl,.caster,MoveMdlAtt))
endif
endmethod
method endmotion takes nothing returns nothing
call SetUnitPathing(.caster,true)
call DestroyLightning(.rope)
call DestroyEffect(.gfx)
call RemoveUnit(.dummy)
set .caster=null
set .dummy =null
set .rope =null
set .gfx =null
call .destroy()
endmethod
//! runtextmacro CostumMotion("GroundHitData","motion","endmotion","periodic")
endstruct
private struct UnitHitData
unit caster
unit target
unit dummy
lightning rope
effect gfx
real speed
real x
real y
real z
method motion takes nothing returns nothing
local real x =GetUnitX(.target)
local real y =GetUnitY(.target)
local real z =GetUnitFlyHeight(.target)
local real angle =Atan2(y-.y,x-.x)
local real distance=D2PXY(.x,.y,x,y)
if distance>CasterCollision and GetUnitState(.target,UNIT_STATE_LIFE)>0.00 and GetUnitState(.caster,UNIT_STATE_LIFE)>0.00 then
set .x=.x+.speed*Cos(angle)
set .y=.y+.speed*Sin(angle)
call SetUnitX(.caster,.x)
call SetUnitY(.caster,.y)
call SetUnitPosition(.dummy,x,y)
call MoveLightningEx(.rope,true,.x,.y,.z+MissileStartZ+GetZ(.x,.y),x,y,z+GetZ(x,y))
call DestroyEffect(AddSpecialEffectTarget(MoveMdl,.caster,MoveMdlAtt))
else
set .active=false
endif
endmethod
method endmotion takes nothing returns nothing
call SetUnitPathing(.caster,true)
call DestroyLightning(.rope)
call DestroyEffect(.gfx)
call RemoveUnit(.dummy)
set .caster=null
set .dummy =null
set .rope =null
set .gfx =null
call .destroy()
endmethod
//! runtextmacro CostumMotion("UnitHitData","motion","endmotion","periodic")
endstruct
private struct SearchData
unit caster
unit dummy
lightning rope
effect gfx
real dmg
real distance
real maxdistance
real array x[2]
real array y[2]
real array z[3]
real speed
integer lvl
method motion takes nothing returns nothing
local GroundHitData ghd
local UnitHitData uhd
local real cx =GetUnitX(.caster)
local real cy =GetUnitY(.caster)
local real cz =GetZ(cx,cy)
local real angle=Atan2(.y[1]-cy,.x[1]-cx)
local real z
local real curv
local group g
local unit a
local real az
local real amr
set .x[0]=.x[0]+.speed*Cos(angle)
set .y[0]=.y[0]+.speed*Sin(angle)
set z =GetZ(.x[0],.y[0])
set .distance=.distance+.speed
set curv =GetFlyParabula(.z[1],.z[0],.z[2],.distance/.maxdistance) + z
call SetUnitPosition(.dummy,.x[0],.y[0])
call SetUnitFlyHeight(.dummy,curv-z,0.)
call MoveLightningEx(.rope,true,cx,cy,cz+MissileStartZ,.x[0],.y[0],curv)
if curv<=z or not RectContainsCoords(MaxArea,.x[0],.y[0]) or .distance>.maxdistance then
set ghd =GroundHitData.create()
set ghd.caster =.caster
set ghd.dummy =.dummy
set ghd.rope =.rope
set ghd.gfx =.gfx
set ghd.speed =CasterSpeed(.lvl)
set ghd.x[0] =cx
set ghd.y[0] =cy
set ghd.x[1] =ghd.speed*Cos(angle)
set ghd.y[1] =ghd.speed*Sin(angle)
set ghd.x[2] =.x[0]
set ghd.y[2] =.y[0]
set ghd.z[1] =z
set ghd.distance =0.
set ghd.maxdistance=D2PXY(cx,cy,.x[0],.y[0])
set ghd.z[0] =GetUnitDefaultFlyHeight(.caster)
call DestroyEffect(AddSpecialEffect(HitGroundMdl,.x[0],.y[0]))
call SetUnitFlyHeight(.dummy,0.,0.)
call SetUnitPathing(.caster,false)
call GroundHitData.addMotion(ghd)
set .active=false
else
set g=GetUnitsInRange(MissileRange,.x[0],.y[0])
call GroupRemoveUnit(g,.caster)
call GroupRemoveUnit(g,.dummy)
loop
set a=FirstOfGroup(g)
exitwhen a==null
call GroupRemoveUnit(g,a)
if UnitFilter(.caster,a) then
set az=GetUnitDefaultFlyHeight(a)+z
if az<curv and curv<MissileRange+az then
if IsUnitEnemy(a,GetOwningPlayer(.caster)) then
call DestroyEffect(AddSpecialEffectTarget(DamageMdl,a,DamageMdlAtt))
call UnitDamageTarget(.caster,a,.dmg,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
if GetUnitState(a,UNIT_STATE_LIFE)>0.00 then
set uhd=UnitHitData.create()
set uhd.target =a
set uhd.caster =.caster
set uhd.rope =.rope
set uhd.dummy =.dummy
set uhd.gfx =.gfx
set uhd.speed =CasterSpeed(.lvl)
set uhd.x =cx
set uhd.y =cy
set uhd.z =GetUnitDefaultFlyHeight(.caster)
call SetUnitPathing(.caster,false)
call UnitHitData.addMotion(uhd)
call GroupClear(g)
set .active=false
endif
endif
endif
endloop
set g=null
endif
endmethod
method endmotion takes nothing returns nothing
set .caster=null
set .dummy =null
set .rope =null
set .gfx =null
call .destroy()
endmethod
//! runtextmacro CostumMotion("SearchData","motion","endmotion","periodic")
endstruct
private function Whippy_Rope_Actions takes nothing returns nothing
local SearchData sd=SearchData.create()
local unit u =GetTriggerUnit()
local real x =GetSpellTargetX()
local real y =GetSpellTargetY()
local real cx =GetUnitX(u)
local real cy =GetUnitY(u)
set sd.lvl =GetUnitAbilityLevel(u,SpellId)
set sd.distance =0.
set sd.x[0] =cx
set sd.y[0] =cy
set sd.x[1] =x
set sd.y[1] =y
set sd.z[0] =GetZ(cx,cy)+MissileStartZ
set sd.z[1] =MissileMaxHeight
set sd.z[2] =GetZ(x,y)
set sd.speed =RopeSpeed(sd.lvl)
if x==cx and y==cy then
set sd.maxdistance=10.
else
set sd.maxdistance=D2PXY(cx,cy,x,y)
endif
set sd.caster =u
set sd.dummy =CreateUnit(Player(14),DummyId,cx,cy,A2PXY(cx,cy,x,y))
set sd.rope =AddLightningEx(LightningType,true,cx,cy,sd.z[1]+MissileStartZ,cx,cy,sd.z[1]+MissileStartZ)
set sd.gfx =AddSpecialEffectTarget(MissileMdl,sd.dummy,MissileMdlAtt)
set sd.dmg =Damage(sd.lvl)
call SetUnitScale(sd.dummy,MissileSize,MissileSize,MissileSize)
call SetLightningColor(sd.rope,0.,1.,0.,0.5)
call UnitAddFly(sd.caster)
call UnitAddFly(sd.dummy)
call SearchData.addMotion(sd)
set u =null
endfunction
//===========================================================================
private function init takes nothing returns nothing
local integer i =0
set gg_trg_WhippyRope = CreateTrigger( )
set MaxArea = bj_mapInitialPlayableArea
loop
call TriggerRegisterPlayerUnitEvent(gg_trg_WhippyRope, Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, MainFunctions_filter)
set i=i+1
exitwhen i==bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition( gg_trg_WhippyRope, Condition( function Whippy_Rope_Conditions ))
call TriggerAddAction( gg_trg_WhippyRope, function Whippy_Rope_Actions )
//Preload Models
call Preload(MissileMdl)
call Preload(DamageMdl)
call Preload(MoveMdl)
call Preload(HitGroundMdl)
endfunction
endscope
```