// ©2008 Toadcop
Name | Type | is_array | initial_value |
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct mx
unit u
real x
real y
real z
real vecx
real vecy
real vecz
real vecfx
real vecfy
real vecfz=-1500
real rad=45 // Scale 6 // 7.5
real elastic=GetRandomReal(0.55,0.95)
real mass=1
real refscale=GetRandomReal(0.5,0.85)
real scale=1
integer lvl=1
real disdmg=0.1
real stackness=1// :P
unit caster
stone_crusher_caster xcas
real unitrecyclet=1.5
boolean shakecam=true
real toshake=1400
string groundeffect="Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"
attacktype atype=ATTACK_TYPE_SIEGE
damagetype dtype=DAMAGE_TYPE_NORMAL
weapontype wtype=WEAPON_TYPE_ROCK_HEAVY_BASH
group clg
endstruct
globals
// © 2006-2008 Author: Toadcop All rights reserved.
//################################################################################################
//## B U R A N X V A R I A B L E S by Toadcop ##
//################################################################################################
integer eax = 0
real erx = 0
boolean ebx = false
unit eux = null
timer etx = null
item eix = null
effect eex = null
group egx = null
location tmploc = null
real tmplocZ = 0
real TPCVecX = 0
real TPCVecY = 0
real TPCVecZ = 0
real MapMinX = 0
real MapMinY = 0
real MapMaxX = 0
real MapMaxY = 0
real MapBoundMinX
real MapBoundMinY
real MapBoundMaxX
real MapBoundMaxY
boolean dis_msg = true
// OPC
timer array OPCTimers
boolean array OPCTimersUsed
integer array OPCTimersRefCount
unit array OPCUnits
boolean array OPCUnitsUsed
integer OPCTimersCur = 0
integer OPCTimersToInit = 0
integer OPCTimersMinIndex = 999999999
integer OPCTimersMaxIndex = 0
integer OPCUnitsCur = 0
integer OPCUnitsToInit = 0
integer OPCUnitsMinIndex = 999999999
integer OPCMaxtimers = 0
integer OPCMaxunits = 0
integer QUCUnitId = 'e000'
real QUCCasterPlaceX = 4085
real QUCCasterPlaceY = 4085
unit array QUCDummyCasters
endglobals
constant function h2i takes handle h returns integer
return h
return 0
endfunction
constant function b2i takes boolean b returns integer
if b==true then
return 1
endif
return 0
endfunction
constant function i2b takes integer i returns boolean
if i>=1 then
return true
endif
return false
endfunction
constant function i2wdg takes integer H returns widget
return H
return null
endfunction
constant function i2u takes integer H returns unit
return H
return null
endfunction
constant function i2it takes integer H returns item
return H
return null
endfunction
constant function i2effect takes integer H returns effect
return H
return null
endfunction
constant function i2eff takes integer H returns effect
return H
return null
endfunction
constant function i2fx takes integer H returns effect
return H
return null
endfunction
constant function i2race takes integer H returns race
return H
return null
endfunction
constant function i2ip takes integer H returns itempool
return H
return null
endfunction
constant function i2up takes integer H returns unitpool
return H
return null
endfunction
constant function i2mb takes integer H returns multiboard
return H
return null
endfunction
constant function i2mbi takes integer i returns multiboarditem
return i
return null
endfunction
constant function i2g takes integer i returns group
return i
return null
endfunction
constant function i2bexpr takes integer i returns boolexpr
return i
return null
endfunction
constant function i2be takes integer i returns boolexpr
return i
return null
endfunction
constant function i2t takes integer H returns trigger
return H
return null
endfunction
constant function i2trg takes integer H returns trigger
return H
return null
endfunction
constant function i2s takes integer H returns string
return H
return null
endfunction
constant function s2i takes string S returns integer
return S
return 0
endfunction
constant function i2l takes integer H returns location
return H
return null
endfunction
constant function i2loc takes integer H returns location
return H
return null
endfunction
constant function i2timer takes integer i returns timer
return i
return null
endfunction
constant function i2tmr takes integer i returns timer
return i
return null
endfunction
constant function code2i takes code i returns integer
return i
return 0
endfunction
constant function i2code takes integer i returns code
return i
return null
endfunction
constant function i2tt takes integer i returns texttag
return i
return null
endfunction
constant function i2ta takes integer i returns triggeraction
return i
return null
endfunction
constant function i2tc takes integer i returns triggercondition
return i
return null
endfunction
constant function i2img takes integer i returns image
return i
return null
endfunction
constant function r2i takes real r returns integer
return r
return 0
endfunction
constant function i2r takes integer i returns real
return i
return 0.0
endfunction
constant function i2snd takes integer i returns sound
return i
return null
endfunction
function echo takes string s returns nothing
if dis_msg then
call DisplayTextToPlayer(GetLocalPlayer(),0,0,s)
endif
endfunction
globals
constant integer IS_DUMMY='A001'
constant integer DUMMY_MORPH='S000'
constant real Unit_height_default=120
constant real Unit_collision_default=32
real array Unit_data
endglobals
function InitUnitHeightsBX takes nothing returns nothing
set Unit_data[s2i(I2S('hpea')+"height")]=90
set Unit_data[s2i(I2S('hcas')+"height")]=400
set Unit_data[s2i(I2S('hgra')+"height")]=400
set Unit_data[s2i(I2S('hatw')+"collision")]=250
set Unit_data[s2i(I2S('hvlt')+"collision")]=300
set Unit_data[s2i(I2S('htow')+"collision")]=350
set Unit_data[s2i(I2S('hgtw')+"collision")]=250
//###########
//#COLLISION#
//###########
set Unit_data[s2i(I2S('hpea')+"collision")]=20
set Unit_data[s2i(I2S('hcas')+"collision")]=150
set Unit_data[s2i(I2S('hgra')+"collision")]=150
set Unit_data[s2i(I2S('hatw')+"collision")]=40
set Unit_data[s2i(I2S('hvlt')+"collision")]=100
set Unit_data[s2i(I2S('htow')+"collision")]=150
set Unit_data[s2i(I2S('hgtw')+"collision")]=40
endfunction
function GetUnitHeightBX takes unit u returns real
set erx=Unit_data[s2i(I2S(GetUnitTypeId(u))+"height")]
if erx!=0 then
return erx
endif
return Unit_height_default
endfunction
function GetUnitCollisionBX takes unit u returns real
set erx=Unit_data[s2i(I2S(GetUnitTypeId(u))+"collision")]
if erx!=0 then
return erx
endif
return Unit_collision_default
endfunction
globals
real x_per=0.0225
constant real terr_size=16
group dummygroup=CreateGroup()
boolexpr collision
boolexpr collisionadv
mx mmx
mx mmx0
mx mmx1
mx mmx2
endglobals
globals
integer TCM_maxunits=0
mx array TCM_unt
integer array TCM_untpos
endglobals
globals
integer txa=0
integer txa0=0
integer txa1=0
integer txa2=0
integer txa3=0
integer txa4=0
integer txa5=0
integer txa6=0
integer txa7=0
integer txa8=0
integer txa9=0
integer txa10=0
integer txa11=0
integer txa12=0
integer txa13=0
integer txa14=0
integer txa15=0
integer txa16=0
integer txa17=0
integer txa18=0
integer txa19=0
integer txa20=0
integer txa21=0
integer txa22=0
integer txa23=0
integer txa24=0
integer txa25=0
integer txa26=0
integer txa27=0
integer txa28=0
integer txa29=0
integer txa30=0
integer txa31=0
integer txa32=0
real txr=0
real txr0=0
real txr1=0
real txr2=0
real txr3=0
real txr4=0
real txr5=0
real txr6=0
real txr7=0
real txr8=0
real txr9=0
real txr10=0
real txr11=0
real txr12=0
real txr13=0
real txr14=0
real txr15=0
real txr16=0
real txr17=0
real txr18=0
real txr19=0
real txr20=0
real txr21=0
real txr22=0
real txr23=0
real txr24=0
real txr25=0
real txr26=0
real txr27=0
real txr28=0
real txr29=0
real txr30=0
real txr31=0
real txr32=0
real txrx=0
real txrx0=0
real txrx1=0
real txrx2=0
real txrx3=0
real txrx4=0
real txrx5=0
real txrx6=0
real txrx7=0
real txrx8=0
real txrx9=0
real txrx10=0
real txrx11=0
real txrx12=0
real txrx13=0
real txrx14=0
real txrx15=0
real txrx16=0
endglobals
// Extra
function DistanceBetweenCord takes real X,real Y returns real
return SquareRoot(X*X+Y*Y)
endfunction
function DistanceIn3D takes real X,real Y,real Z returns real
return SquareRoot(X*X+Y*Y+Z*Z)
endfunction
function AngleBetweenCord takes real X,real Y returns real
return 57.296*Atan2(Y,X)
endfunction
function MoveX takes real x, real Dist, real Angle returns real
return x+Dist*Cos(Angle*0.0175)
endfunction
function MoveY takes real x, real Dist, real Angle returns real
return x+Dist*Sin(Angle*0.0175)
endfunction
function MoveLocBR takes location l,real x,real y returns location
call MoveLocation(l,x,y)
return l
endfunction
function RAbs takes real a returns real
if (a >= 0) then
return a
else
return -a
endif
endfunction
function GetUnitZ takes unit u returns real
return GetLocationZ(MoveLocBR(tmploc,GetUnitX(u),GetUnitY(u)))+GetUnitFlyHeight(u)
endfunction
function SetUnitZ takes unit u,real z returns nothing
set tmplocZ=GetLocationZ(MoveLocBR(tmploc,GetUnitX(u),GetUnitY(u)))
call SetUnitFlyHeight(u,z-tmplocZ,0)
endfunction
function AddEffect takes string s,real x,real y returns nothing
call DestroyEffect(AddSpecialEffect(s,x,y))
endfunction
function AddEffectTarget takes string s,widget w,string a returns nothing
call DestroyEffect(AddSpecialEffectTarget(s,w,a))
endfunction
constant function Modulo takes integer h,integer d returns integer
return h-(h/d)*d
endfunction
function ReduceThanLessBX takes real r,real limit,real to returns real
if r<limit then
return to
endif
return r
endfunction
//#########################################################
//## Toadcop's Object Pre-Cacher ##
//#########################################################
function GetTimerBR takes nothing returns timer
local timer t=null
local integer i=OPCTimersCur
if i>0 then
set OPCTimersCur=OPCTimersCur-1
set t=OPCTimers[i]
set OPCTimersUsed[h2i(t)-OPCTimersMinIndex]=true
set OPCTimers[i]=null
set OPCMaxtimers=OPCMaxtimers+1
return t
endif
return CreateTimer()
endfunction
function GetUnitBR takes nothing returns unit
local unit u=null
local integer i=OPCUnitsCur
if i>0 then
set OPCUnitsCur=OPCUnitsCur-1
set u=OPCUnits[i]
call SetUnitAnimation(u,"Stand")
call SetUnitScale(u,1,1,1)
call SetUnitVertexColor(u,255,255,255,255)
set OPCUnitsUsed[h2i(u)-OPCUnitsMinIndex]=true
set OPCUnits[i]=null
set OPCMaxunits=OPCMaxunits+1
return u
endif
return CreateUnit(Player(15),QUCUnitId,0,0,0)
endfunction
//##############################################################
//## Recycling Funcs
//##############################################################
function RecycleTimer takes timer t returns nothing
local integer i=OPCTimersCur+1
if OPCTimersUsed[h2i(t)-OPCTimersMinIndex] then
if i<0x1fff and t!=null then
call TimerStart(t,0,false,null)
set OPCTimersCur=i
set OPCTimers[i]=t
set OPCTimersUsed[h2i(t)-OPCTimersMinIndex]=false
set OPCMaxtimers=OPCMaxtimers-1
else
if t!=null then
call DestroyTimer(t)
endif
endif
endif
endfunction
function RecycleUnit takes unit u returns nothing
local integer i=OPCUnitsCur+1
if OPCUnitsUsed[h2i(u)-OPCUnitsMinIndex] then
if i<0x1fff and u!=null then
call IssueImmediateOrder(u,"stop")
call SetUnitScale(u,0,0,0)
call SetUnitTimeScale(u,1)
call SetUnitX(u,QUCCasterPlaceX)
call SetUnitY(u,QUCCasterPlaceY)
call SetUnitVertexColor(u,255,255,255,0)
call SetUnitFlyHeight(u,999999,0)
call SetUnitOwner(u,Player(15),true)
set OPCUnitsCur=i
set OPCUnits[i]=u
set OPCUnitsUsed[h2i(u)-OPCUnitsMinIndex]=false
set OPCMaxunits=OPCMaxunits-1
else
if u!=null then
call RemoveUnit(u)
endif
endif
endif
endfunction
//##############################################################
//## Obj Init Funcs
//##############################################################
function InitTimer takes nothing returns nothing
local timer t=CreateTimer()
local integer h=h2i(t)
local integer i=OPCTimersCur+1
if h<OPCTimersMinIndex then
set OPCTimersMinIndex=h
endif
if h>OPCTimersMaxIndex then
set OPCTimersMaxIndex=h
endif
set OPCTimersCur=i
set OPCTimers[i]=t
set t=null
endfunction
function InitUnit takes nothing returns nothing
local unit u=CreateUnit(Player(15),QUCUnitId,QUCCasterPlaceX,QUCCasterPlaceY,0)
local integer h=h2i(u)
local integer i=OPCUnitsCur+1
call UnitAddAbility(u,'Aloc')
call UnitAddAbility(u,DUMMY_MORPH)
call SetUnitX(u,QUCCasterPlaceX)
call SetUnitY(u,QUCCasterPlaceY)
call SetUnitScale(u,0,0,0)
call SetUnitVertexColor(u,255,255,255,0)
call SetUnitFlyHeight(u,999999,0)
if h<OPCUnitsMinIndex then
set OPCUnitsMinIndex=h
endif
set OPCUnitsCur=i
set OPCUnits[i]=u
set u=null
endfunction
function TimerInitExec takes nothing returns nothing
local integer i=1
loop
exitwhen i>OPCTimersToInit or i>0x1ffe
call ExecuteFunc("InitTimer")
set i=i+1
endloop
endfunction
function TimerInit takes integer c returns nothing
set OPCTimersToInit=c
call ExecuteFunc("TimerInitExec")
endfunction
function UnitInitExec takes nothing returns nothing
local integer i=1
loop
exitwhen i>OPCUnitsToInit or i>0x1ffe
call ExecuteFunc("InitUnit")
set i=i+1
endloop
endfunction
function UnitInit takes integer c returns nothing
set OPCUnitsToInit=c
call ExecuteFunc("UnitInitExec")
endfunction
function QUCRecycle takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer tid=h2i(t)-OPCTimersMinIndex
local unit u=QUCDummyCasters[tid]
set QUCDummyCasters[tid]=null
call RecycleUnit(u)
call RecycleTimer(t)
endfunction
function RecycleUnitTimed takes unit u,real timeout returns nothing
local timer t=GetTimerBR()
local integer tid=h2i(t)-OPCTimersMinIndex
if OPCUnitsUsed[h2i(u)-OPCUnitsMinIndex] then
set QUCDummyCasters[tid]=u
call TimerStart(t,timeout,false,function QUCRecycle)
endif
endfunction
function CreateVecBR takes real x,real y,real z,real x1,real y1,real z1 returns nothing
set TPCVecX=(x1-x)
set TPCVecY=(y1-y)
set TPCVecZ=(z1-z)
endfunction
function SetVecLengthBR takes real x,real y,real z,real length returns nothing
local real r=length/(DistanceIn3D(x,y,z)+0.001)
set TPCVecX=x*r
set TPCVecY=y*r
set TPCVecZ=z*r
endfunction
function VecGetRollBR takes real x,real y,real z returns real
return Atan2(z,DistanceBetweenCord(x,y))
endfunction
function VecGetAngleBR takes real x,real y,real z returns real
return AngleBetweenCord(x,y)
endfunction
function GetSurfaceVectorBR takes real z1,real z2,real z3,real z4,real size returns nothing
set TPCVecX=0-(z2-z1)*size
set TPCVecY=0-size*(z4-z3)
set TPCVecZ=size*size
endfunction
function ReflectFromTerrainBR takes real x,real y,real size,real VecX,real VecY,real VecZ,real scale,real invscale returns nothing
set txr2=size*2
call MoveLocation(tmploc,x-size,y)
set txr3=GetLocationZ(tmploc)
call MoveLocation(tmploc,x+size,y)
set TPCVecX=-txr2*(GetLocationZ(tmploc)-txr3)
call MoveLocation(tmploc,x,y-size)
set txr3=GetLocationZ(tmploc)
call MoveLocation(tmploc,x,y+size)
set TPCVecY=-txr2*(GetLocationZ(tmploc)-txr3)
set TPCVecZ=txr2*txr2
set txr1=(VecX*TPCVecX+VecY*TPCVecY+VecZ*TPCVecZ)/(TPCVecX*TPCVecX+TPCVecY*TPCVecY+TPCVecZ*TPCVecZ)
set TPCVecX=(VecX+invscale*(txr1*TPCVecX))*scale
set TPCVecY=(VecY+invscale*(txr1*TPCVecY))*scale
set TPCVecZ=(VecZ+invscale*(txr1*TPCVecZ))*scale
endfunction
function AddProjBX takes unit u returns nothing
local mx x=mx.create()
call SetUnitUserData(u,x)
set x.u=u
set x.x=GetUnitX(u)
set x.y=GetUnitY(u)
set x.z=GetUnitZ(u)
if x.clg==null then
set x.clg=CreateGroup()
else
call GroupClear(x.clg)
endif
//set x.vecx=GetRandomReal(-200,200)
//set x.vecy=GetRandomReal(-200,200)
set TCM_maxunits=TCM_maxunits+1
set TCM_unt[TCM_maxunits]=x
set TCM_untpos[x]=TCM_maxunits
set mmx=x
endfunction
function RemoveProjBX takes mx x returns nothing
if TCM_untpos[x]>0 then
call SetUnitUserData(x.u,0)
set x.u=null
set TCM_unt[TCM_untpos[x]]=TCM_unt[TCM_maxunits]
set TCM_untpos[TCM_unt[TCM_maxunits]]=TCM_untpos[x]
set TCM_untpos[x]=0
set TCM_maxunits=TCM_maxunits-1
call x.destroy()
endif
endfunction
function RemoveStoneProjBX takes mx x returns nothing
if TCM_untpos[x]>0 then
call SetUnitTimeScale(x.u,1)
call SetUnitAnimation(x.u,"death")
call RecycleUnitTimed(x.u,x.unitrecyclet)
call GroupRemoveUnit(x.xcas.stones,x.u)
call RemoveProjBX(x)
endif
endfunction
function StoneCrusherSoundFX takes real x,real y returns nothing
local sound s=CreateSound("Abilities\\Weapons\\Catapult\\CatapultMissile"+I2S(GetRandomInt(1,4))+".wav",false,true,false,10,10,"")
local sound s1=CreateSound("Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissileHit"+I2S(GetRandomInt(1,3))+".wav",false,true,false,10,10,"")
local real z=GetLocationZ(MoveLocBR(tmploc,x,y))
call SetSoundVolume(s,GetRandomInt(110,150))
call SetSoundVolume(s1,GetRandomInt(110,150))
call SetSoundChannel(s,GetRandomInt(0,11))
call SetSoundChannel(s1,GetRandomInt(0,11))
call SetSoundDistances(s,600,100000)
call SetSoundDistances(s1,600,100000)
call SetSoundConeAngles(s,0,0,0)
call SetSoundConeAngles(s1,0,0,0)
call SetSoundDistanceCutoff(s,3400)
call SetSoundDistanceCutoff(s1,3400)
call SetSoundPosition(s,x,y,z)
call SetSoundPosition(s1,x,y,z)
call SetSoundPitch(s,GetRandomReal(0.75,1))
call SetSoundPitch(s1,GetRandomReal(0.75,1))
call StartSound(s)
call StartSound(s1)
call KillSoundWhenDone(s)
call KillSoundWhenDone(s1)
set s=null
set s1=null
endfunction
//#############################
//## COLLISION ##
//#############################
function CollisionBX takes nothing returns boolean
//clg
set eux=GetFilterUnit()
set mmx0=GetUnitUserData(eux)
if mmx0!=mmx then
if GetUnitAbilityLevel(eux,IS_DUMMY)>0 then
if not IsUnitInGroup(mmx0.u,mmx.clg) then
set txr0=mmx0.x-mmx.x
set txr1=mmx0.y-mmx.y
set txr2=mmx0.z-mmx.z
set txr=SquareRoot(txr0*txr0+txr1*txr1+txr2*txr2)+0.001
//call echo("DETECT")
if txr<mmx.rad+mmx0.rad then
//call echo("IS OK")
call GroupAddUnit(mmx0.clg,mmx.u)
// CORRECTION
set txr3=(mmx.rad+mmx0.rad)/txr
if mmx.z<=mmx0.z then
set mmx0.x=(mmx.x+txr0*1.005*txr3)
set mmx0.y=(mmx.y+txr1*1.005*txr3)
set mmx0.z=(mmx.z+txr2*1.005*txr3)
else
set mmx.x=(mmx0.x-txr0*1.005*txr3)
set mmx.y=(mmx0.y-txr1*1.005*txr3)
set mmx.z=(mmx0.z-txr2*1.005*txr3)
endif
// BEGIN
set txr0=txr0/txr
set txr1=txr1/txr
set txr2=txr2/txr
set txr4=-txr2
set txr5=-txr1
set txr6=txr0
// v1n
set txr7=txr0*mmx.vecx+txr1*mmx.vecy+txr2*mmx.vecz
// v1t
set txr8=txr4*mmx.vecx+txr5*mmx.vecy+txr6*mmx.vecz
// v2n
set txr9=txr0*mmx0.vecx+txr1*mmx0.vecy+txr2*mmx0.vecz
// v2t
set txr10=txr4*mmx0.vecx+txr5*mmx0.vecy+txr6*mmx0.vecz
set txr11=mmx.mass+mmx0.mass+0.001
set txr12=(txr7*(mmx.mass-mmx0.mass)+2.*mmx0.mass*txr9)/txr11
set txr13=(txr9*(mmx0.mass-mmx.mass)+2.*mmx.mass*txr7)/txr11
set txr14=mmx.elastic*mmx0.elastic
set mmx.vecx=(txr12*txr0+txr8*txr4)*txr14
set mmx.vecy=(txr12*txr1+txr8*txr5)*txr14
set mmx.vecz=(txr12*txr2+txr8*txr6)//*txr14
set mmx0.vecx=(txr13*txr0+txr10*txr4)*txr14
set mmx0.vecy=(txr13*txr1+txr10*txr5)*txr14
set mmx0.vecz=(txr13*txr2+txr10*txr6)//*txr14
// ENDCOLLISON
endif
endif
else
// SIMPLE UNIT
if GetWidgetLife(eux)>0.5 and mmx.caster!=eux then
set txr0=GetUnitHeightBX(eux)
set txr1=GetUnitZ(eux)
if mmx.z+mmx.rad>=txr1 and mmx.z-mmx.rad<=txr1+txr0 then
if DistanceBetweenCord(mmx.x-GetUnitX(eux),mmx.y-GetUnitY(eux))<=GetUnitCollisionBX(eux)+mmx.rad then
set txr10=ReduceThanLessBX(DistanceIn3D(mmx.vecx,mmx.vecy,mmx.vecz),100,0)*mmx.disdmg*mmx.mass
if txr10>0 then
set txr11=GetWidgetLife(eux)
set txr12=txr11/txr10
if txr11>=txr10 then
call RemoveStoneProjBX(mmx)
else
set mmx.vecx=mmx.vecx*txr12
set mmx.vecy=mmx.vecy*txr12
set mmx.vecz=mmx.vecz*txr12
endif
call UnitDamageTarget(mmx.caster,eux,txr10,true,true,mmx.atype,mmx.dtype,mmx.wtype)
endif
endif
endif
endif
endif
endif
return false
endfunction
//#############################
//## ADVANCED COLLISION ##
//#############################
function CollisionAdvBX takes nothing returns boolean
//clg
set eux=GetFilterUnit()
set mmx0=GetUnitUserData(eux)
if mmx0!=mmx then
if GetUnitAbilityLevel(eux,IS_DUMMY)>0 then
if not IsUnitInGroup(mmx0.u,mmx.clg) then
// vec
set txrx0=mmx0.vecx-mmx.vecx//(mmx0.vecx+mmx0.vecfx*x_per)-mmx.vecx
set txrx1=mmx0.vecy-mmx.vecy//(mmx0.vecy+mmx0.vecfy*x_per)-mmx.vecy
set txrx2=mmx0.vecz-mmx.vecz//(mmx0.vecz+mmx0.vecfz*x_per)-mmx.vecz
// pos
set txrx3=mmx0.x-mmx.x
set txrx4=mmx0.y-mmx.y
set txrx5=mmx0.z-mmx.z
set txrx=mmx0.rad+mmx.rad
//a
set txrx6=txrx0*txrx0+txrx1*txrx1+txrx2*txrx2
//b
set txrx7=2*(txrx0*txrx3+txrx1*txrx4+txrx2*txrx5)
//c
set txrx8=txrx3*txrx3+txrx4*txrx4+txrx5*txrx5-txrx*txrx
if txrx6!=0 then
set txrx3=(-txrx7-SquareRoot(txrx7*txrx7-4*txrx6*txrx8))/(2*txrx6)
else
set txrx3=0
endif
//call echo("Time To Collide "+R2SW(txrx3,10,10))
if txrx3<=x_per and txrx3>=0 then
//call echo("Time To Collide "+R2SW(txrx3,10,10))
set txrx4=mmx.x+mmx.vecx*txrx3
set txrx5=mmx.y+mmx.vecy*txrx3
set txrx6=mmx.z+mmx.vecz*txrx3
set txrx7=mmx0.x+mmx0.vecx*txrx3
set txrx8=mmx0.y+mmx0.vecy*txrx3
set txrx9=mmx0.z+mmx0.vecz*txrx3
set txr0=txrx7-txrx4
set txr1=txrx8-txrx5
set txr2=txrx9-txrx6
set txr=SquareRoot(txr0*txr0+txr1*txr1+txr2*txr2)+0.001
//call echo("DETECT")
//call echo("DIS "+R2S(txr)+" RAN "+R2S(txrx))
//call echo("Z dis "+R2S(txr))
if RAbs(txr2)<=txrx then//if txr<=txrx+0.002 then
//call echo("IS OK")
call GroupAddUnit(mmx0.clg,mmx.u)
set txrx16=txrx16-txrx3
// BEGIN
set txr0=txr0/txr
set txr1=txr1/txr
set txr2=txr2/txr
set txr4=-txr2
set txr5=-txr1
set txr6=txr0
// v1n
set txr7=txr0*mmx.vecx+txr1*mmx.vecy+txr2*mmx.vecz
// v1t
set txr8=txr4*mmx.vecx+txr5*mmx.vecy+txr6*mmx.vecz
// v2n
set txr9=txr0*mmx0.vecx+txr1*mmx0.vecy+txr2*mmx0.vecz
// v2t
set txr10=txr4*mmx0.vecx+txr5*mmx0.vecy+txr6*mmx0.vecz
set txr11=mmx.mass+mmx0.mass+0.001
set txr12=(txr7*(mmx.mass-mmx0.mass)+2.*mmx0.mass*txr9)/txr11
set txr13=(txr9*(mmx0.mass-mmx.mass)+2.*mmx.mass*txr7)/txr11
set txr14=mmx.elastic*mmx0.elastic
set mmx.vecx=(txr12*txr0+txr8*txr4)*txr14
set mmx.vecy=(txr12*txr1+txr8*txr5)*txr14
set mmx.vecz=(txr12*txr2+txr8*txr6)//*txr14
set mmx0.vecx=(txr13*txr0+txr10*txr4)*txr14
set mmx0.vecy=(txr13*txr1+txr10*txr5)*txr14
set mmx0.vecz=(txr13*txr2+txr10*txr6)//*txr14
if txrx16>0 then
set mmx.x=txrx4+mmx.vecx*txrx16
set mmx.y=txrx5+mmx.vecy*txrx16
set mmx.z=txrx6+mmx.vecz*txrx16
set mmx0.x=txrx7+mmx0.vecx*txrx16
set mmx0.y=txrx8+mmx0.vecy*txrx16
set mmx0.z=txrx9+mmx0.vecz*txrx16
endif
// ENDCOLLISON
endif
endif
endif
else
// SIMPLE UNIT
if GetWidgetLife(eux)>0.5 and mmx.caster!=eux then
set txr0=GetUnitHeightBX(eux)
set txr1=GetUnitZ(eux)
if mmx.z+mmx.rad>=txr1 and mmx.z-mmx.rad<=txr1+txr0 then
if DistanceBetweenCord(mmx.x-GetUnitX(eux),mmx.y-GetUnitY(eux))<=GetUnitCollisionBX(eux)+mmx.rad then
set txr10=ReduceThanLessBX(DistanceIn3D(mmx.vecx,mmx.vecy,mmx.vecz),100,0)*mmx.disdmg*mmx.mass
if txr10>0 then
set txr11=GetWidgetLife(eux)
set txr12=txr11/txr10
if txr11>=txr10 then
call RemoveStoneProjBX(mmx)
else
set mmx.vecx=mmx.vecx*txr12
set mmx.vecy=mmx.vecy*txr12
set mmx.vecz=mmx.vecz*txr12
endif
call UnitDamageTarget(mmx.caster,eux,txr10,true,true,mmx.atype,mmx.dtype,mmx.wtype)
endif
endif
endif
endif
endif
endif
return false
endfunction
globals
timer shaketimer=CreateTimer()
endglobals
function ResetCameraNoise takes nothing returns nothing
call CameraSetTargetNoiseEx(0,0,false)
call CameraSetSourceNoiseEx(0,0,false)
call CameraSetSmoothingFactor(0)
endfunction
//#############################
//## MAIN LOOP ##
//#############################
function RunSys takes nothing returns nothing
local integer i=TCM_maxunits
local mx x=TCM_unt[i]
local real z
local location l=tmploc
local real r=0
local real r1=0
local real r2=0
local real r3=0
local real xx=0
local real yy=0
local real zz=0
loop
exitwhen i<1
call GroupClear(x.clg)
set i=i-1
set x=TCM_unt[i]
endloop
set i=TCM_maxunits
set x=TCM_unt[i]
//x_per
loop
exitwhen i<1
//##########
set x.vecx=x.vecx+x.vecfx*x_per
set x.vecy=x.vecy+x.vecfy*x_per
set x.vecz=x.vecz+x.vecfz*x_per
set xx=x.x
set yy=x.y
set zz=x.z
call SetUnitTimeScale(x.u,(ReduceThanLessBX(DistanceIn3D(x.vecx,x.vecy,x.vecz),125,0)*0.001))
set mmx=x
// COLLISON
if SquareRoot(x.vecx*x.vecx+x.vecy*x.vecy+x.vecz*x.vecz)*x_per<=x.rad then
set x.x=x.x+x.vecx*x_per
set x.y=x.y+x.vecy*x_per
set x.z=x.z+x.vecz*x_per
call GroupEnumUnitsInRange(dummygroup,x.x,x.y,x.rad*2+1,collision)
else
// EXTENDED ALG
set txrx16=x_per
call GroupEnumUnitsInRange(dummygroup,x.x,x.y,x.rad*2+SquareRoot(x.vecx*x.vecx+x.vecy*x.vecy)*x_per,collisionadv)
if txrx16>0 then
set x.x=x.x+x.vecx*txrx16
set x.y=x.y+x.vecy*txrx16
set x.z=x.z+x.vecz*txrx16
endif
endif
call MoveLocation(l,x.x,x.y)
set z=GetLocationZ(l)
if x.z<=z+x.rad then
set x.z=z+x.rad
if -x.vecz*x.scale>x.toshake then
// add effect + shake cam
call AddEffect(x.groundeffect,x.x,x.y)
call StoneCrusherSoundFX(x.x,x.y)
if x.shakecam then
call CameraSetSmoothingFactor(1)
call CameraSetTargetNoiseEx(25,200,true)
call TimerStart(shaketimer,0.15,false,function ResetCameraNoise)
endif
//
endif
// REFLECT
// size is 16
call MoveLocation(l,x.x-16,x.y)
set r=GetLocationZ(l)
call MoveLocation(l,x.x+16,x.y)
set r1=-32*(GetLocationZ(l)-r)
call MoveLocation(l,x.x,x.y-16)
set r=GetLocationZ(l)
call MoveLocation(l,x.x,x.y+16)
set r2=-32*(GetLocationZ(l)-r)
// TPCVecZ=1024
set r3=(x.vecx*r1+x.vecy*r2+x.vecz*1024)/(r1*r1+r2*r2+1048576)
set x.vecx=(x.vecx+(-2)*(r3*r1))*x.refscale
set x.vecy=(x.vecy+(-2)*(r3*r2))*x.refscale
set x.vecz=(x.vecz+(-2)*(r3*1024))*x.refscale
endif
if x.x>MapBoundMinX and x.y>MapBoundMinY and x.x<MapBoundMaxX and x.y<MapBoundMaxY then
if DistanceIn3D(xx-x.x,yy-x.y,zz-x.z)>x.stackness then
call SetUnitX(x.u,x.x)
call SetUnitY(x.u,x.y)
else
set x.x=xx
set x.y=yy
endif
else
if x.x<MapBoundMinX then
set x.vecx=-x.vecx
set x.x=MapBoundMinX+1
elseif x.x>MapBoundMaxX then
set x.vecx=-x.vecx
set x.x=MapBoundMaxX-1
elseif x.y<MapBoundMinY then
set x.vecy=-x.vecy
set x.y=MapBoundMinY+1
elseif x.y>MapBoundMaxY then
set x.vecy=-x.vecy
set x.y=MapBoundMaxY-1
else
set x.vecx=-x.vecx
set x.vecy=-x.vecy
endif
endif
call SetUnitFlyHeight(x.u,x.z-z,0)
//##########
set i=i-1
set x=TCM_unt[i]
endloop
endfunction
function InitTrig_Run takes nothing returns nothing
call TimerStart(CreateTimer(),x_per,true,function RunSys)
call ExecuteFunc("InitUnitHeightsBX")
set collision=Condition(function CollisionBX)
set collisionadv=Condition(function CollisionAdvBX)
call UnitInit(200)
call TimerInit(500)
call FogEnable(false)
call FogMaskEnable(false)
//
set MapBoundMinX=GetCameraBoundMinX()
set MapBoundMinY=GetCameraBoundMinY()
set MapBoundMaxX=GetCameraBoundMaxX()
set MapBoundMaxY=GetCameraBoundMaxY()
set tmploc=Location(0,0)
endfunction
struct stone_crusher_caster
group stones
endstruct
function CreateStoneCrusher takes unit cas,integer lvl,real x,real y returns nothing
local unit u
local integer i=1
local integer max=10*lvl
local real r
local real xx=0
local real yy=0
local real zz=0
local real xy=lvl*40
local real z=GetLocationZ(MoveLocBR(tmploc,x,y))+GetRandomReal(1000+lvl*100,1300+lvl*150)
local stone_crusher_caster sc=GetUnitUserData(cas)
loop
exitwhen i>max
set xx=GetRandomReal(x-xy,x+xy)
set yy=GetRandomReal(y-xy,y+xy)
set zz=GetRandomReal(z-xy,z+xy)
set r=GetRandomReal(0.25+(lvl*0.2),2)
set u=GetUnitBR()
call SetUnitX(u,xx)
call SetUnitY(u,yy)
call SetUnitScale(u,r,r,r)
call SetUnitFlyHeight(u,zz,0)
call AddProjBX(u)
call GroupAddUnit(sc.stones,u)
set mmx.xcas=sc
set mmx.disdmg=0.25*lvl+0.15
set mmx.scale=r
set mmx.caster=cas
set mmx.x=xx
set mmx.y=yy
set mmx.vecx=GetRandomReal(-100,100)
set mmx.vecy=GetRandomReal(-100,100)
set mmx.vecz=GetRandomReal(-1000-lvl*200,-600)
set mmx.rad=22.5*r
set mmx.mass=r
set i=i+1
endloop
set u=null
endfunction
function Trig_Untitled_Trigger_001_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A002'
endfunction
function StoneCrusherCleanStones takes nothing returns nothing
call RemoveStoneProjBX(GetUnitUserData(GetEnumUnit()))
endfunction
function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
local location l=GetSpellTargetLoc()
local stone_crusher_caster sc
set eux=GetTriggerUnit()
if GetUnitUserData(eux)==0 then
call SetUnitUserData(eux,integer(stone_crusher_caster.create()))
set sc=GetUnitUserData(eux)
set sc.stones=CreateGroup()
else
set sc=GetUnitUserData(eux)
endif
call ForGroup(sc.stones,function StoneCrusherCleanStones)
call GroupClear(sc.stones)
call CreateStoneCrusher(eux,GetUnitAbilityLevel(eux,GetSpellAbilityId()),GetLocationX(l),GetLocationY(l))
call RemoveLocation(l)
set l=null
endfunction
//===========================================================================
function InitTrig_Spell_StoneCrusher takes nothing returns nothing
set gg_trg_Spell_StoneCrusher = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Spell_StoneCrusher, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Spell_StoneCrusher, Condition( function Trig_Untitled_Trigger_001_Conditions ) )
call TriggerAddAction( gg_trg_Spell_StoneCrusher, function Trig_Untitled_Trigger_001_Actions )
endfunction
function Trig_xxxx_Actions takes nothing returns nothing
local unit u=GetAttacker()
local unit tar=GetTriggerUnit()
local mx x
if GetUnitTypeId(u)=='N000' and GetUnitTypeId(tar)=='e001' then
set x=GetUnitUserData(tar)
call CreateVecBR(GetUnitX(u),GetUnitY(u),GetUnitZ(u),x.x,x.y,x.z)
call SetVecLengthBR(TPCVecX,TPCVecY,TPCVecZ,(GetHeroStr(u,true)*20)/(x.mass+0.001))
set x.vecx=TPCVecX
set x.vecy=TPCVecY
set x.vecz=TPCVecZ
endif
endfunction
//===========================================================================
function InitTrig_xxxx takes nothing returns nothing
set gg_trg_xxxx = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_xxxx, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddAction( gg_trg_xxxx, function Trig_xxxx_Actions )
endfunction