- Joined
- Feb 17, 2007
- Messages
- 368
I'm using the Whippy Rope spell provided by Hanky, but it seems to be glitching whenever I use it in a boss arena that has the terrain decreased by 1. When the rope lands, the unit goes toward the point at which it landed, however he also ascends in the air and remains slightly elevated above the arena. Why is this occurring and how do I fix it?
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