- Joined
- Mar 6, 2012
- Messages
- 64
Warcraft 3 modding community led me to take Computer Science course and I am really thankful for it. I was like 11 or 12 when I created my first spell and posted it on here (dont look it up, its really bad) and now I'm back for reforged.
I'm using Jass now and created a physics and missile system for my map and I'm wondering if my code can further be optimized
As you can see, my physics system is somehow similar to Quillnez rigid body physics except that it doesn't work in upward slope (For balance purposes)
I'm using Jass now and created a physics and missile system for my map and I'm wondering if my code can further be optimized
JASS:
struct physics
unit Target
real dist=0
real vel=0
real friction=0
real velZ=0
real z=0
real sin=0
real cos=0
boolean affGrav =true
//string animation
//string effect
endstruct
struct effectMissile
effect model
real x
real y
real z = 60
real tx
real ty
real tz
real angle
real dis
real vel
real turnrate = 1
//damage
unit owner
unit target
real damage
damagetype dmgtype
////for Altair, melee = 0; defend = 1; missile = 2
integer state
// if missile deals aoe damage
real HitZ = 60
boolean areaEffect = false
boolean homing = true
//first unit hit = FUHit
boolean FUHit
endstruct
struct Altair
unit caster
//swords that will encircle/defend Altair
effectMissile array sword[20]
integer swordCount
endstruct
globals
timer pArTimer = CreateTimer()
physics array pAr
Altair array altair
effectMissile array missile
integer misTotal = 0
integer altTotal = 0
integer pArTotal = 0
constant real knockbackFricPerc = 0.0
constant real knockbackFricReal = 0.0
constant real TimerInterval = 0.0165
constant real gravity = 9.8*200
endglobals
function Physics takes integer i, physics p returns nothing
local real nextZ
local real x
local real y
//knockback
set x = GetUnitX(p.Target) + p.vel* p.cos
set y = GetUnitY(p.Target) + p.vel* p.sin
if p.dist > 0 and x>GetRectMinX(GetPlayableMapRect()) and x<GetRectMaxX(GetPlayableMapRect()) and y>GetRectMinY(GetPlayableMapRect()) and y<GetRectMaxY(GetPlayableMapRect()) then
call SetUnitX(p.Target,x)
call SetUnitY(p.Target,y)
endif
set p.dist = p.dist - p.vel
set p.vel = p.vel - (p.vel*p.friction)
if p.vel <= 2 then
set p.vel = 2
endif
//set final flying height
//set p.z = GetUnitFlyHeight(p.Target)+BlzGetLocalUnitZ(p.Target)
//knockup
set nextZ = p.z + p.velZ*TimerInterval
if (nextZ - BlzGetLocalUnitZ(p.Target)) >0 then
call UnitAddAbilityBJ( 'Amrf', p.Target )
call SetUnitFlyHeight( p.Target , nextZ-BlzGetLocalUnitZ(p.Target), 999999.00 )
call UnitRemoveAbilityBJ( 'Amrf', p.Target )
if p.affGrav == true then
set p.velZ = p.velZ - gravity*TimerInterval
endif
set p.z = nextZ
else
set p.velZ = 0
set p.z = GetUnitFlyHeight(p.Target)+BlzGetLocalUnitZ(p.Target)
endif
//finish
if (nextZ-BlzGetLocalUnitZ(p.Target)) <= 0 and p.dist <= 0 then
set pAr[i] = pAr[pArTotal - 1]
set pArTotal = pArTotal - 1
call p.destroy()
endif
endfunction
function MissileSystem takes integer i, effectMissile m returns nothing
local real angle = m.angle + 360
local real angleto
local real pitch = RAbsBJ(Atan2((m.tz-m.z),m.dis))
set m.x = m.x + Cos(angle * bj_DEGTORAD)*m.vel
set m.y = m.y + Sin(angle * bj_DEGTORAD)*m.vel
if m.homing then
set m.dis = SquareRoot(((m.tx-m.x)*(m.tx-m.x))+((m.ty-m.y)*(m.ty-m.y)))
endif
set m.z = m.z + ((m.tz-m.z)/((m.dis*0.1)+1))
if m.z <= 0 then
set m.z = 60
endif
set angleto = Atan2BJ((m.ty-m.y),(m.tx-m.x))
///////////////calculate angle ////////////////////////////
if not ((m.angle >0 and angleto>0)or(m.angle <0 and angleto<0)) then
if angleto<0 then
if RAbsBJ(m.angle -(angleto+360))< RAbsBJ(m.angle - angleto) then
if RAbsBJ(m.angle -(angleto+360)) >= m.turnrate then
set m.angle =m.angle + m.turnrate
else
set m.angle = angleto
endif
else
if RAbsBJ(m.angle - angleto) >= m.turnrate then
set m.angle =m.angle - m.turnrate
else
set m.angle = angleto
endif
endif
else
if RAbsBJ(angleto-(m.angle+360))< RAbsBJ(angleto - m.angle) then
if RAbsBJ(angleto-(m.angle+360)) >= m.turnrate then
set m.angle =m.angle - m.turnrate
else
set m.angle = angleto
endif
else
if RAbsBJ(angleto-m.angle) >= m.turnrate then
set m.angle =m.angle + m.turnrate
else
set m.angle = angleto
endif
endif
endif
else
if RAbsBJ(m.angle-angleto)>= m.turnrate then
if m.angle<angleto then
set m.angle = m.angle + m.turnrate
else
set m.angle = m.angle - m.turnrate
endif
else
set m.angle = angleto
endif
endif
if m.angle > 180 then
set m.angle = m.angle -360
else
if m.angle <-180 then
set m.angle = m.angle +360
endif
endif
//////////////////////////////////////////////
//call DisplayTextToForce( GetPlayersAll(), R2S(m.y) )
//move missile
call BlzSetSpecialEffectOrientation(m.model,0,pitch,m.angle* bj_DEGTORAD)
call BlzSetSpecialEffectPosition(m.model,m.x,m.y,m.z)
//finish
///damage
if m.areaEffect then
if m.dis<=0 then
set missile[i] = missile[misTotal - 1]
set misTotal = misTotal - 1
call DestroyEffect(m.model)
call m.destroy()
endif
set m.tx = GetUnitX(m.target)
set m.ty = GetUnitY(m.target)
set m.tz = GetUnitFlyHeight(m.target)+BlzGetLocalUnitZ(m.target)
else
if m.homing then
if m.dis<=50 then
set missile[i] = missile[misTotal - 1]
set misTotal = misTotal - 1
call DestroyEffect(m.model)
call m.destroy()
else
set m.tx = GetUnitX(m.target)
set m.ty = GetUnitY(m.target)
set m.tz = GetUnitFlyHeight(m.target)+BlzGetLocalUnitZ(m.target)
endif
endif
endif
endfunction
function AltairSystem takes integer i, Altair a returns nothing
endfunction
function Loop takes nothing returns nothing
//declare locals here
local physics p
local effectMissile m
local Altair a
////Physics
local integer i = 0
loop
exitwhen i>=pArTotal
set p = pAr[i]
call Physics(i,p)
set i = i+1
endloop
////EndPhysics
////Missile
set i = 0
loop
exitwhen i >= misTotal
set m = missile[i]
call MissileSystem(i,m)
set i = i+1
endloop
////EndMissile
////Altair
set i = 0
loop
exitwhen i>=altTotal
set a = altair[i]
call AltairSystem(i,a)
set i = i+1
endloop
///EndAltair
if pArTotal == 0 and misTotal == 0 then
call PauseTimer(pArTimer)
endif
endfunction
/////////////////////////////////////////////////////////////////////////////////
function CheckUnitPhysics takes unit Target returns integer
local integer i = 0
local integer r = -1
loop
exitwhen i >= pArTotal
if pAr[i].Target == Target then
set r = i
endif
set i = i + 1
endloop
return r
endfunction
function ApplyForceDis takes unit target, real dist, real angle returns nothing
endfunction
function ApplyForceDisFric takes unit target, real dist, real vel, real angle, real fric returns nothing
local physics p = physics.create()
local real initZ = GetUnitFlyHeight(target)+BlzGetLocalUnitZ(target)
local integer r = CheckUnitPhysics(target)
if r == -1 then
//setthing for p
set p.Target = target
set p.vel = vel
set p.friction = fric
set p.dist = dist
set p.sin = Sin(angle * bj_DEGTORAD)
set p.cos = Cos(angle * bj_DEGTORAD)
set p.z = initZ
//startphysics
if pArTotal == 0 and misTotal == 0 then
call TimerStart(pArTimer,TimerInterval,true,function Loop)
endif
set pAr[pArTotal] = p
set pArTotal = pArTotal + 1
else
set pAr[r].vel = vel
set pAr[r].friction = fric
set pAr[r].dist = dist
set pAr[r].sin = Sin(angle * bj_DEGTORAD)
set pAr[r].cos = Cos(angle * bj_DEGTORAD)
set pAr[r].z = initZ
endif
endfunction
function ApplyForceZheightAdd takes unit target, real maxheight returns nothing
local physics p = physics.create()
local real initZ = GetUnitFlyHeight(target)+BlzGetLocalUnitZ(target)
local real initvel = SquareRoot(2*gravity*maxheight)
local integer r = CheckUnitPhysics(target)
if r == -1 then
//setthing for p
set p.Target = target
set p.velZ = initvel
set p.z = initZ
//startphysics
if pArTotal == 0 and misTotal == 0 then
call TimerStart(pArTimer,TimerInterval,true,function Loop)
endif
set pAr[pArTotal] = p
set pArTotal = pArTotal + 1
else
call DisplayTextToForce( GetPlayersAll(), I2S(r) )
set pAr[r].velZ = initvel
set pAr[r].z = initZ
endif
endfunction
function ApplyForceZheight takes unit target, real maxheight returns nothing
local physics p = physics.create()
local real initZ = GetUnitFlyHeight(target)+BlzGetLocalUnitZ(target)
local real initvel = SquareRoot(2*gravity*(maxheight-initZ))
local integer r = CheckUnitPhysics(target)
if r == -1 then
//setthing for p
set p.Target = target
set p.velZ = initvel
set p.z = initZ
//startphysics
if pArTotal == 0 and misTotal == 0 then
call TimerStart(pArTimer,TimerInterval,true,function Loop)
endif
set pAr[pArTotal] = p
set pArTotal = pArTotal + 1
else
call DisplayTextToForce( GetPlayersAll(), "found" )
set pAr[r].velZ = initvel
set pAr[r].z = initZ
endif
endfunction
/////////////////////////////////////////////////////////////////////////////////
function AltairSwordCircle takes unit caster returns nothing
endfunction
function AltairSwordAdd takes unit caster returns nothing
endfunction
function FireMissile takes effectMissile m returns nothing
if pArTotal == 0 and misTotal == 0 then
call TimerStart(pArTimer,TimerInterval,true,function Loop)
endif
set missile[misTotal] = m
set misTotal = misTotal + 1
endfunction
function CreateMissileHomingTR takes unit owner, unit target, string model, location loc, real angle, real velocity, real turnrate returns nothing
local effectMissile m = effectMissile.create()
call AddSpecialEffectLocBJ( loc, model )
set m.model = GetLastCreatedEffectBJ()
set m.x = GetLocationX(loc)
set m.y = GetLocationY(loc)
set m.z = GetUnitFlyHeight(owner)+BlzGetLocalUnitZ(owner)+60
call RemoveLocation(loc)
set m.owner = owner
set m.target = target
set m.turnrate = turnrate*TimerInterval
set m.angle = angle
set m.vel = velocity
set m.homing = true
set m.tx = GetUnitX(m.target)
set m.ty = GetUnitY(m.target)
set m.tz = GetUnitFlyHeight(m.target)+BlzGetLocalUnitZ(m.target)
call FireMissile(m)
endfunction
As you can see, my physics system is somehow similar to Quillnez rigid body physics except that it doesn't work in upward slope (For balance purposes)