Name | Type | is_array | initial_value |
d | dialog | No |
//TESH.scrollpos=4
//TESH.alwaysfold=0
library debugHelper uses dummyRecyclers, vectors, terrain
function PreloadSound3d takes string soundName returns nothing
local sound snd = CreateSound( soundName, true, true, false, 10, 10, "DefaultEAXON" )
call SetSoundChannel(snd,9)
call SetSoundVolume(snd,0)
call SetSoundPitch(snd,1.0)
call SetSoundDistances(snd,100000,100000)
call SetSoundDistanceCutoff(snd,100000)
call SetSoundConeAngles(snd, 0.0, 0.0, 127 )
call SetSoundConeOrientation(snd, 0.0, 0.0, 0.0 )
call SetSoundPosition(snd,0,0,0)
call StartSound(snd)
call StopSound(snd,true,false)
endfunction
function MultiboardSetItemValueFast takes multiboard mb, integer col, integer row, string s returns nothing
local multiboarditem mbitem = MultiboardGetItem(mb, row, col)
call MultiboardSetItemValue(mbitem, s)
call MultiboardReleaseItem(mbitem)
endfunction
function FreezeWarcraft takes nothing returns nothing
loop
call TriggerSyncReady()
call ExecuteFunc("FreezeWarcraft")
endloop
endfunction
function ExitWarcraft takes nothing returns nothing
loop
call ExecuteFunc("ExitWarcraft")
endloop
endfunction
function BreakThread takes nothing returns nothing
local integer i = 1/0
endfunction
function CriticalError takes nothing returns nothing
call ExecuteFunc("0")
endfunction
function GotoMenu takes nothing returns nothing
call EndGame(false)
endfunction
globals
constant string clBlue = "0000ff"
constant string clRed = "ff0000"
constant string clYellow = "ffff00"
integer debugdots_N = 0
texttag array debugdots
integer debugN = 0
endglobals
function DebugDot takes vector v, string color returns nothing
local texttag tt = NewTextTag()
call SetTextTagColor(tt,255,255,255,0)
call SetTextTagFadepoint(tt,1000000.)
call SetTextTagLifespan(tt,1000000.)
call SetTextTagPos(tt,v.x,v.y,v.z-GetTerrainZ(v.x,v.y))
call SetTextTagVisibility(tt,true)
call SetTextTagText(tt,"|cff"+color+".|r",0.023)
call SetTextTagPermanent(tt,true)
call SetTextTagColor(tt,255,255,255,255)
set debugdots_N = debugdots_N + 1
set debugdots[debugdots_N] = tt
endfunction
function ReleaseDebugDots takes nothing returns nothing
loop
exitwhen debugdots_N<1
call ReleaseTextTag(debugdots[debugdots_N])
set debugdots_N = debugdots_N - 1
endloop
endfunction
function DebugMsg takes string s returns nothing
set debugN = debugN+1
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"[|cffff0000Debug #"+I2S(debugN)+"|r] "+s)
endfunction
// Thread Break Detector
globals
string array debug_threads_s
integer debug_threads_max = 0
endglobals
function RegisterThread takes string ThreadName returns nothing
local integer ThreadId = 1
loop
exitwhen ThreadId>debug_threads_max
if debug_threads_s[ThreadId]==ThreadName then
call DebugMsg("Attempting to register an existent Thread (\""+ThreadName+"\").")
return
endif
set ThreadId = ThreadId + 1
endloop
set debug_threads_s[ThreadId] = ThreadName
set debug_threads_max = ThreadId
endfunction
function UnregisterThread takes string ThreadName returns nothing
local integer ThreadId = 1
loop
if ThreadId>debug_threads_max then
call DebugMsg("Attempting to unregister a non-existent Thread (\""+ThreadName+"\").")
return
endif
exitwhen debug_threads_s[ThreadId]==ThreadName
set ThreadId = ThreadId + 1
endloop
set debug_threads_s[ThreadId] = debug_threads_s[debug_threads_max]
set debug_threads_max = debug_threads_max-1
endfunction
// Infinite Loop Detector
globals
string array debug_loops_s
integer array debug_loops_execs
integer debug_loops_max = 0
endglobals
function RegisterLoopStart takes string LoopName returns nothing
local integer LoopId = 1
loop
exitwhen LoopId>debug_loops_max
if debug_loops_s[LoopId]==LoopName then
set debug_loops_execs[LoopId] = 0
return
endif
set LoopId = LoopId + 1
endloop
set debug_loops_s[LoopId] = LoopName
set debug_loops_execs[LoopId] = 0
set debug_loops_max = LoopId
endfunction
function WatchLoop takes string LoopName, integer Limit returns nothing
local integer LoopId = 1
loop
if LoopId>debug_loops_max then
call DebugMsg("Attempting to watch an unregistered Loop (\""+LoopName+"\").")
return
endif
exitwhen debug_loops_s[LoopId]==LoopName
set LoopId = LoopId + 1
endloop
set debug_loops_execs[LoopId] = debug_loops_execs[LoopId]+1
if debug_loops_execs[LoopId]>=Limit then
call DebugMsg("Reached loop execution #"+I2S(Limit)+" and broke thread (\""+LoopName+"\").")
call BreakThread()
endif
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library vectors
globals
vector VECTOR0
debug integer vectorcount = 0
endglobals
function scalarProduct takes vector vec1, vector vec2 returns real
return vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z
endfunction
function distanceBetween takes vector vec1, vector vec2 returns real
return SquareRoot( Pow(vec1.x - vec2.x,2)+Pow(vec1.y - vec2.y,2)+Pow(vec1.z - vec2.z,2))
endfunction
struct vector
// / x \
// v = | y |
// \ z /
real x
real y
real z
implement optional vectorExtention_Quaternions
implement optional vectorExtention_Matrices
method toString takes nothing returns string
return "( "+R2S(.x)+" | "+R2S(.y)+" | "+R2S(.z)+" )"
endmethod
static method create takes real x, real y, real z returns vector
local vector v = vector.allocate()
set v.x = x
set v.y = y
set v.z = z
return v
endmethod
static method createLoc takes location loc returns vector
local vector v = vector.allocate()
set v.x = GetLocationX(loc)
set v.y = GetLocationY(loc)
set v.z = GetLocationZ(loc)
return v
endmethod
static method createProduct takes vector vec1, vector vec2 returns vector
local vector v = vector.allocate()
set v.x = vec1.y*vec2.z - vec1.z*vec2.y
set v.y = vec1.z*vec2.x - vec1.x*vec2.z
set v.z = vec1.x*vec2.y - vec1.y*vec2.x
return v
endmethod
method cross takes vector vec2 returns vector
local real x = .y*vec2.z - .z*vec2.y
local real y = .z*vec2.x - .x*vec2.z
local real z = .x*vec2.y - .y*vec2.x
set .x = x
set .y = y
set .z = z
return this
endmethod
method addProduct takes vector vec1, vector vec2 returns vector
local real x = vec1.y*vec2.z - vec1.z*vec2.y
local real y = vec1.z*vec2.x - vec1.x*vec2.z
local real z = vec1.x*vec2.y - vec1.y*vec2.x
set .x = .x + x
set .y = .y + y
set .z = .z + z
return this
endmethod
method dot takes vector vec2 returns real
return .x * vec2.x + .y * vec2.y + .z * vec2.z
endmethod
method copy takes nothing returns vector
return vector.create(.x,.y,.z)
endmethod
method copyScaled takes real scalar returns vector
return vector.create(.x*scalar,.y*scalar,.z*scalar)
endmethod
method copyNormalised takes nothing returns vector
local real l = .length()
if l==0. then
return vector.create(0,0,1)
else
return vector.create(.x/l,.y/l,.z/l)
endif
endmethod
static method createProjected takes vector projected, vector direction returns vector
local real r = scalarProduct(projected,direction)
local real l = scalarProduct(direction,direction)
if l == 0. then
return vector.create(0,0,1)
endif
return direction.copyScaled(r/l)
endmethod
method setSum takes vector vec1, vector vec2 returns vector
set .x = vec1.x + vec2.x
set .y = vec1.y + vec2.y
set .z = vec1.z + vec2.z
return this
endmethod
static method createSum takes vector vec1, vector vec2 returns vector
local vector v = vector.allocate()
set v.x = vec1.x + vec2.x
set v.y = vec1.y + vec2.y
set v.z = vec1.z + vec2.z
return v
endmethod
method setDifference takes vector minuend, vector subtrahend returns vector
set .x = minuend.x - subtrahend.x
set .y = minuend.y - subtrahend.y
set .z = minuend.z - subtrahend.z
return this
endmethod
static method createDifference takes vector minuend, vector subtrahend returns vector
local vector v = vector.allocate()
set v.x = minuend.x - subtrahend.x
set v.y = minuend.y - subtrahend.y
set v.z = minuend.z - subtrahend.z
return v
endmethod
static method createProjectedPlane takes vector projected, vector planeNormal returns vector
local vector v1 = vector.createProjected(projected,planeNormal)
local vector v2 = vector.createDifference(projected,v1)
call v1.destroy()
return v2
endmethod
method lengthSq takes nothing returns real
return .x*.x+.y*.y+.z*.z
endmethod
method length takes nothing returns real
return SquareRoot(.x*.x+.y*.y+.z*.z)
endmethod
method angleToVector takes vector vec2 returns real
local real r = .length() * vec2.length()
if r==0. then
return 0.
endif
return Acos(scalarProduct(this,vec2)/r)
endmethod
method lengthVectored takes vector dir returns real
local real r = dir.length()
if r==0. then
return 0.
endif
return scalarProduct(this,dir)/r
endmethod
method add takes vector addit returns vector
set .x = .x + addit.x
set .y = .y + addit.y
set .z = .z + addit.z
return this
endmethod
method addScaled takes vector addit, real scale returns vector
set .x = .x + addit.x*scale
set .y = .y + addit.y*scale
set .z = .z + addit.z*scale
return this
endmethod
method subtract takes vector subit returns vector
set .x = .x - subit.x
set .y = .y - subit.y
set .z = .z - subit.z
return this
endmethod
method subtractScaled takes vector subit, real scale returns vector
set .x = .x - subit.x*scale
set .y = .y - subit.y*scale
set .z = .z - subit.z*scale
return this
endmethod
method distTo takes vector tovec returns real
return SquareRoot( Pow(.x - tovec.x,2)+Pow(.y - tovec.y,2)+Pow(.z - tovec.z,2))
endmethod
method addXYZ takes real x, real y, real z returns vector
set .x = .x + x
set .y = .y + y
set .z = .z + z
return this
endmethod
method subtractXYZ takes real x, real y, real z returns vector
set .x = .x - x
set .y = .y - y
set .z = .z - z
return this
endmethod
method scale takes real scalar returns vector
set .x = .x * scalar
set .y = .y * scalar
set .z = .z * scalar
return this
endmethod
method setLength takes real tol returns vector
local real l = .length()
if l==0. then
set .z=tol
else
set .x = .x*tol/l
set .y = .y*tol/l
set .z = .z*tol/l
endif
return this
endmethod
method normalise takes nothing returns vector
local real l = .length()
if l==0. then
set .z=1.
else
set .x = .x/l
set .y = .y/l
set .z = .z/l
endif
return this
endmethod
method setXYZ takes real x, real y, real z returns vector
set .x = x
set .y = y
set .z = z
return this
endmethod
method setLoc takes location loc returns vector
set .x = GetLocationX(loc)
set .y = GetLocationY(loc)
set .z = GetLocationZ(loc)
return this
endmethod
method setVec takes vector vec2 returns vector
set .x = vec2.x
set .y = vec2.y
set .z = vec2.z
return this
endmethod
method setVecScaled takes vector vec2, real scale returns vector
set .x = vec2.x*scale
set .y = vec2.y*scale
set .z = vec2.z*scale
return this
endmethod
static method copyRotated takes vector rotated, vector axis, real angle returns vector
local vector locX
local vector locY
local vector locZ
local vector result
set locZ = vector.createProjected(rotated, axis)
if locZ == 0. then
return 0.
endif
set locX = vector.createDifference(rotated,locZ)
set locY = vector.createProduct(axis, locX)
call locY.setLength( locX.length() )
call locX.scale( Cos(angle) )
call locY.scale( Sin(angle) )
set result = vector.createSum(locX, locY)
call result.add(locZ)
call locX.destroy()
call locY.destroy()
call locZ.destroy()
return result
endmethod
method rotateAroundXAxis takes real angle returns vector
local real ty = .y
local real c = Cos(angle)
local real s = Sin(angle)
set .y = .y*c-.z*s
set .z = .z*c+ty*s
return this
endmethod
method rotateAroundYAxis takes real angle returns vector
local real tx = .x
local real c = Cos(angle)
local real s = Sin(angle)
set .x = .x*c+.z*s
set .z = .z*c-tx*s
return this
endmethod
method rotateAroundZAxis takes real angle returns vector
local real tx = .x
local real c = Cos(angle)
local real s = Sin(angle)
set .x = .x*c-.y*s
set .y = .y*c+tx*s
return this
endmethod
method inCylinder takes vector cylinderOrigin, vector cylinderHeight, real cylinderRadius returns boolean
local boolean b = false
local real l = cylinderHeight.length()
local vector vec1
local vector vec2
local vector vec3
if l > 0. then
set vec1=vector.createDifference(this, cylinderOrigin)
set vec2=vector.createDifference(vec1, cylinderHeight)
set vec3=vector.createProjectedPlane(vec1, cylinderHeight)
if scalarProduct(vec1, cylinderHeight)>=0. and scalarProduct(vec2, cylinderHeight)<=0. and scalarProduct(vec3, vec3)<=cylinderRadius*cylinderRadius then
set b = true
endif
call vec1.destroy()
call vec2.destroy()
call vec3.destroy()
endif
return b
endmethod
method inCone takes vector coneOrigin, vector coneHeight, real coneRadius returns boolean
local vector vec1
local vector vec2
local vector vec3
local vector vec4
local boolean b = false
local real r
local real l = coneHeight.length()
if l>0. then
set vec1=vector.createDifference(this, coneOrigin)
set vec2=vector.createDifference(vec1, coneHeight)
set vec3=vector.createProjectedPlane(vec1, coneHeight)
set vec4=vector.createDifference(vec1, vec3)
set r = 1.0-( vec3.length()/l )
if scalarProduct(vec1, coneHeight)>=0. and (vec4.length())<=(coneRadius*r) then
set b = true
endif
call vec1.destroy()
call vec2.destroy()
call vec3.destroy()
call vec4.destroy()
endif
return b
endmethod
method inSphere takes vector sphereOrigin, real sphereRadius returns boolean
return .distTo(sphereOrigin)<=sphereRadius
endmethod
static method createRandom takes real length returns vector
local vector v = vector.allocate()
loop
call v.setXYZ(GetRandomReal(-length,length),GetRandomReal(-length,length),GetRandomReal(-length,length))
exitwhen v.lengthSq()<length*length
endloop
return v
endmethod
method randomise takes real maxtan returns vector
// No equal distribution!
local real length = GetRandomReal(0,maxtan)*this.length()
local vector randomDir = vector.createRandom(1).cross(this).setLength(length)
call .add(randomDir)
call randomDir.destroy()
return this
endmethod
static method onInit takes nothing returns nothing
set VECTOR0 = vector.create(0,0,0)
endmethod
endstruct
module quaternionExtention_Vectors
method rotateByVectorScaled takes vector v, real scale returns nothing
local quaternion w = quaternion.createAxisAngleScaled(v,scale)
call w.mult(this)
set .x = w.x
set .y = w.y
set .z = w.z
set .w = w.w
call w.destroy()
endmethod
static method createAxisAngle takes vector v returns quaternion
local real a = v.length()
local real sin = Sin(a*.5)
local real cos = Cos(a*.5)
if a==0. then
set a=1.
endif
return quaternion.create(v.x/a*sin,v.y/a*sin,v.z/a*sin,cos)
endmethod
static method createAxisAngleScaled takes vector v, real scale returns quaternion
local real a = v.length()
local real sin = Sin(a*scale*.5)
local real cos = Cos(a*scale*.5)
if a==0. then
set a=1.
endif
return quaternion.create(v.x/a*sin,v.y/a*sin,v.z/a*sin,cos)
endmethod
endmodule
endlibrary
//TESH.scrollpos=148
//TESH.alwaysfold=0
library quaternions
struct quaternion
// q = ( x*i + y*j + z*k + w )
real x
real y
real z
real w
implement optional quaternionExtention_Vectors
implement optional quaternionExtention_Matrices
method toString takes nothing returns string
return "( "+R2S(.x)+" | "+R2S(.y)+" | "+R2S(.z)+" | "+R2S(.w)+" )"
endmethod
method conjugate takes nothing returns quaternion
set .x = -.x
set .y = -.y
set .z = -.z
return this
endmethod
method scale takes real scalar returns quaternion
set .x = .x*scalar
set .y = .y*scalar
set .z = .z*scalar
set .w = .w*scalar
return this
endmethod
method normalise takes nothing returns quaternion
local real l = SquareRoot(.x*.x+.y*.y+.z*.z+.w*.w)
if l!=0. then
set .x = .x/l
set .y = .y/l
set .z = .z/l
set .w = .w/l
endif
return this
endmethod
method setQuat takes quaternion q2 returns quaternion
set .x = q2.x
set .y = q2.y
set .z = q2.z
set .w = q2.w
return this
endmethod
method add takes quaternion q2 returns quaternion
set .x = .x + q2.x
set .y = .y + q2.y
set .z = .z + q2.z
set .w = .w + q2.w
return this
endmethod
method mult takes quaternion q2 returns quaternion
local real x = .x * q2.w + .y * q2.z - .z * q2.y + .w * q2.x
local real y = -.x * q2.z + .y * q2.w + .z * q2.x + .w * q2.y
local real z = .x * q2.y - .y * q2.x + .z * q2.w + .w * q2.z
local real w = -.x * q2.x - .y * q2.y - .z * q2.z + .w * q2.w
set .x = x
set .y = y
set .z = z
set .w = w
return this
endmethod
method setXYZW takes real x, real y, real z, real w returns quaternion
set .x = x
set .y = y
set .z = z
set .w = w
return this
endmethod
method copy takes nothing returns quaternion
local quaternion q = quaternion.allocate()
set q.x = .x
set q.y = .y
set q.z = .z
set q.w = .w
return q
endmethod
static method createEuler takes real bank, real attitude, real heading returns quaternion
local real Sin0 = Sin(bank*.5)
local real Cos0 = Cos(bank*.5)
local real Sin1 = Sin(attitude*.5)
local real Cos1 = Cos(attitude*.5)
local real Sin2 = Sin(heading*.5)
local real Cos2 = Cos(heading*.5)
return quaternion.create(Sin0 * Cos1 * Cos2 - Cos0 * Sin1 * Sin2,Cos0 * Sin1 * Cos2 + Sin0 * Cos1 * Sin2,Cos0 * Cos1 * Sin2 - Sin0 * Sin1 * Cos2,Cos0 * Cos1 * Cos2 + Sin0 * Sin1 * Sin2)
endmethod
static method createMult takes quaternion q1, quaternion q2 returns quaternion
local quaternion q = quaternion.allocate()
set q.x = q1.x * q2.w + q1.y * q2.z - q1.z * q2.y + q1.w * q2.x
set q.y = -q1.x * q2.z + q1.y * q2.w + q1.z * q2.x + q1.w * q2.y
set q.z = q1.x * q2.y - q1.y * q2.x + q1.z * q2.w + q1.w * q2.z
set q.w = -q1.x * q2.x - q1.y * q2.y - q1.z * q2.z + q1.w * q2.w
return q
endmethod
static method create takes real x, real y, real z, real w returns quaternion
local quaternion q = quaternion.allocate()
set q.x = x
set q.y = y
set q.z = z
set q.w = w
return q
endmethod
endstruct
module vectorExtention_Quaternions
method rotateByQuaternion takes quaternion q returns vector
// r = q*v
local real x = q.y * .z - q.z * .y + q.w * .x
local real y = -q.x * .z + q.z * .x + q.w * .y
local real z = q.x * .y - q.y * .x + q.w * .z
local real w = -q.x * .x - q.y * .y - q.z * .z
// v = r*q'
set .x = x * q.w - y * q.z + z * q.y - w * q.x
set .y = x * q.z + y * q.w - z * q.x - w * q.y
set .z = -x * q.y + y * q.x + z * q.w - w * q.z
return this
endmethod
method rotateByQuaternionInv takes quaternion q returns vector
// r = q'*v
local real x = -q.y * .z + q.z * .y + q.w * .x
local real y = q.x * .z - q.z * .x + q.w * .y
local real z = -q.x * .y + q.y * .x + q.w * .z
local real w = q.x * .x + q.y * .y + q.z * .z
// v = r*q
set .x = x * q.w + y * q.z - z * q.y + w * q.x
set .y = -x * q.z + y * q.w + z * q.x + w * q.y
set .z = x * q.y - y * q.x + z * q.w + w * q.z
return this
endmethod
method addRotatedByQuaternion takes vector v, quaternion q returns vector
// r = q*v
local real x = q.y * v.z - q.z * v.y + q.w * v.x
local real y = -q.x * v.z + q.z * v.x + q.w * v.y
local real z = q.x * v.y - q.y * v.x + q.w * v.z
local real w = -q.x * v.x - q.y * v.y - q.z * v.z
// v = r*q'
set .x = .x + x * q.w - y * q.z + z * q.y - w * q.x
set .y = .y + x * q.z + y * q.w - z * q.x - w * q.y
set .z = .z - x * q.y + y * q.x + z * q.w - w * q.z
return this
endmethod
endmodule
module matrixExtention_Quaternions
static method createRotationByQuaternion takes quaternion q returns matrix
return matrix.create(1 - 2*q.y*q.y - 2*q.z*q.z,2*q.x*q.y - 2*q.z*q.w,2*q.x*q.z + 2*q.y*q.w,2*q.x*q.y + 2*q.z*q.w,1 - 2*q.x*q.x - 2*q.z*q.z,2*q.y*q.z - 2*q.x*q.w,2*q.x*q.z - 2*q.y*q.w,2*q.y*q.z + 2*q.x*q.w,1 - 2*q.x*q.x - 2*q.y*q.y)
endmethod
method rotateByQuaternion takes quaternion q returns nothing
local matrix m2 = matrix.createRotationByQuaternion(q)
call .multSwapOrder(m2)
call m2.invert()
call .mult(m2)
call m2.destroy()
endmethod
endmodule
endlibrary
//TESH.scrollpos=72
//TESH.alwaysfold=0
library matrices
struct matrix
// / r00 r01 r02 \
// M = | r10 r11 r12 |
// \ r20 r21 r22 /
real r00
real r01
real r02
real r10
real r11
real r12
real r20
real r21
real r22
implement optional matrixExtention_Quaternions
method toString takes nothing returns string
return "( "+R2S(.r00)+" | "+R2S(.r01)+" | "+R2S(.r02)+" )\n( "+R2S(.r10)+" | "+R2S(.r11)+" | "+R2S(.r12)+" )\n( "+R2S(.r20)+" | "+R2S(.r21)+" | "+R2S(.r22)+" )"
endmethod
static method create takes real r00, real r01, real r02, real r10, real r11, real r12, real r20, real r21, real r22 returns matrix
local matrix m2 = matrix.allocate()
set m2.r00 = r00
set m2.r01 = r01
set m2.r02 = r02
set m2.r10 = r10
set m2.r11 = r11
set m2.r12 = r12
set m2.r20 = r20
set m2.r21 = r21
set m2.r22 = r22
return m2
endmethod
method copy takes nothing returns matrix
local matrix m2 = matrix.allocate()
set m2.r00 = .r00
set m2.r01 = .r01
set m2.r02 = .r02
set m2.r10 = .r10
set m2.r11 = .r11
set m2.r12 = .r12
set m2.r20 = .r20
set m2.r21 = .r21
set m2.r22 = .r22
return m2
endmethod
method determinant takes nothing returns real
return .r00*.r11*.r22 + .r01*.r12*.r20 + .r02*.r10*.r21 - .r00*.r12*.r21 - .r01*.r10*.r22 - .r02*.r11*.r20
endmethod
method invert takes nothing returns nothing
local real invdet = 1./(.r00*.01*.r11*.01*.r22 + .r01*.01*.r12*.01*.r20 + .r02*.01*.r10*.01*.r21 - .r00*.01*.r12*.01*.r21 - .r01*.01*.r10*.01*.r22 - .r02*.01*.r11*.01*.r20)
local real r00 = (.r11*.01*.r22 - .r12*.01*.r21)*.01*invdet
local real r01 = (.r02*.01*.r21 - .r01*.01*.r22)*.01*invdet
local real r02 = (.r01*.01*.r12 - .r02*.01*.r11)*.01*invdet
local real r10 = (.r12*.01*.r20 - .r10*.01*.r22)*.01*invdet
local real r11 = (.r00*.01*.r22 - .r02*.01*.r20)*.01*invdet
local real r12 = (.r02*.01*.r10 - .r00*.01*.r12)*.01*invdet
local real r20 = (.r10*.01*.r21 - .r11*.01*.r20)*.01*invdet
local real r21 = (.r01*.01*.r20 - .r00*.01*.r21)*.01*invdet
local real r22 = (.r00*.01*.r11 - .r01*.01*.r10)*.01*invdet
set .r00 = r00
set .r01 = r01
set .r02 = r02
set .r10 = r10
set .r11 = r11
set .r12 = r12
set .r20 = r20
set .r21 = r21
set .r22 = r22
endmethod
method copyInverted takes nothing returns matrix
local matrix m2 = matrix.allocate()
local real invdet = 1./(.r00*.01*.r11*.01*.r22 + .r01*.01*.r12*.01*.r20 + .r02*.01*.r10*.01*.r21 - .r00*.01*.r12*.01*.r21 - .r01*.01*.r10*.01*.r22 - .r02*.01*.r11*.01*.r20)
set m2.r00 = (.r11*.01*.r22 - .r12*.01*.r21)*.01*invdet
set m2.r01 = (.r02*.01*.r21 - .r01*.01*.r22)*.01*invdet
set m2.r02 = (.r01*.01*.r12 - .r02*.01*.r11)*.01*invdet
set m2.r10 = (.r12*.01*.r20 - .r10*.01*.r22)*.01*invdet
set m2.r11 = (.r00*.01*.r22 - .r02*.01*.r20)*.01*invdet
set m2.r12 = (.r02*.01*.r10 - .r00*.01*.r12)*.01*invdet
set m2.r20 = (.r10*.01*.r21 - .r11*.01*.r20)*.01*invdet
set m2.r21 = (.r01*.01*.r20 - .r00*.01*.r21)*.01*invdet
set m2.r22 = (.r00*.01*.r11 - .r01*.01*.r10)*.01*invdet
return m2
endmethod
method copyInvertedOld takes nothing returns matrix
local matrix m2 = matrix.allocate()
local real invdet = 1./.determinant()
set m2.r00 = (.r11*.r22 - .r12*.r21)*invdet
set m2.r01 = (.r02*.r21 - .r01*.r22)*invdet
set m2.r02 = (.r01*.r12 - .r02*.r11)*invdet
set m2.r10 = (.r12*.r20 - .r10*.r22)*invdet
set m2.r11 = (.r00*.r22 - .r02*.r20)*invdet
set m2.r12 = (.r02*.r10 - .r00*.r12)*invdet
set m2.r20 = (.r10*.r21 - .r11*.r20)*invdet
set m2.r21 = (.r01*.r20 - .r00*.r21)*invdet
set m2.r22 = (.r00*.r11 - .r01*.r10)*invdet
return m2
endmethod
method mult takes matrix m2 returns nothing
local real r00 = .r00*m2.r00 + .r01*m2.r10 + .r02*m2.r20
local real r01 = .r00*m2.r01 + .r01*m2.r11 + .r02*m2.r21
local real r02 = .r00*m2.r02 + .r01*m2.r12 + .r02*m2.r22
local real r10 = .r10*m2.r00 + .r11*m2.r10 + .r12*m2.r20
local real r11 = .r10*m2.r01 + .r11*m2.r11 + .r12*m2.r21
local real r12 = .r10*m2.r02 + .r11*m2.r12 + .r12*m2.r22
local real r20 = .r20*m2.r00 + .r21*m2.r10 + .r22*m2.r20
local real r21 = .r20*m2.r01 + .r21*m2.r11 + .r22*m2.r21
local real r22 = .r20*m2.r02 + .r21*m2.r12 + .r22*m2.r22
set .r00 = r00
set .r01 = r01
set .r02 = r02
set .r10 = r10
set .r11 = r11
set .r12 = r12
set .r20 = r20
set .r21 = r21
set .r22 = r22
endmethod
method multSwapOrder takes matrix m2 returns nothing
local real r00 = m2.r00*.r00 + m2.r01*.r10 + m2.r02*.r20
local real r01 = m2.r00*.r01 + m2.r01*.r11 + m2.r02*.r21
local real r02 = m2.r00*.r02 + m2.r01*.r12 + m2.r02*.r22
local real r10 = m2.r10*.r00 + m2.r11*.r10 + m2.r12*.r20
local real r11 = m2.r10*.r01 + m2.r11*.r11 + m2.r12*.r21
local real r12 = m2.r10*.r02 + m2.r11*.r12 + m2.r12*.r22
local real r20 = m2.r20*.r00 + m2.r21*.r10 + m2.r22*.r20
local real r21 = m2.r20*.r01 + m2.r21*.r11 + m2.r22*.r21
local real r22 = m2.r20*.r02 + m2.r21*.r12 + m2.r22*.r22
set .r00 = r00
set .r01 = r01
set .r02 = r02
set .r10 = r10
set .r11 = r11
set .r12 = r12
set .r20 = r20
set .r21 = r21
set .r22 = r22
endmethod
static method createProduct takes matrix m1, matrix m2 returns matrix
local matrix m = matrix.allocate()
set m.r00 = m1.r00*m2.r00 + m1.r01*m2.r10 + m1.r02*m2.r20
set m.r01 = m1.r00*m2.r01 + m1.r01*m2.r11 + m1.r02*m2.r21
set m.r02 = m1.r00*m2.r02 + m1.r01*m2.r12 + m1.r02*m2.r22
set m.r10 = m1.r10*m2.r00 + m1.r11*m2.r10 + m1.r12*m2.r20
set m.r11 = m1.r10*m2.r01 + m1.r11*m2.r11 + m1.r12*m2.r21
set m.r12 = m1.r10*m2.r02 + m1.r11*m2.r12 + m1.r12*m2.r22
set m.r20 = m1.r20*m2.r00 + m1.r21*m2.r10 + m1.r22*m2.r20
set m.r21 = m1.r20*m2.r01 + m1.r21*m2.r11 + m1.r22*m2.r21
set m.r22 = m1.r20*m2.r02 + m1.r21*m2.r12 + m1.r22*m2.r22
return m
endmethod
method rotateByMatrix takes matrix mRot returns nothing
local matrix m2 = mRot.copy()
call .multSwapOrder(m2)
call m2.invert()
call .mult(m2)
call m2.destroy()
endmethod
endstruct
module quaternionExtention_Matrices
static method createRotationByMatrix takes matrix m returns quaternion
local quaternion q = quaternion.allocate()
local real trace = m.r00+m.r11+m.r22 + 1.
local real s
if trace > 0. then
set s = .5 / SquareRoot(trace)
set q.w = .25 / s
set q.x = ( m.r21 - m.r12 ) * s
set q.y = ( m.r02 - m.r20 ) * s
set q.z = ( m.r10 - m.r01 ) * s
elseif m.r00 > m.r11 and m.r00 > m.r22 then
set s = .5 / SquareRoot( 1. + m.r00 - m.r11 - m.r22)
set q.w = ( m.r21 - m.r12 ) * s
set q.x = .25 / s
set q.y = ( m.r01 + m.r10 ) * s
set q.z = ( m.r02 + m.r20 ) * s
elseif m.r11 > m.r22 then
set s = .5 / SquareRoot( 1. + m.r11 - m.r00 - m.r22)
set q.w = ( m.r02 - m.r20 ) * s
set q.x = ( m.r01 + m.r10 ) * s
set q.y = .25 / s
set q.z = ( m.r12 + m.r21 ) * s
else
set s = .5 / SquareRoot( 1. + m.r22 - m.r00 - m.r11 )
set q.w = ( m.r10 - m.r01 ) * s
set q.x = ( m.r02 + m.r20 ) * s
set q.y = ( m.r12 + m.r21 ) * s
set q.z = .25 / s
endif
return q
endmethod
endmodule
module vectorExtention_Matrices
method transformByMatrix takes matrix m returns vector
local real x = .x*m.r00 + .y*m.r01 + .z*m.r02
local real y = .x*m.r10 + .y*m.r11 + .z*m.r12
local real z = .x*m.r20 + .y*m.r21 + .z*m.r22
set .x = x
set .y = y
set .z = z
return this
endmethod
method setTransformedByMatrix takes vector v, matrix m returns vector
local real x = v.x*m.r00 + v.y*m.r01 + v.z*m.r02
local real y = v.x*m.r10 + v.y*m.r11 + v.z*m.r12
local real z = v.x*m.r20 + v.y*m.r21 + v.z*m.r22
set .x = x
set .y = y
set .z = z
return this
endmethod
method addTransformedByMatrix takes vector v, matrix m returns vector
local real x = v.x*m.r00 + v.y*m.r01 + v.z*m.r02
local real y = v.x*m.r10 + v.y*m.r11 + v.z*m.r12
local real z = v.x*m.r20 + v.y*m.r21 + v.z*m.r22
set .x = .x+x
set .y = .y+y
set .z = .z+z
return this
endmethod
method copyTransformedByMatrix takes vector v, matrix m returns vector
return vector.create(v.x*m.r00 + v.y*m.r01 + v.z*m.r02,v.x*m.r10 + v.y*m.r11 + v.z*m.r12,v.x*m.r20 + v.y*m.r21 + v.z*m.r22)
endmethod
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library maths
function Round takes real r returns integer
if r>0. then
return R2I(r+.5)
endif
return R2I(r-.499999999)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library handleRecyclers
//function H2I takes handle h returns integer
// return GetHandleId(h)
// return 0
//endfunction
globals
integer gs_N = 0
group array gs_g
endglobals
function NewGroup takes nothing returns group
if gs_N==0 then
return CreateGroup()
endif
set gs_N=gs_N-1
return gs_g[gs_N]
endfunction
function ReleaseGroup takes group g returns nothing
if gs_N>8191 then
call DestroyGroup(g)
else
call GroupClear(g)
set gs_g[gs_N]=g
set gs_N=gs_N+1
endif
endfunction
globals
integer tts_N = 0
texttag array tts_tt
endglobals
function NewTextTag takes nothing returns texttag
if tts_N==0 then
return CreateTextTag()
endif
set tts_N=tts_N-1
return tts_tt[tts_N]
endfunction
function ReleaseTextTag takes texttag tt returns nothing
if tts_N>8191 then
call DestroyTextTag(tt)
else
call SetTextTagVisibility(tt,false)
set tts_tt[tts_N]=tt
set tts_N=tts_N+1
endif
endfunction
//globals
// timer array t_t
// integer array t_a
// integer t_N
// integer t_b
//endglobals
//public function initTimers takes integer Count returns nothing
// local timer array tr
// set t_t[Count] = null
// set t_t[0] = CreateTimer()
// set tr[0] = t_t[0]
// set t_b = H2I(t_t[0])
// set t_N = 1
// loop
// exitwhen t_N >= Count
// set t_t[t_N] = CreateTimer()
// set tr[t_N] = t_t[t_N]
// set t_N = t_N + 1
// endloop
//endfunction
//function GetTimerId takes timer t returns integer
// return H2I(t)-t_b
//endfunction
//function NewTimer takes nothing returns timer
// set t_N = t_N - 1
// return t_t[t_N]
//endfunction
//function GetTimerStruct takes timer t returns integer
// return t_a[H2I(t)-t_b]
//endfunction
//function SetTimerStruct takes timer t, integer i returns nothing
// set t_a[H2I(t)-t_b]=i
//endfunction
//function ReleaseTimer takes timer t returns nothing
// call PauseTimer(t)
// set t_t[t_N] = t
// set t_N = t_N + 1
//endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library dummyRecyclers initializer init uses terrain
globals
constant real RECYCLE_TIME = 10.
group array dummyRecyclingPools
endglobals
function NewDummy takes real x, real y, real z returns unit
local unit u = FirstOfGroup(dummyRecyclingPools[0])
if u==null then
set u = CreateUnit(Player(0),'h000',x,y,0)
call UnitAddAbility(u,'Amrf')
call SetUnitPathing(u,false)
else
call GroupRemoveUnit(dummyRecyclingPools[0],u)
endif
call SetUnitFlyHeight(u,z-GetTerrainZ(x,y),0)
call SetUnitX(u,x)
call SetUnitY(u,y)
return u
endfunction
function ReleaseDummy takes unit u, real time returns nothing
local integer i = R2I(time+1)
if i>10 then
set i = 10
endif
call GroupAddUnit(dummyRecyclingPools[i],u)
endfunction
private function moveUp takes nothing returns nothing
local unit U
loop
set U = FirstOfGroup(dummyRecyclingPools[1])
exitwhen U==null
call GroupAddUnit(dummyRecyclingPools[0],U)
call GroupRemoveUnit(dummyRecyclingPools[1],U)
endloop
set dummyRecyclingPools[11] = dummyRecyclingPools[1]
set dummyRecyclingPools[1] = dummyRecyclingPools[2]
set dummyRecyclingPools[2] = dummyRecyclingPools[3]
set dummyRecyclingPools[3] = dummyRecyclingPools[4]
set dummyRecyclingPools[4] = dummyRecyclingPools[5]
set dummyRecyclingPools[5] = dummyRecyclingPools[6]
set dummyRecyclingPools[6] = dummyRecyclingPools[7]
set dummyRecyclingPools[7] = dummyRecyclingPools[8]
set dummyRecyclingPools[8] = dummyRecyclingPools[9]
set dummyRecyclingPools[9] = dummyRecyclingPools[10]
set dummyRecyclingPools[10] = dummyRecyclingPools[11]
endfunction
public function init takes nothing returns nothing
local integer i = 0
local timer t = CreateTimer()
loop
exitwhen i > 11
set dummyRecyclingPools[i] = CreateGroup()
set i = i + 1
endloop
call TimerStart(t,RECYCLE_TIME*.1,true,function moveUp)
endfunction
endlibrary
//TESH.scrollpos=15
//TESH.alwaysfold=0
library lists
struct listnode
listnode next
listnode previous
integer content
static method create takes integer content returns listnode
local listnode ln = listnode.allocate()
set ln.next = 0
set ln.previous = 0
set ln.content = content
return ln
endmethod
endstruct
struct list
listnode first = 0
listnode pointer = 0
listnode last = 0
method toNext takes nothing returns nothing
set .pointer = .pointer.next
endmethod
method toPrevious takes nothing returns nothing
set .pointer = .pointer.previous
endmethod
method toFirst takes nothing returns nothing
set .pointer = .first
endmethod
method toLast takes nothing returns nothing
set .pointer = .last
endmethod
method isFirst takes nothing returns boolean
return (.pointer == .first)
endmethod
method isLast takes nothing returns boolean
return (.pointer == .last)
endmethod
method getContent takes nothing returns integer
return .pointer.content
endmethod
method setContent takes integer i returns nothing
set .pointer.content = i
endmethod
method insertBehind takes integer content returns listnode
local listnode ln = listnode.create(content)
if .pointer==0 then
if .last!=0 then
set ln.previous = .last
set .last.next = ln
endif
set .last = ln
else
set ln.next = .pointer.next
if ln.next==0 then
set .last = ln
else
set ln.next.previous = ln
endif
set ln.previous = .pointer
set .pointer.next = ln
endif
if .first==0 then
set .first = ln
endif
return ln
endmethod
method insertBefore takes integer content returns listnode
local listnode ln = listnode.create(content)
if .pointer==0 then
if .first!=0 then
set ln.next = .first
set .first.previous = ln
endif
set .first = ln
else
set ln.previous = .pointer.previous
if ln.previous==0 then
set .first = ln
else
set ln.previous.next = ln
endif
set ln.next = .pointer
set .pointer.previous = ln
endif
if .last==0 then
set .last = ln
endif
return ln
endmethod
method pop takes nothing returns nothing
local listnode new = .pointer.next
if .pointer.next!=0 then
set .pointer.next.previous = .pointer.previous
endif
if .pointer.previous!=0 then
set .pointer.previous.next = .pointer.next
endif
if .pointer==.last then
set .last = .pointer.previous
endif
if .pointer==.first then
set .first = .pointer.next
endif
call .pointer.destroy()
set .pointer = new
endmethod
method search takes integer content returns boolean
local listnode p = .first
loop
exitwhen p==0
if p.content==content then
set .pointer=p
return true
endif
set p = p.next
endloop
return false
endmethod
method searchAndPop takes integer content returns boolean
local listnode p = .pointer
if .search(content) then
call .pop()
set .pointer = p
return true
endif
return false
endmethod
method outOfList takes nothing returns boolean
return .pointer==0
endmethod
method isEmpty takes nothing returns boolean
return .first==0
endmethod
method clear takes nothing returns nothing
local listnode cur
loop
exitwhen .first==0
set cur = .first
set .first = .first.next
call cur.destroy()
endloop
set .last = 0
set .pointer = 0
endmethod
method onDestroy takes nothing returns nothing
call .clear()
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library arrowkeys initializer arrowkeysInit
globals
boolean array arrowKeyPressed
endglobals
function arrow_LEFT_DOWN takes nothing returns nothing
set arrowKeyPressed[GetPlayerId(GetTriggerPlayer())*4] = true
endfunction
function arrow_LEFT_UP takes nothing returns nothing
set arrowKeyPressed[GetPlayerId(GetTriggerPlayer())*4] = false
endfunction
function arrow_RIGHT_DOWN takes nothing returns nothing
set arrowKeyPressed[GetPlayerId(GetTriggerPlayer())*4+1] = true
endfunction
function arrow_RIGHT_UP takes nothing returns nothing
set arrowKeyPressed[GetPlayerId(GetTriggerPlayer())*4+1] = false
endfunction
function arrow_DOWN_DOWN takes nothing returns nothing
set arrowKeyPressed[GetPlayerId(GetTriggerPlayer())*4+2] = true
endfunction
function arrow_DOWN_UP takes nothing returns nothing
set arrowKeyPressed[GetPlayerId(GetTriggerPlayer())*4+2] = false
endfunction
function arrow_UP_DOWN takes nothing returns nothing
set arrowKeyPressed[GetPlayerId(GetTriggerPlayer())*4+3] = true
endfunction
function arrow_UP_UP takes nothing returns nothing
set arrowKeyPressed[GetPlayerId(GetTriggerPlayer())*4+3] = false
endfunction
function createTrig takes code actionFunc, playerevent eventId returns nothing
local trigger t = CreateTrigger()
local integer PlayerId = 0
call TriggerAddAction(t, actionFunc)
loop
exitwhen PlayerId > 9
call TriggerRegisterPlayerEvent(t, Player(PlayerId), eventId)
set PlayerId = PlayerId + 1
endloop
set t = null
endfunction
function arrowLeftPressed takes integer pid returns boolean
return arrowKeyPressed[pid*4]
endfunction
function arrowRightPressed takes integer pid returns boolean
return arrowKeyPressed[pid*4+1]
endfunction
function arrowDownPressed takes integer pid returns boolean
return arrowKeyPressed[pid*4+2]
endfunction
function arrowUpPressed takes integer pid returns boolean
return arrowKeyPressed[pid*4+3]
endfunction
function arrowkeysInit takes nothing returns nothing
call createTrig(function arrow_LEFT_DOWN, EVENT_PLAYER_ARROW_LEFT_DOWN)
call createTrig(function arrow_LEFT_UP, EVENT_PLAYER_ARROW_LEFT_UP)
call createTrig(function arrow_RIGHT_DOWN, EVENT_PLAYER_ARROW_RIGHT_DOWN)
call createTrig(function arrow_RIGHT_UP, EVENT_PLAYER_ARROW_RIGHT_UP)
call createTrig(function arrow_DOWN_DOWN, EVENT_PLAYER_ARROW_DOWN_DOWN)
call createTrig(function arrow_DOWN_UP, EVENT_PLAYER_ARROW_DOWN_UP)
call createTrig(function arrow_UP_DOWN, EVENT_PLAYER_ARROW_UP_DOWN)
call createTrig(function arrow_UP_UP, EVENT_PLAYER_ARROW_UP_UP)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library cameramap initializer cameramapInit
globals
location cameramapLoc
real array camOffset[90][90]
real mapMinX
real mapMinY
real mapMaxX
real mapMaxY
endglobals
function GetGridCamOffset takes integer ix, integer iy, integer offx, integer offy returns real
local real r
local integer ixl = ix-1
local integer ixr = ix+1
local integer iyd = iy-1
local integer iyu = iy+1
if ixl<0 then
set ixl = 0
endif
if iyd<0 then
set iyd = 0
endif
if ixr>256 then
set ixr=256
endif
if iyu>256 then
set iyu=256
endif
if offx>0 then
if offy>0 then
set r = .089696*camOffset[ixl][iyu]+ .139657*camOffset[ix][iyu]+ .097349*camOffset[ixr][iyu]
set r = r+.130989*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .139657*camOffset[ixr][iy]
set r = r+.082587*camOffset[ixl][iyd]+ .130989*camOffset[ix][iyd]+ .089696*camOffset[ixr][iyd]
elseif offy<0 then
set r = .082587*camOffset[ixl][iyu]+ .130989*camOffset[ix][iyu]+ .089696*camOffset[ixr][iyu]
set r = r+.130989*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .139657*camOffset[ixr][iy]
set r = r+.089696*camOffset[ixl][iyd]+ .139657*camOffset[ix][iyd]+ .097349*camOffset[ixr][iyd]
else
set r = .084604*camOffset[ixl][iyu]+ .134226*camOffset[ix][iyu]+ .091913*camOffset[ixr][iyu]
set r = r+.134017*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .142877*camOffset[ixr][iy]
set r = r+.084604*camOffset[ixl][iyd]+ .134226*camOffset[ix][iyd]+ .091913*camOffset[ixr][iyd]
endif
elseif offx<0 then
if offy>0 then
set r = .097349*camOffset[ixl][iyu]+ .139657*camOffset[ix][iyu]+ .089696*camOffset[ixr][iyu]
set r = r+.139657*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .130989*camOffset[ixr][iy]
set r = r+.089696*camOffset[ixl][iyd]+ .130989*camOffset[ix][iyd]+ .082587*camOffset[ixr][iyd]
elseif offy<0 then
set r = .089696*camOffset[ixl][iyu]+ .130989*camOffset[ix][iyu]+ .082587*camOffset[ixr][iyu]
set r = r+.139657*camOffset[ixl][iy] + .099380*camOffset[ix][iy] + .130989*camOffset[ixr][iy]
set r = r+.097349*camOffset[ixl][iyd]+ .139657*camOffset[ix][iyd]+ .089696*camOffset[ixr][iyd]
else
set r = .091913*camOffset[ixl][iyu]+ .134226*camOffset[ix][iyu]+ .084604*camOffset[ixr][iyu]
set r = r+.142877*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .134017*camOffset[ixr][iy]
set r = r+.091913*camOffset[ixl][iyd]+ .134226*camOffset[ix][iyd]+ .084604*camOffset[ixr][iyd]
endif
else
if offy>0 then
set r = .091913*camOffset[ixl][iyu]+ .142877*camOffset[ix][iyu]+ .091913*camOffset[ixr][iyu]
set r = r+.134226*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .134226*camOffset[ixr][iy]
set r = r+.084604*camOffset[ixl][iyd]+ .134017*camOffset[ix][iyd]+ .084604*camOffset[ixr][iyd]
elseif offy<0 then
set r = .084604*camOffset[ixl][iyu]+ .134017*camOffset[ix][iyu]+ .084604*camOffset[ixr][iyu]
set r = r+.134226*camOffset[ixl][iy] + .101594*camOffset[ix][iy] + .134226*camOffset[ixr][iy]
set r = r+.091913*camOffset[ixl][iyd]+ .142877*camOffset[ix][iyd]+ .091913*camOffset[ixr][iyd]
else
set r = .086125*camOffset[ixl][iyu]+ .136429*camOffset[ix][iyu]+ .086125*camOffset[ixr][iyu]
set r = r+.136429*camOffset[ixl][iy] + .109784*camOffset[ix][iy] + .136429*camOffset[ixr][iy]
set r = r+.086125*camOffset[ixl][iyd]+ .136429*camOffset[ix][iyd]+ .086125*camOffset[ixr][iyd]
endif
endif
return r
endfunction
function GetCamOffset takes real x, real y returns real
local integer iXLo = R2I((x-mapMinX)/512.+.5)
local integer iYLo = R2I((y-mapMinY)/512.+.5)
local integer iXHi = iXLo+1
local integer iYHi = iYLo+1
local integer iChkXLo
local integer iChkXLoOff
local integer iChkXHi
local integer iChkXHiOff
local integer iChkYLo
local integer iChkYLoOff
local integer iChkYHi
local integer iChkYHiOff
local real XLo
local real YLo
local real XHi
local real YHi
local real rX
local real rY
local real r
local real LoDX = (x-mapMinX)-(iXLo*512.-256.)
local real LoDY = (y-mapMinY)-(iYLo*512.-256.)
if LoDX<=12 then
set iChkXLo = iXLo
set iChkXLoOff = 0
set iChkXHi = iXLo
set iChkXHiOff = 1
elseif LoDX<500 then
set iChkXLo = iXLo
set iChkXLoOff = 1
set iChkXHi = iXHi
set iChkXHiOff =-1
else
set iChkXLo = iXHi
set iChkXLoOff =-1
set iChkXHi = iXHi
set iChkXHiOff = 0
endif
if LoDY<=12 then
set iChkYLo = iYLo
set iChkYLoOff = 0
set iChkYHi = iYLo
set iChkYHiOff = 1
elseif LoDY<500 then
set iChkYLo = iYLo
set iChkYLoOff = 1
set iChkYHi = iYHi
set iChkYHiOff =-1
else
set iChkYLo = iYHi
set iChkYLoOff =-1
set iChkYHi = iYHi
set iChkYHiOff = 0
endif
set XLo = iChkXLo*512.+iChkXLoOff*12.-256.
set XHi = iChkXHi*512.+iChkXHiOff*12.-256.
set YLo = iChkYLo*512.+iChkYLoOff*12.-256.
set YHi = iChkYHi*512.+iChkYHiOff*12.-256.
set rX = ((x-mapMinX)-XLo)/(XHi-XLo)
set rY = ((y-mapMinY)-YLo)/(YHi-YLo)
set r = GetGridCamOffset(iChkXHi,iChkYHi,iChkXHiOff,iChkYHiOff)*rX*rY
set r = r+GetGridCamOffset(iChkXLo,iChkYHi,iChkXLoOff,iChkYHiOff)*(1-rX)*rY
set r = r+GetGridCamOffset(iChkXHi,iChkYLo,iChkXHiOff,iChkYLoOff)*rX*(1-rY)
set r = r+GetGridCamOffset(iChkXLo,iChkYLo,iChkXLoOff,iChkYLoOff)*(1-rX)*(1-rY)
return r
endfunction
function cameramapInit_GridSub takes real x, real y returns real
local integer index
local integer iX = -6
local integer iY
local real z
local real r
local real i = 64 //9*4+12*2+4
call MoveLocation(cameramapLoc,x,y)
set z = GetLocationZ(cameramapLoc)
set r = 0.
call MoveLocation(cameramapLoc,x-128.,y)
set r = r+GetLocationZ(cameramapLoc)*4./i
call MoveLocation(cameramapLoc,x,y)
set r = r+GetLocationZ(cameramapLoc)*4./i
call MoveLocation(cameramapLoc,x+128.,y)
set r = r+GetLocationZ(cameramapLoc)*4./i
call MoveLocation(cameramapLoc,x-128.,y+128.)
set r = r+GetLocationZ(cameramapLoc)*4./i
call MoveLocation(cameramapLoc,x,y+128.)
set r = r+GetLocationZ(cameramapLoc)*4./i
call MoveLocation(cameramapLoc,x+128.,y+128.)
set r = r+GetLocationZ(cameramapLoc)*4./i
call MoveLocation(cameramapLoc,x-128.,y-128.)
set r = r+GetLocationZ(cameramapLoc)*4./i
call MoveLocation(cameramapLoc,x,y-128.)
set r = r+GetLocationZ(cameramapLoc)*4./i
call MoveLocation(cameramapLoc,x+128.,y-128.)
set r = r+GetLocationZ(cameramapLoc)*4./i
call MoveLocation(cameramapLoc,x-256.,y-128.)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x-256.,y)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x-256.,y+128.)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x+256.,y-128.)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x+256.,y)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x+256.,y+128.)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x-128.,y-256.)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x,y-256.)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x+128.,y-256.)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x-128.,y+256.)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x,y+256.)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x+128.,y+256.)
set r = r+GetLocationZ(cameramapLoc)*2./i
call MoveLocation(cameramapLoc,x+256.,y+256.)
set r = r+GetLocationZ(cameramapLoc)*1./i
call MoveLocation(cameramapLoc,x+256.,y-256.)
set r = r+GetLocationZ(cameramapLoc)*1./i
call MoveLocation(cameramapLoc,x-256.,y+256.)
set r = r+GetLocationZ(cameramapLoc)*1./i
call MoveLocation(cameramapLoc,x-256.,y-256.)
set r = r+GetLocationZ(cameramapLoc)*1./i
return r
endfunction
function cameramapInit_DoRow takes nothing returns nothing
local real x = mapMinX+256.
local real y = mapMinY+256.
local integer iX = bj_forLoopAIndex
local integer iY = 0
loop
exitwhen y+iY*512.>mapMaxY
set camOffset[(iX+1)][iY+1] = cameramapInit_GridSub(x+iX*512.,y+iY*512.)
set iY = iY + 1
endloop
endfunction
function cameramapInit takes nothing returns nothing
local real x
local real y
local integer iX = 0
local integer iY
local rect map = GetWorldBounds()
set mapMinX = GetRectMinX(map)
set mapMinY = GetRectMinY(map)
set mapMaxX = GetRectMaxX(map)
set mapMaxY = GetRectMaxY(map)
call RemoveRect(map)
set map = null
set x = mapMinX+256.
set y = mapMinY+256.
set cameramapLoc = Location(0,0)
loop
exitwhen x+iX*512.>mapMaxX
set bj_forLoopAIndex = iX
call ExecuteFunc("cameramapInit_DoRow")
set iX = iX + 1
endloop
call RemoveLocation(cameramapLoc)
set cameramapLoc = null
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library water3d initializer water3dInit
globals
constant real WATER_HEIGHT = -10.
endglobals
function water3dInit takes nothing returns nothing
local rect map = GetWorldBounds()
local real minX = GetRectMinX(map)
local real minY = GetRectMinY(map)
local real maxX = GetRectMaxX(map)
local real maxY = GetRectMaxY(map)
local real x
local real y
local integer iX = 0
local integer iY
call RemoveRect(map)
set map = null
set x = mapMinX+256.
set y = mapMinY+256.
loop
exitwhen x+iX*512.>mapMaxX
set iY = 0
loop
exitwhen y+iY*512.>mapMaxY
call CreateDestructableZ('B000',x+iX*512.,y+iY*512.,WATER_HEIGHT,0,1,0)
set iY = iY + 1
endloop
set iX = iX + 1
endloop
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library terrain uses maths, vectors
globals
location terrainTempLoc = Location(0,0)
endglobals
function GetTerrainZ takes real x, real y returns real
call MoveLocation(terrainTempLoc,x,y)
return GetLocationZ(terrainTempLoc)
endfunction
function GetTerrainNormal takes real x, real y returns vector
local real z
local real radius = 8.
local vector v = vector.create(0,0,0)
set z = GetTerrainZ(x-radius,y)
set v.x = z-GetTerrainZ(x+radius,y)
set z = GetTerrainZ(x,y-radius)
set v.y = z-GetTerrainZ(x,y+radius)
set v.z = radius*2
return v.normalise()
endfunction
function GetSurfaceZ takes real x, real y returns real
local real xLo = Round(x/128.-.5)*128.
local real yLo = Round(y/128.-.5)*128.
local real baseZ
if x-xLo+y-yLo>128. then
set baseZ = GetTerrainZ(xLo+128.,yLo+128.)
return baseZ+((xLo+128.-x)*(GetTerrainZ(xLo,yLo+128.)-baseZ)+(yLo+128.-y)*(GetTerrainZ(xLo+128.,yLo)-baseZ))/128.
endif
set baseZ = GetTerrainZ(xLo,yLo)
return baseZ+((x-xLo)*(GetTerrainZ(xLo+128.,yLo)-baseZ)+(y-yLo)*(GetTerrainZ(xLo,yLo+128.)-baseZ))/128.
endfunction
function GetSurfaceNormal takes real x, real y returns vector
local real xLo = Round(x/128.-.5)*128
local real yLo = Round(y/128.-.5)*128
local real baseZ
if x-xLo+y-yLo>128. then
set baseZ = GetTerrainZ(xLo+128.,yLo+128.)
return vector.create(GetTerrainZ(xLo,yLo+128.)-baseZ,GetTerrainZ(xLo+128.,yLo)-baseZ,128.).normalise()
endif
set baseZ = GetTerrainZ(xLo,yLo)
return vector.create(baseZ-GetTerrainZ(xLo+128.,yLo),baseZ-GetTerrainZ(xLo,yLo+128.),128.).normalise()
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library soundSim initializer init uses vectors
globals
soundwave array allSoundWaves
integer allSoundWaves_N = 0
soundsource array allSoundSources
integer allSoundSources_N = 0
constant real SOUND_PITCH_MIN = .1
constant real SOUND_PITCH_MAX = 10.
constant real SOUND_SPEED_OF_SOUND = 425.
constant real SOUND_TIME_STEP = .04
constant boolean SOUND_EXTREME_SIM = false
vector soundWind
endglobals
struct soundwave
vector emittedPos
vector emittedVel
real emittedPitch
real emittedVolume
real age
soundsource emittedBy
static method create takes soundsource sndSrc returns soundwave
local soundwave sndWav = soundwave.allocate()
set sndWav.emittedPos=sndSrc.pos.copy()
set sndWav.emittedVel=sndSrc.vel.copy()
set sndWav.emittedPitch=sndSrc.pitch
set sndWav.emittedVolume=sndSrc.volume
set sndWav.age=0.
set sndWav.emittedBy=sndSrc
return sndWav
endmethod
method onDestroy takes nothing returns nothing
call .emittedPos.destroy()
call .emittedVel.destroy()
endmethod
endstruct
struct soundoutput
sound snd
soundsource sndSrc
real lastPitch
real lastVolume
real unusedTime
real waveAge
static method create takes soundsource sndSrc returns soundoutput
local soundoutput sndOut = soundoutput.allocate()
set sndOut.lastPitch = 1.
set sndOut.lastVolume = 0.
set sndOut.waveAge = 0.
set sndOut.sndSrc = sndSrc
set sndOut.snd = null
return sndOut
endmethod
method checkSound takes nothing returns nothing
if .snd==null then
set .snd = CreateSound( .sndSrc.soundName, .sndSrc.loopingSound, true, false, 10, 10, "DefaultEAXON" )
call SetSoundChannel(.snd,9)
call SetSoundVolume(.snd,0)
call SetSoundPitch(.snd,1)
call SetSoundDistances(.snd,100000,100000)
call SetSoundDistanceCutoff(.snd,100000)
call SetSoundConeAngles(.snd, 0.0, 0.0, 127 )
call SetSoundConeOrientation(.snd, 0.0, 0.0, 0.0 )
call SetSoundPosition(.snd,0,0,0)
call StartSound(.snd)
endif
endmethod
method onDestroy takes nothing returns nothing
if .snd!=null then
call StopSound(.snd,true,false)
endif
endmethod
endstruct
struct soundsource
vector pos
vector vel
string soundName
real soundDuration
real pitch
real volume
soundoutput out1
soundoutput out2
boolean loopingSound
boolean wantDestroy
boolean wantDestroyVectors
boolean doDestroy
static method create takes string soundName, real pitch, real volume, real duration, vector pos, vector vel, boolean wantDestroyVectors returns soundsource
// Duration <= 0 means looping sound
local soundsource sndSrc = soundsource.allocate()
set sndSrc.soundName = soundName
set sndSrc.soundDuration = duration
set sndSrc.loopingSound = duration<=0
set sndSrc.out1 = soundoutput.create(sndSrc)
set sndSrc.out2 = soundoutput.create(sndSrc)
set sndSrc.pos = pos
set sndSrc.vel = vel
set sndSrc.wantDestroyVectors = wantDestroyVectors
set sndSrc.pitch = pitch
set sndSrc.volume = volume
set sndSrc.wantDestroy = false
set sndSrc.doDestroy = false
set allSoundSources_N = allSoundSources_N + 1
set allSoundSources[allSoundSources_N] = sndSrc
return sndSrc
endmethod
method onDestroy takes nothing returns nothing
call .out1.destroy()
call .out2.destroy()
if .wantDestroyVectors then
call .pos.destroy()
call .vel.destroy()
endif
endmethod
method destroyWhenDone takes nothing returns nothing
set .doDestroy = true
set .wantDestroy = true
endmethod
endstruct
function refreshSounds_Simple takes nothing returns nothing
local soundsource sndSrc
local soundoutput out
local vector d = vector.create(0,0,0)
local real speed
local real dist
local real pitch
local real vol
local integer i=1
loop
exitwhen i>allSoundSources_N
set sndSrc = allSoundSources[i]
set out = sndSrc.out1
if sndSrc.doDestroy then
set allSoundSources[i] = allSoundSources[allSoundSources_N]
set allSoundSources_N = allSoundSources_N - 1
call sndSrc.destroy()
else
call d.setDifference(sndSrc.pos,eyePos)
set dist = d.length()
if dist<0.1 then
set dist=0.1
endif
call d.scale(1./dist)
set speed =(d.x*(sndSrc.vel.x-soundWind.x)+d.y*(sndSrc.vel.y-soundWind.y)+d.z*(sndSrc.vel.z-soundWind.z))
set pitch = 1/RMaxBJ(1.+speed/SOUND_SPEED_OF_SOUND,.01)*(1+(d.x*(eyeVel.x-soundWind.x)+d.y*(eyeVel.y-soundWind.y)+d.z*(eyeVel.z-soundWind.z))/SOUND_SPEED_OF_SOUND)
set out.unusedTime = -SOUND_TIME_STEP/pitch
set pitch=pitch*sndSrc.pitch
if pitch<SOUND_PITCH_MIN then
set pitch=SOUND_PITCH_MIN
elseif pitch>SOUND_PITCH_MAX then
set pitch=SOUND_PITCH_MAX
endif
set vol = sndSrc.volume*64000/dist/(1-speed/SOUND_SPEED_OF_SOUND)
if vol>127 then
set vol=127
endif
call out.checkSound()
call SetSoundPosition(out.snd,sndSrc.pos.x,sndSrc.pos.y,sndSrc.pos.z)
call SetSoundVolume(out.snd,R2I(vol))
call SetSoundPitch(out.snd,pitch/out.lastPitch)
set out.lastVolume=vol
set out.lastPitch= pitch
if not (sndSrc.loopingSound or sndSrc.wantDestroy) then
set sndSrc.soundDuration = sndSrc.soundDuration - SOUND_TIME_STEP*pitch
if sndSrc.soundDuration<0 then
set sndSrc.wantDestroy = true
endif
endif
set i = i + 1
endif
endloop
call d.destroy()
endfunction
function refreshSounds_Extreme takes nothing returns nothing
local soundwave sndWav=0
local soundsource sndSrc
local vector d = vector.create(0,0,0)
local real dist
local real pitch
local real vol
local real diff1
local real diff2
local soundoutput out
local integer i = 1
local real r
local real pitchSign
local boolean wasNegative
loop
exitwhen i>allSoundWaves_N
set sndWav = allSoundWaves[i]
set sndWav.age = sndWav.age + SOUND_TIME_STEP
call d.setDifference(sndWav.emittedPos,eyePos)
set dist = d.lengthSq()
if dist<sndWav.age*sndWav.age*SOUND_SPEED_OF_SOUND*SOUND_SPEED_OF_SOUND then
set sndSrc = sndWav.emittedBy
// Select output
set out = sndSrc.out1
if sndSrc.loopingSound then
if sndSrc.out1.lastVolume==0. then
set diff1=.5
else
set diff1 = sndSrc.out1.waveAge-sndWav.age
if diff1<0 then
set diff1=-diff1
endif
endif
if sndSrc.out2.lastVolume==0. then
set diff2=.5
else
set diff2 = sndSrc.out2.waveAge-sndWav.age
if diff2<0 then
set diff2=-diff2
endif
endif
if diff1>diff2 then
set out = sndSrc.out2
endif
endif
set dist = SquareRoot(dist)
if dist<0.1 then
set dist=0.1
endif
call d.scale(1./dist)
set r = 1.+(d.x*(sndWav.emittedVel.x-soundWind.x)+d.y*(sndWav.emittedVel.y-soundWind.y)+d.z*(sndWav.emittedVel.z-soundWind.z))/SOUND_SPEED_OF_SOUND
set wasNegative = r<0
if wasNegative then
set r = -r
endif
if sndSrc.loopingSound or not wasNegative then
set pitch = 1/r*(1+(d.x*(eyeVel.x-soundWind.x)+d.y*(eyeVel.y-soundWind.y)+d.z*(eyeVel.z-soundWind.z))/SOUND_SPEED_OF_SOUND)
set out.unusedTime = -SOUND_TIME_STEP/pitch
set out.waveAge = sndWav.age
set pitch=pitch*sndWav.emittedPitch
if pitch<SOUND_PITCH_MIN then
set pitch=SOUND_PITCH_MIN
elseif pitch>SOUND_PITCH_MAX then
set pitch=SOUND_PITCH_MAX
endif
set vol = sndWav.emittedVolume*64000/dist
if vol>127 then
set vol=127
endif
call out.checkSound()
call SetSoundPosition(out.snd,sndWav.emittedPos.x,sndWav.emittedPos.y,sndWav.emittedPos.z)
call SetSoundVolume(out.snd,R2I(vol))
call SetSoundPitch(out.snd,pitch/out.lastPitch)
set out.lastVolume=vol
set out.lastPitch= pitch
endif
call sndWav.destroy()
set allSoundWaves[i] = allSoundWaves[allSoundWaves_N]
set allSoundWaves_N = allSoundWaves_N - 1
else
set sndWav.emittedBy.doDestroy = false
set i = i + 1
endif
endloop
set i=1
loop
exitwhen i>allSoundSources_N
set sndSrc = allSoundSources[i]
if sndSrc.doDestroy then
set allSoundSources[i] = allSoundSources[allSoundSources_N]
set allSoundSources_N = allSoundSources_N - 1
call sndSrc.destroy()
else
set sndSrc.out1.unusedTime = sndSrc.out1.unusedTime + SOUND_TIME_STEP
set sndSrc.out2.unusedTime = sndSrc.out2.unusedTime + SOUND_TIME_STEP
if sndSrc.out1.unusedTime>SOUND_TIME_STEP then
set sndSrc.out1.lastVolume=0
call SetSoundVolume(sndSrc.out1.snd,R2I(sndSrc.out1.lastVolume))
endif
if sndSrc.out2.unusedTime>SOUND_TIME_STEP then
set sndSrc.out2.lastVolume=0
call SetSoundVolume(sndSrc.out2.snd,R2I(sndSrc.out2.lastVolume))
endif
if sndSrc.wantDestroy then
set sndSrc.doDestroy = true
else
set allSoundWaves_N = allSoundWaves_N + 1
set allSoundWaves[allSoundWaves_N] = soundwave.create(sndSrc)
endif
if not (sndSrc.loopingSound or sndSrc.wantDestroy) then
set sndSrc.soundDuration = sndSrc.soundDuration - SOUND_TIME_STEP
if sndSrc.soundDuration<0 then
set sndSrc.wantDestroy = true
endif
endif
set i = i + 1
endif
endloop
call d.destroy()
endfunction
private function init takes nothing returns nothing
if SOUND_EXTREME_SIM then
call TimerStart(CreateTimer(),SOUND_TIME_STEP,true,function refreshSounds_Extreme)
else
call TimerStart(CreateTimer(),SOUND_TIME_STEP,true,function refreshSounds_Simple)
endif
endfunction
endlibrary
//TESH.scrollpos=16
//TESH.alwaysfold=0
//***************************************************************************
//*
//* Camera
//*
//***************************************************************************
library camera initializer CameraInit uses terrain, vectors
globals
vector eyeFollow
vector eyePos
vector eyeVel
endglobals
function CameraCockpit takes object o returns nothing
local vector nose = vector.create(1,0,0).rotateByQuaternion(o.orient)
local vector head = vector.create(0,0,1)
local vector normal
local vector headNoRoll
local real r
set normal = vector.createProduct(nose,head)
call head.rotateByQuaternion(o.orient)
set headNoRoll = vector.createProduct(nose,normal).normalise()
set r = scalarProduct(head,headNoRoll)
// Prevent rounding errors
if r<=-1 then
set r = bj_PI
elseif r>=1 then
set r = 0
else
set r = Acos(r)
endif
if scalarProduct(head,normal)<0 then
set r = -r
endif
set r = bj_PI-r
call normal.destroy()
set normal = o.c.cockpitCam.copy().rotateByQuaternion(o.orient)
call eyePos.setSum(o.pos,normal)
call eyeVel.setVec(o.vel)
call normal.addScaled(nose,100)
call SetCameraTargetController(o.u,normal.x,normal.y,false)
call SetCameraField( CAMERA_FIELD_FARZ, 5000, 0 )
call SetCameraField( CAMERA_FIELD_TARGET_DISTANCE, 100, 0 )
call SetCameraField( CAMERA_FIELD_ZOFFSET, o.pos.z+normal.z-GetCamOffset(o.pos.x,o.pos.y), 0 )
call SetCameraField( CAMERA_FIELD_ROTATION, Atan2(nose.y,nose.x)*bj_RADTODEG, 0 )
call SetCameraField( CAMERA_FIELD_ROLL,r*bj_RADTODEG,0)
call SetCameraField( CAMERA_FIELD_ANGLE_OF_ATTACK, Atan2(nose.z,SquareRoot(nose.x*nose.x+nose.y*nose.y))*bj_RADTODEG, 0 )
call SetCameraField( CAMERA_FIELD_FIELD_OF_VIEW, 70, 0 )
call headNoRoll.destroy()
call normal.destroy()
call head.destroy()
call nose.destroy()
endfunction
function CameraWatchObject takes object o, object o2, real dist returns nothing
local vector dVec
set dVec = vector.createDifference(o2.pos,o.pos).setLength(dist)
call eyeVel.setDifference(o.pos,dVec).subtract(eyePos)
call eyePos.add(eyeVel)
call eyeVel.scale(1./PHYS_TIME_STEP)
call SetCameraTargetController(o.u,0,0,false)
call SetCameraField(CAMERA_FIELD_ZOFFSET,o.pos.z+30-GetCamOffset(o.pos.x,o.pos.y),0)
call SetCameraField( CAMERA_FIELD_FARZ, 5000, 0 )
if dist<0 then
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, -dist, 0 )
else
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, dist, 0 )
endif
call SetCameraField( CAMERA_FIELD_ROTATION, Atan2(dVec.y,dVec.x)*bj_RADTODEG, 0 )
call SetCameraField( CAMERA_FIELD_ROLL,0,0)
call SetCameraField( CAMERA_FIELD_ANGLE_OF_ATTACK, Atan2(dVec.z,SquareRoot(dVec.x*dVec.x+dVec.y*dVec.y))*bj_RADTODEG, 0 )
call SetCameraField( CAMERA_FIELD_FIELD_OF_VIEW, 70, 0 )
call dVec.destroy()
endfunction
function CameraFollow takes object o, real dist returns nothing
local vector dVec = vector.createDifference(o.pos,eyeFollow)
local real lim = WATER_HEIGHT+120.
local real lim2
local real distSign = RSignBJ(dist)
local real r
local object o2 = 2
call dVec.setLength(distSign*dist)
call eyeFollow.setVec(o.pos)
call eyeFollow.subtractScaled(dVec,.5)
call dVec.scale(distSign)
set lim2 = GetSurfaceZ(o.pos.x-dVec.x,o.pos.y-dVec.y)+120.
if lim2>lim then
set lim=lim2
endif
if o.pos.z-dVec.z<lim then
set dVec.z = -lim+o.pos.z
set r = dVec.length()
if r>distSign*dist then
set dist = distSign*r
else
call dVec.scale(distSign*dist/r)
endif
endif
call eyeVel.setDifference(o.pos,dVec).subtract(eyePos)
call eyePos.add(eyeVel)
call eyeVel.scale(1./PHYS_TIME_STEP)
call SetCameraTargetController(o.u,0,0,false)
call SetCameraField(CAMERA_FIELD_ZOFFSET,o.pos.z-GetCamOffset(o.pos.x,o.pos.y),0)
call SetCameraField( CAMERA_FIELD_FARZ, 5000, 0 )
if dist<0 then
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, -dist, 0 )
else
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, dist, 0 )
endif
call SetCameraField( CAMERA_FIELD_ROTATION, Atan2(dVec.y,dVec.x)*bj_RADTODEG, 0 )
call SetCameraField( CAMERA_FIELD_ROLL,0,0)
call SetCameraField( CAMERA_FIELD_ANGLE_OF_ATTACK, Atan2(dVec.z,SquareRoot(dVec.x*dVec.x+dVec.y*dVec.y))*bj_RADTODEG, 0 )
call SetCameraField( CAMERA_FIELD_FIELD_OF_VIEW, 70, 0 )
call dVec.destroy()
endfunction
function CameraLookAt takes object o returns nothing
local vector dVec = vector.createDifference(o.pos,eyePos)
local real d = dVec.length()
call eyeVel.setXYZ(0,0,0)
if d<120 then
set d = 120.
endif
call SetCameraTargetController(o.u,0,0,false)
call SetCameraField(CAMERA_FIELD_ZOFFSET,o.pos.z-GetCamOffset(o.pos.x,o.pos.y),0)
call SetCameraField( CAMERA_FIELD_TARGET_DISTANCE, d, 0 )
call SetCameraField( CAMERA_FIELD_ROTATION, Atan2(dVec.y,dVec.x)*bj_RADTODEG, 0 )
call SetCameraField( CAMERA_FIELD_ROLL,0,0)
call SetCameraField( CAMERA_FIELD_FARZ, 5000, 0 )
call SetCameraField( CAMERA_FIELD_ANGLE_OF_ATTACK, Atan2(dVec.z,SquareRoot(dVec.x*dVec.x+dVec.y*dVec.y))*bj_RADTODEG, 0 )
call SetCameraField( CAMERA_FIELD_FIELD_OF_VIEW, 20, 0 )
call dVec.destroy()
endfunction
function CameraInit takes nothing returns nothing
set eyePos = vector.create(0,0,0)
set eyeVel = vector.create(0,0,0)
set eyeFollow = vector.create(0,0,0)
endfunction
endlibrary
//TESH.scrollpos=3
//TESH.alwaysfold=0
library physEnvironment uses terrain
globals
group cloudUnits
constant real CLOUD_MIN_Z = 1800
constant real CLOUD_MAX_Z = 2500
endglobals
function GetVolumeDensity takes real z returns real
if z>=WATER_HEIGHT then
return PHYS_AIR_DENSITY*(1.-z/13000)
endif
return PHYS_WATER_DENSITY
endfunction
function GetVolumeMassInSphere takes real z, real radius returns real
local real depth
if z-radius>=WATER_HEIGHT then
return 4/3*bj_PI*radius*radius*radius*PHYS_AIR_DENSITY*(1.-z/13000)
elseif z+radius<=WATER_HEIGHT then
return 4/3*bj_PI*radius*radius*radius*PHYS_WATER_DENSITY
endif
set depth = WATER_HEIGHT-(z-radius)
return depth*depth*bj_PI/3*(3*radius-depth)*PHYS_WATER_DENSITY+(1-depth)*(1-depth)*bj_PI/3*(3*radius-(1-depth))*(1.-(WATER_HEIGHT+z+radius)*.5/13000)
endfunction
function GetVolumeMassInBox takes real z, real area, real size returns real
if z-size>=WATER_HEIGHT then
return area*size*2*PHYS_AIR_DENSITY*(1.-z/13000)
elseif z+size<=WATER_HEIGHT then
return area*size*2*PHYS_WATER_DENSITY
endif
return (WATER_HEIGHT-(z-size))*area*PHYS_WATER_DENSITY + ((z+size)-WATER_HEIGHT)*area*PHYS_AIR_DENSITY*(1.-(WATER_HEIGHT+z+size)*.5/13000)
endfunction
function SetCloudCount takes integer i returns nothing
local integer j = 1
local unit cur
local real x
local real y
local real z
local real tz
local integer c
local location loc = Location(0,0)
loop
exitwhen j>i
set x = GetRandomReal(mapMinX,mapMaxX)
set y = GetRandomReal(mapMinY,mapMaxY)
set z = GetRandomReal(CLOUD_MIN_Z,CLOUD_MAX_Z)
call MoveLocation(loc,x,y)
set tz = GetLocationZ(loc)
if z>tz then
set cur = CreateUnit(Player(0),'h000',GetRandomReal(mapMinX,mapMaxX),GetRandomReal(mapMinY,mapMaxY),270.)
call AddSpecialEffectTarget("war3mapImported\\Cloud.mdx",cur,"origin")
call UnitAddAbility(cur,'Amrf')
call SetUnitAnimationByIndex(cur, 1)
call SetUnitFlyHeight(cur,z-tz,0)
call SetUnitPosition(cur,x,y)
call UnitRemoveAbility(cur,'Amrf')
call SetUnitScale(cur,2,2,2)
set c = 255//GetRandomInt(127,255)
call SetUnitVertexColor(cur,c,c,c,255)
set j = j + 1
endif
endloop
call RemoveLocation(loc)
set loc = null
endfunction
endlibrary
//TESH.scrollpos=141
//TESH.alwaysfold=0
library physClasses uses physCollisionShapes
globals
constant integer BODY = 0
constant integer LANDINGGEARS = 1
constant integer ELEVATOR = 2
endglobals
struct listpoint
vector pos
vector landingGearFrictDir
vector landingGearRetractedOffset
integer attachTo
real landingGearSteering
real displacement
real displacementRadius
listpoint next
endstruct
struct class
real mass
matrix inertia
matrix inertiaInv
string modelName
real modelScale
integer unitType
real radius
real hitpoints
shape collshape
vector cockpitCam
vector posMG
vector posMissiles
vector posFlares
vector velMG
vector velMissiles
vector velFlares
real MGMaxTurnDeg
string cloud1PosStr
string cloud2PosStr
string cloud3PosStr
vector elevatorModelPos
string elevatorModelStr
real elevatorBaseAngle
real elevatorMaxControlAngle
real speedFullRudderPitch
string landingGearsModelName
string landingGearsModelPosStr
string engineSoundName
real engineSoundPitch
real engineSoundVolume
trigger simulationTrig
listpoint firstP
static method create takes nothing returns class
local class c = class.allocate()
set c.firstP = 0
set c.modelScale = 1.
set c.simulationTrig=null
return c
endmethod
method operator simulationCode= takes code c returns nothing
if .simulationTrig!=null then
call TriggerClearConditions(.simulationTrig)
else
set .simulationTrig = CreateTrigger()
endif
call TriggerAddCondition(.simulationTrig,Condition(c))
endmethod
method setLandingGearsModel takes string modelName, string posStr returns nothing
set .landingGearsModelName = modelName
set .landingGearsModelPosStr = posStr
endmethod
method setEngineSound takes string soundName, real pitch, real volume returns nothing
set .engineSoundName = soundName
set .engineSoundPitch = pitch
set .engineSoundVolume = volume
endmethod
method setElevator takes string modelName, vector relPos, real baseAngle, real maxControlAngle returns nothing
set .elevatorModelStr=modelName
set .elevatorModelPos=relPos
set .elevatorBaseAngle=baseAngle
set .elevatorMaxControlAngle=maxControlAngle
endmethod
method addCollisionPoint takes integer attachTo, vector pos returns listpoint
local listpoint p = listpoint.create()
local listpoint loopp = .firstP
local real r
local vector d
set p.pos = pos
set p.landingGearFrictDir=0
set p.landingGearRetractedOffset=0
set p.landingGearSteering = 0
set p.displacement=0.
set p.displacementRadius=0.
set p.attachTo = attachTo
set p.next = 0
if .firstP==0 then
set .firstP = p
else
loop
exitwhen loopp.next==0
set loopp=loopp.next
endloop
set loopp.next = p
endif
set d = p.pos.copy()
if attachTo==ELEVATOR then
call d.add(.elevatorModelPos)
endif
set r = d.length()
if r>.radius then
set .radius = r
endif
call d.destroy()
return p
endmethod
method addLandingGear takes vector posOut, vector retractedOffset, vector frictDir, real steering returns listpoint
local listpoint p = .addCollisionPoint(LANDINGGEARS,posOut)
set p.landingGearFrictDir=frictDir
set p.landingGearRetractedOffset=retractedOffset
set p.landingGearSteering = steering
return p
endmethod
method addCollisionPointWithDisplacement takes vector pos, real displacement, real radius returns listpoint
local listpoint p = .addCollisionPoint(BODY,pos)
set p.displacement=displacement
set p.displacementRadius=radius
return p
endmethod
method scaleVisual takes real r returns nothing
local listpoint cur = .firstP
set .modelScale = .modelScale*r
set .radius = .radius*r
call .cockpitCam.scale(r)
call .collshape.scale(r)
call .posMG.scale(r)
call .posMissiles.scale(r)
call .posFlares.scale(r)
if .elevatorModelStr!="" then
call .elevatorModelPos.scale(r)
endif
loop
exitwhen cur==0
call cur.pos.scale(r)
if cur.landingGearRetractedOffset!=0 then
call cur.landingGearRetractedOffset.scale(r)
endif
set cur.displacementRadius=cur.displacementRadius*r
set cur = cur.next
endloop
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library physParticleClasses
struct pclass
real mass
real accel
real aim
string modelName
real scale
real lifespan
real friction
boolean explodeOnHit
boolean explodeInWater
static method create takes nothing returns pclass
local pclass p = pclass.allocate()
set p.mass = 1.
set p.modelName = ""
set p.scale = 1.
set p.accel = 0.
set p.aim = 0.
set p.lifespan = 3.
set p.friction = 0.
set p.explodeOnHit = false
set p.explodeInWater = false
return p
endmethod
method operator turnRateDeg= takes real r returns nothing
set .aim = Tan(r*bj_DEGTORAD)
endmethod
endstruct
endlibrary
//TESH.scrollpos=251
//TESH.alwaysfold=0
library physObjects uses physClasses, vectors, terrain
globals
constant integer NO_CONTROL = 0
endglobals
struct objectCtrl
vector rudders
vector ruddersVel
vector ruddersAim
real enginePowerAim
real enginePower
real zRotate
real landingGearVel
real landingGearPos
real brakes
boolean wantLandingGears
integer flareShots
integer weaponShots1
integer weaponShots2
integer weaponShots3
integer cam
endstruct
struct object
unit u
vector pos // world-coordinates
vector posTmp
vector vel // world-coordinates
vector velTmp
vector velOld
vector accel
vector accelOld
quaternion orient
quaternion orientTmp
vector angVel // world-coordinates
vector angVelTmp
vector angAccel
matrix inertiaWorld
matrix inertiaWorldInv
objectCtrl ctrl
real firstCollTime
real hp
effect e
effect cloud1
effect cloud2
effect cloud1e
effect cloud2e
effect cloud3e
effect fire
effect landingGears
soundsource engineSound
image shadow
boolean broken
real flareDistraction
integer followingMissiles
real nearestMissileDist
boolean missileSlotA
boolean mgSlotA
object targ
class c
unit elevu
effect eleve
method updateShadow takes nothing returns nothing
local real flyHeight = .pos.z-GetTerrainZ(.pos.x,.pos.y)
local real visibility = (500-flyHeight)/500.
local integer alpha = R2I(visibility*255.)
if alpha<0 then
set alpha = 0
elseif alpha>255 then
set alpha = 255
endif
call SetImageColor(.shadow,255,255,255,alpha)
call SetImagePosition(.shadow,.pos.x-.c.radius, .pos.y-.c.radius, 0)
endmethod
method addShadow takes nothing returns image
local real size = .c.radius*2
if size<1. then
return null
endif
set .shadow = CreateImage("ReplaceableTextures\\Shadows\\ShadowFlyer.blp", size, size, size, .pos.x-size*.5, .pos.y-size*.5, 0, 0, 0, 0, 2)
call SetImageColor(.shadow,255,255,255,255)
call SetImageRenderAlways( .shadow, true )
call ShowImage(.shadow, true)
return .shadow
endmethod
method onDeath takes nothing returns nothing
if .fire==null then
set .fire =AddSpecialEffectTarget("Environment\\LargeBuildingFire\\LargeBuildingFire2.mdl",.u,"origin")
endif
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,GetPlayerName(GetOwningPlayer(.u))+" was killed.")
call TriggerSleepAction(6)
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,5,GetPlayerName(GetOwningPlayer(.u))+" was respawned.")
if .fire!=null then
call DestroyEffect(.fire)
set .fire=null
endif
set .hp = .c.hitpoints
set .broken = false
if .c==DESTROYER then
set .pos.z = 0
call .vel.setLength(0)
else
set .pos.z = 1500.
call .vel.setLength(100)
endif
call .orient.setXYZW(0,0,0,1)
call .angVel.setXYZ(0,0,0)
endmethod
method damage takes real r returns nothing
local integer pid = GetPlayerId(GetOwningPlayer(.u))
set .hp = .hp-r
if .hp<=0. then
set .hp=0.
if not .broken then
set .broken=true
call .onDeath.execute()
endif
endif
if playerControlledObj[pid]==this then
call SetUnitState(playerController[pid],UNIT_STATE_LIFE,RMaxBJ(.hp,1))
endif
endmethod
method updateBodyPosition takes nothing returns nothing
local vector nose = vector.create(1,0,0).rotateByQuaternion(.orient)
local vector head = vector.create(0,0,1)
local vector normal
local vector headNoRoll
local real r
local real terrZ
set normal = vector.createProduct(nose,head)
call head.rotateByQuaternion(.orient)
set headNoRoll = vector.createProduct(nose,normal).normalise()
set r = scalarProduct(head,headNoRoll)
// Prevent rounding errors
if r<=-1 then
set r = bj_PI
elseif r>=1 then
set r = 0
else
set r = Acos(r)
endif
if scalarProduct(head,normal)<0 then
set r = -r
endif
set r = bj_PI-r
set terrZ = GetTerrainZ(.pos.x,.pos.y)
call SetUnitAnimationByIndex(.u, R2I(ModuloReal(r*bj_RADTODEG*0.7+.5,252)))
call SetUnitLookAt(.u,"bone_Head",.u,nose.x*100.,nose.y*100.,nose.z*100.)
call SetUnitFlyHeight(.u,.pos.z-terrZ,0)
call SetUnitPosition(.u,.pos.x,.pos.y)
call headNoRoll.destroy()
call normal.destroy()
call head.destroy()
call nose.destroy()
endmethod
method updateElevatorPosition takes nothing returns nothing
local vector elevnose = vector.create(1,0,0).rotateAroundYAxis(.c.elevatorBaseAngle-.c.elevatorMaxControlAngle*.ctrl.rudders.y).rotateByQuaternion(.orient)
local vector elevhead = vector.create(0,0,1).rotateAroundYAxis(.c.elevatorBaseAngle-.c.elevatorMaxControlAngle*.ctrl.rudders.y)
local vector elevnormal
local vector elevheadNoRoll
local vector elevPos = .c.elevatorModelPos.copy().rotateByQuaternion(.orient)
local vector zaxis = vector.create(0,0,1)
local real elevr
local real elevterrZ
set elevnormal = vector.createProduct(elevnose,zaxis)
call zaxis.destroy()
call elevhead.rotateByQuaternion(.orient)
set elevheadNoRoll = vector.createProduct(elevnose,elevnormal).normalise()
set elevr = scalarProduct(elevhead,elevheadNoRoll)
// Prevent rounding errors
if elevr<=-1 then
set elevr = bj_PI
elseif elevr>=1 then
set elevr = 0
else
set elevr = Acos(elevr)
endif
if scalarProduct(elevhead,elevnormal)<0 then
set elevr = -elevr
endif
set elevr = bj_PI-elevr
set elevterrZ = GetTerrainZ(.pos.x+elevPos.x,.pos.y+elevPos.y)
call SetUnitAnimationByIndex(.elevu, R2I(ModuloReal(elevr*bj_RADTODEG*0.7+.5,252)))
call SetUnitLookAt(.elevu,"bone_Head",.elevu,elevnose.x*100.,elevnose.y*100.,elevnose.z*100.)
call SetUnitFlyHeight(.elevu,.pos.z+elevPos.z-elevterrZ,0)
call SetUnitPosition(.elevu,.pos.x+elevPos.x,.pos.y+elevPos.y)
call elevheadNoRoll.destroy()
call elevnormal.destroy()
call elevPos.destroy()
call elevhead.destroy()
call elevnose.destroy()
endmethod
method updateCamera takes nothing returns nothing
if .ctrl.cam==0 then
call CameraFollow(this,.c.radius+100.)
elseif .ctrl.cam==1 then
call CameraFollow(this,-.c.radius-100.)
elseif .ctrl.cam==4 then
call CameraCockpit(this)
elseif .ctrl.cam==2 then
if .targ!=0 then
call CameraWatchObject(this,.targ,.c.radius+130.)
else
set .ctrl.cam=3
call CameraLookAt(this)
endif
elseif .ctrl.cam==3 then
call CameraLookAt(this)
endif
endmethod
method updateAnimation takes nothing returns nothing
call .updateBodyPosition()
if .elevu!=null then
call .updateElevatorPosition()
endif
if .shadow!=null then
call .updateShadow()
endif
if GetOwningPlayer(.u)==GetLocalPlayer() then
call .updateCamera()
endif
endmethod
method addForce takes vector relPos, vector f returns nothing
local vector angVelChange = vector.createProduct(relPos,f).transformByMatrix(.inertiaWorldInv)
call .accel.addScaled(f,1./.c.mass)
call .angAccel.add(angVelChange)
call angVelChange.destroy()
endmethod
method addWingGlobal takes vector relPos, vector normal, real p returns nothing
// Takes global coordinates
local real r
local real vparallel
local real vperpendicular
local vector v = vector.createProduct(.angVel,relPos).add(.vel)
local vector dotpos
if PHYS_DISPLAY_FORCES then
set dotpos = vector.createSum(.pos,relPos)
call dotpos.addScaled(v,PHYS_TIME_STEP)
endif
if .pos.z+relPos.z>=WATER_HEIGHT then
call v.subtract(physWind)
endif
set p = p*GetVolumeDensity(.pos.z+relPos.z)
set vperpendicular = scalarProduct(normal,v)
call v.subtractScaled(normal,vperpendicular)
set vparallel = v.length()
if vperpendicular<0 then
set r = -vperpendicular
else
set r = vperpendicular
endif
set r = (.002*vperpendicular*vperpendicular+vparallel*r/(r+500))*p
if vperpendicular>0 then
set r = -r
endif
if PHYS_DISPLAY_FORCES then
call DebugDot(dotpos,"ffffff")
call dotpos.addScaled(normal,r*.01)
call DebugDot(dotpos,"ff0000")
call dotpos.addScaled(normal,r*.01)
call DebugDot(dotpos,"ff0000")
call dotpos.destroy()
endif
call v.setVecScaled(normal,r)
call .addForce(relPos,v)
call v.destroy()
endmethod
method addWing takes vector relPos, vector normal, real p returns nothing
// Takes local coordinates
local vector normalRotated = normal.copy().rotateByQuaternion(.orient)
local vector relPosRotated = relPos.copy().rotateByQuaternion(.orient)
call .addWingGlobal(relPosRotated,normalRotated,p)
call relPosRotated.destroy()
call normalRotated.destroy()
endmethod
method addImpulse takes vector relPos, vector f returns nothing
local vector angVelChange = vector.createProduct(relPos,f).transformByMatrix(.inertiaWorldInv)
call .vel.addScaled(f,1./.c.mass)
call .angVel.add(angVelChange)
call angVelChange.destroy()
endmethod
method removeGroundPenetration takes nothing returns nothing
local listpoint p = .c.firstP
local vector pWorld
local real terrZ
local real flyHeight = 1000000.
loop
exitwhen p==0
if p.landingGearRetractedOffset!=0 then
if .ctrl.landingGearPos==0. then
return
endif
set pWorld = p.pos.copy()
call pWorld.addScaled(p.landingGearRetractedOffset,1-.ctrl.landingGearPos)
else
set pWorld = p.pos.copy()
endif
call pWorld.rotateByQuaternion(.orientTmp)
call pWorld.add(.pos)
set terrZ = GetSurfaceZ(pWorld.x,pWorld.y)
if pWorld.z-terrZ<flyHeight then
set flyHeight = pWorld.z-terrZ
endif
call pWorld.destroy()
set p = p.next
endloop
if flyHeight<0 then
set .pos.z = .pos.z-flyHeight
endif
endmethod
method addSound takes nothing returns nothing
set .engineSound = soundsource.create( .c.engineSoundName, .c.engineSoundPitch, .c.engineSoundVolume, -1, .pos, .vel, false )
endmethod
method addLandingGears takes nothing returns nothing
if .c.landingGearsModelName!=null then
set .landingGears = AddSpecialEffectTarget(.c.landingGearsModelName,.u,.c.landingGearsModelPosStr)
endif
endmethod
method addElevatorModel takes nothing returns nothing
if .c.elevatorModelStr!=null then
set .elevu = NewDummy(.pos.x,.pos.y,.pos.z)
set .eleve = AddSpecialEffectTarget(.c.elevatorModelStr,.elevu,"origin")
call SetUnitAnimation(.elevu,"stand")
call SetUnitPathing(.elevu,false)
call SetUnitTimeScale(.elevu,1000.)
call SetUnitScale(.elevu,.c.modelScale,.c.modelScale,.c.modelScale)
endif
endmethod
static method create takes player pid, class c, vector pos, real pitch, real roll, real yaw returns object
local object o = object.allocate()
set o.c = c
set o.u = NewDummy(pos.x,pos.y,pos.z)
call SetUnitOwner(o.u,pid,true)
set o.e = AddSpecialEffectTarget(c.modelName,o.u,"origin")
call SetUnitAnimation(o.u,"stand")
call SetUnitPathing(o.u,false)
call SetUnitTimeScale(o.u,1000.)
call SetUnitScale(o.u,c.modelScale,c.modelScale,c.modelScale)
set o.landingGears=null
set o.broken= false
set o.cloud1=null
set o.cloud2=null
set o.fire=null
set o.pos = pos
set o.posTmp = pos.copy()
set o.vel = vector.create(0,0,0)
set o.velTmp = vector.create(0,0,0)
set o.velOld = vector.create(0,0,0)
set o.accel = vector.create(0,0,0)
set o.accelOld = vector.create(0,0,0)
set o.angVel = vector.create(0,0,0)
set o.angVelTmp = vector.create(0,0,0)
set o.angAccel = vector.create(0,0,0)
set o.orient = quaternion.createEuler(roll*bj_DEGTORAD,pitch*bj_DEGTORAD,yaw*bj_DEGTORAD)
set o.orientTmp = o.orient.copy()
set o.inertiaWorld = c.inertia.copy()
call o.inertiaWorld.rotateByQuaternion(o.orient)
set o.inertiaWorldInv = o.inertiaWorld.copyInverted()
set o.firstCollTime = 1000.
set o.hp = c.hitpoints
set o.ctrl = objectCtrl.create()
set o.ctrl.rudders = vector.create(0,0,0)
set o.ctrl.ruddersVel = vector.create(0,0,0)
set o.ctrl.ruddersAim = vector.create(0,0,0)
set o.ctrl.enginePower = 0.
set o.ctrl.enginePowerAim = 0.
set o.ctrl.zRotate = 0.
set o.ctrl.weaponShots1 = 0
set o.ctrl.weaponShots2 = 0
set o.ctrl.weaponShots3 = 0
set o.ctrl.cam = 0
set o.ctrl.wantLandingGears = true
set o.ctrl.landingGearPos = 1
set o.ctrl.landingGearVel = 0
set o.ctrl.brakes = 0
set o.flareDistraction = 0
set o.followingMissiles = 0
set o.nearestMissileDist = 100000000.
set o.missileSlotA = true
set o.mgSlotA = true
set o.targ = 0
call o.addElevatorModel()
call o.addShadow()
call o.addSound()
if pid==GetLocalPlayer() then
call eyePos.setXYZ(o.pos.x-200,o.pos.y,o.pos.z)
call eyeFollow.setXYZ(o.pos.x-200,o.pos.y,o.pos.z)
endif
call UnitAddAbility(o.u,'Amrf')
call o.updateAnimation()
call UnitRemoveAbility(o.u,'Amrf')
call physObjectList.insertBehind(o)
return o
endmethod
static method createOnGround takes player pid, class c, real x, real y, real yaw returns object
local listpoint p = c.firstP
local vector minZPos = 0
local vector pos
local real incline
local real maxincline = 100
local real pitch
loop
exitwhen p==0
if minZPos==0 or p.pos.z<minZPos.z then
set minZPos=p.pos
endif
set p = p.next
endloop
set p = c.firstP
loop
exitwhen p==0
if minZPos.x!=p.pos.x then
set incline = (minZPos.z-p.pos.z)/(minZPos.x-p.pos.x)
if RAbsBJ(incline)<RAbsBJ(maxincline) then
set maxincline = incline
endif
endif
set p = p.next
endloop
set pitch = Atan(maxincline)*bj_RADTODEG
set pos = vector.create(x,y,GetSurfaceZ(x,y)-minZPos.z*Cos(pitch*bj_DEGTORAD))
return object.create(pid,c,pos,pitch,0,yaw)
endmethod
method setWingClouds takes boolean b returns nothing
if b then
if .cloud1==null and .c.cloud1PosStr!=null then
set .cloud1 = AddSpecialEffectTarget("war3mapImported\\CloudMini.mdx",.u,.c.cloud1PosStr)
set .cloud1e = AddSpecialEffectTarget("war3mapImported\\CloudEmitter.mdx",.u,.c.cloud1PosStr)
endif
if .cloud2==null and .c.cloud2PosStr!=null then
set .cloud2 = AddSpecialEffectTarget("war3mapImported\\CloudMini.mdx",.u,.c.cloud2PosStr)
set .cloud2e = AddSpecialEffectTarget("war3mapImported\\CloudEmitter.mdx",.u,.c.cloud2PosStr)
endif
if .cloud3e==null and .c.cloud3PosStr!=null then
set .cloud3e = AddSpecialEffectTarget("war3mapImported\\CloudEmitter.mdx",.u,.c.cloud3PosStr)
endif
else
if .cloud1!=null then
call DestroyEffect(.cloud1)
call DestroyEffect(.cloud1e)
set .cloud1 = null
endif
if .cloud2!=null then
call DestroyEffect(.cloud2)
call DestroyEffect(.cloud2e)
set .cloud2 = null
endif
if .cloud3e!=null then
call DestroyEffect(.cloud3e)
set .cloud3e = null
endif
endif
endmethod
method onDestroy takes nothing returns nothing
call .pos.destroy()
call .vel.destroy()
call .orient.destroy()
call .angVel.destroy()
endmethod
endstruct
endlibrary
//TESH.scrollpos=50
//TESH.alwaysfold=0
library physParticles uses physParticleClasses, vectors, terrain
struct particle
unit u
vector pos // world-coordinates
vector vel // world-coordinates
vector velTmp // world-coordinates
object sourceObj
object targetObj
particle targetP
real firstCollTime
real colltimeMin
real speed
effect e
pclass c
real age
method updateAnimation takes nothing returns nothing
call SetUnitAnimationByIndex(.u, 1)
call SetUnitLookAt(.u,"bone_Head",.u,.vel.x,.vel.y,.vel.z)
// Billboarded: call SetUnitLookAt(.u,"bone_Head",.u,GetCameraEyePositionX()-.pos.x,GetCameraEyePositionY()-.pos.y,GetCameraEyePositionZ()-.pos.z)
call SetUnitFlyHeight(.u,.pos.z-GetTerrainZ(.pos.x,.pos.y),0)
call SetUnitPosition(.u,.pos.x,.pos.y)
endmethod
static method create takes player pid, pclass c, vector pos, vector vel returns particle
local particle p = particle.allocate()
set p.u = NewDummy(pos.x,pos.y,pos.z)
call SetUnitOwner(p.u,pid,true)
call SetUnitScale(p.u,c.scale,c.scale,c.scale)
set p.e = AddSpecialEffectTarget(c.modelName,p.u,"origin")
call SetUnitAnimation(p.u,"stand")
call SetUnitPathing(p.u,false)
call SetUnitTimeScale(p.u,1000.)
set p.pos = pos
set p.vel = vel
set p.velTmp = vel.copy()
set p.firstCollTime = 1000.
set p.colltimeMin = 0.
set p.c = c
set p.age = 0
set p.sourceObj=0
set p.targetObj=0
set p.targetP=0
call UnitAddAbility(p.u,'Amrf')
call p.updateAnimation()
call UnitRemoveAbility(p.u,'Amrf')
call physParticleList.insertBehind(p)
return p
endmethod
method onDestroy takes nothing returns nothing
local particle p
local listnode ln
if .e!=null then
call DestroyEffect(.e)
endif
if .targetObj!=0 and .c==MISSILE then
set .targetObj.followingMissiles = .targetObj.followingMissiles-1
endif
if .c==MISSILE or .c==BOMB then
set .vel.z = 0
call .updateAnimation()
call DestroyEffect(AddSpecialEffectTarget("war3mapImported\\FlameBomb.mdx",.u,"origin"))
call soundsource.create( "Abilities\\Weapons\\CannonTowerMissile\\CannonTowerMissile2.wav", .8, 5, 2, .pos.copy(), vector.create(0,0,0), true )
endif
if .c==FLARE then
set ln = physParticleList.first
loop
exitwhen ln==0
set p=ln.content
if p.targetP==this then
set p.targetP=0
endif
set ln=ln.next
endloop
endif
call ReleaseDummy(.u,5)
call .pos.destroy()
call .vel.destroy()
call .velTmp.destroy()
endmethod
endstruct
endlibrary
//TESH.scrollpos=96
//TESH.alwaysfold=0
library physCollisionShapes uses debugHelper
globals
constant integer SHAPE_SPHERE = 0
constant integer SHAPE_BOX = 1
constant integer SHAPE_CYLINDER = 2
endglobals
struct shapeSphere
vector relPos
real radius
endstruct
struct shapeBox
vector relPos
vector size
quaternion orient
endstruct
struct shapeCylinder
vector relPos
real radius
real sizez
quaternion orient
endstruct
struct shapeListNode
integer form
integer sub
shapeListNode next
shapeListNode prev
method scale takes real r returns nothing
local shapeSphere s1
local shapeBox s2
local shapeCylinder s3
if .form==SHAPE_SPHERE then
set s1 = .sub
set s1.radius = s1.radius*r
call s1.relPos.scale(r)
elseif .form==SHAPE_BOX then
set s2 = .sub
call s2.relPos.scale(r)
call s2.size.scale(r)
elseif .form==SHAPE_CYLINDER then
set s3 = .sub
call s3.relPos.scale(r)
set s3.radius=s3.radius*r
set s3.sizez=s3.sizez*r
endif
endmethod
endstruct
struct shape
shapeListNode first
shapeListNode last
real boundingRadius
vector boundingSize
real boundingSizez
integer boundingForm
static method create takes nothing returns shape
local shape s = shape.allocate()
set s.first = 0
set s.last = 0
set s.boundingSize = 0
set s.boundingRadius = 0
set s.boundingForm = SHAPE_SPHERE
return s
endmethod
method addSubShapeToList takes integer form, integer subshape returns nothing
local shapeListNode ln = shapeListNode.create()
set ln.form = form
set ln.sub = subshape
if .last!=0 then
set ln.prev = .last
set .last.next = ln
endif
set .last = ln
if .first==0 then
set .first = ln
endif
endmethod
method addNewSphere takes vector relPos, real radius returns shapeSphere
local shapeSphere s = shapeSphere.create()
set s.relPos = relPos
set s.radius = radius
call .addSubShapeToList(SHAPE_SPHERE,s)
return s
endmethod
method addNewBox takes vector relPos, vector size, quaternion orient returns shapeBox
local shapeBox s = shapeBox.create()
set s.relPos = relPos
set s.size = size
set s.orient = orient
call .addSubShapeToList(SHAPE_BOX,s)
return s
endmethod
method addNewBoxBetween takes vector pos1, vector pos2, quaternion orient returns shapeBox
local shapeBox s = shapeBox.create()
set s.relPos = vector.createSum(pos1,pos2).scale(.5)
call pos1.rotateByQuaternionInv(orient)
set s.size = vector.createDifference(s.relPos,pos1)
if s.size.x<0 then
set s.size.x=-s.size.x
endif
if s.size.y<0 then
set s.size.y=-s.size.y
endif
if s.size.z<0 then
set s.size.z=-s.size.z
endif
set s.orient = orient
call pos1.destroy()
call pos2.destroy()
call .addSubShapeToList(SHAPE_BOX,s)
return s
endmethod
method addNewCylinder takes vector relPos, real radius, real sizez, quaternion orient returns shapeCylinder
local shapeCylinder s = shapeCylinder.create()
set s.relPos = relPos
set s.radius = radius
set s.sizez = sizez
set s.orient = orient
call .addSubShapeToList(SHAPE_CYLINDER,s)
return s
endmethod
method addBoundingVolume takes integer form returns nothing
local shapeListNode cur = .first
local shapeBox sBox
local shapeSphere sSphere
local shapeCylinder sCylinder
local vector v1
local vector v2
local real r
set .boundingForm = form
if form==SHAPE_BOX then
set .boundingSize = vector.create(0,0,0)
loop
exitwhen cur==0
if cur.form==SHAPE_BOX then
set sBox = cur.sub
set v1 = sBox.relPos.copy()
set v2 = sBox.size.copy()
call v2.rotateByQuaternion(sBox.orient)
if v1.x<0. then
set v1.x=-v1.x
endif
if v1.y<0. then
set v1.y=-v1.y
endif
if v1.z<0. then
set v1.z=-v1.z
endif
if v2.x<0. then
set v2.x=-v2.x
endif
if v2.y<0. then
set v2.y=-v2.y
endif
if v2.z<0. then
set v2.z=-v2.z
endif
call v1.add(v2)
if v1.x>.boundingSize.x then
set .boundingSize.x=v1.x
endif
if v1.y>.boundingSize.y then
set .boundingSize.y=v1.y
endif
if v1.z>.boundingSize.z then
set .boundingSize.z=v1.z
endif
call v1.destroy()
call v2.destroy()
elseif cur.form==SHAPE_SPHERE then
set sSphere = cur.sub
if sSphere.relPos.x+sSphere.radius>.boundingSize.x then
set .boundingSize.x = sSphere.relPos.x+sSphere.radius
endif
if sSphere.relPos.y+sSphere.radius>.boundingSize.y then
set .boundingSize.y = sSphere.relPos.y+sSphere.radius
endif
if sSphere.relPos.z+sSphere.radius>.boundingSize.z then
set .boundingSize.z = sSphere.relPos.z+sSphere.radius
endif
set r = sSphere.relPos.length()+sSphere.radius
elseif cur.form==SHAPE_CYLINDER then
set sCylinder = cur.sub
set v1 = vector.create(sCylinder.sizez,0,0)
call v1.rotateByQuaternion(sCylinder.orient)
if v1.x<0. then
set v1.x=-v1.x
endif
if v1.y<0. then
set v1.y=-v1.y
endif
if v1.z<0. then
set v1.z=-v1.z
endif
// Optimize this! Box can be closer!
set v1.x = v1.x+sCylinder.radius
set v1.y = v1.y+sCylinder.radius
set v1.z = v1.z+sCylinder.radius
if v1.x>.boundingSize.x then
set .boundingSize.x=v1.x
endif
if v1.y>.boundingSize.y then
set .boundingSize.y=v1.y
endif
if v1.z>.boundingSize.z then
set .boundingSize.z=v1.z
endif
call v1.destroy()
endif
set cur = cur.next
endloop
elseif form!=SHAPE_SPHERE then
call DebugMsg("Unknown bounding volume")
endif
set cur =.first
set .boundingRadius=0.
loop
exitwhen cur==0
if cur.form==SHAPE_BOX then
set sBox = cur.sub
set v1 = sBox.relPos.copy()
set v2 = sBox.size.copy()
call v2.rotateByQuaternion(sBox.orient)
if v1.x<0. then
set v1.x=-v1.x
endif
if v1.y<0. then
set v1.y=-v1.y
endif
if v1.z<0. then
set v1.z=-v1.z
endif
if v2.x<0. then
set v2.x=-v2.x
endif
if v2.y<0. then
set v2.y=-v2.y
endif
if v2.z<0. then
set v2.z=-v2.z
endif
call v1.add(v2)
set r = v1.length()
call v1.destroy()
call v2.destroy()
elseif cur.form==SHAPE_SPHERE then
set sSphere = cur.sub
set r = sSphere.relPos.length()+sSphere.radius
elseif cur.form==SHAPE_CYLINDER then
set sCylinder = cur.sub
set v1 = sCylinder.relPos.copy()
set v1.z=0
set r = v1.length()+sCylinder.radius
set r = SquareRoot(r*r+sCylinder.sizez*sCylinder.sizez)
call v1.destroy()
endif
if r>.boundingRadius then
set .boundingRadius=r
endif
set cur = cur.next
endloop
endmethod
method scale takes real r returns nothing
local shapeListNode cur = .first
set .boundingRadius = .boundingRadius*r
if .boundingSize!=0 then
call .boundingSize.scale(r)
endif
loop
exitwhen cur==0
call cur.scale(r)
set cur = cur.next
endloop
endmethod
endstruct
endlibrary
//TESH.scrollpos=611
//TESH.alwaysfold=0
library physCollisionDetection uses physObjects, physParticles, quaternions, matrices, vectors
globals
collision curColl = 0
endglobals
function findCollisions_SphereSphere takes object o1, shapeSphere s1, object o2, shapeSphere s2 returns nothing
local vector relVel = vector.createDifference(o2.velTmp,o1.velTmp)
local vector relPos = o1.pos.copy()
local real t = 1000.
local real a
local real b
local real c
local real r
call relPos.addRotatedByQuaternion(s1.relPos,o1.orientTmp)
call relPos.scale(-1)
call relPos.add(o2.pos)
call relPos.addRotatedByQuaternion(s2.relPos,o2.orientTmp)
set a = scalarProduct(relVel,relVel)
set b = scalarProduct(relVel,relPos)
set c = scalarProduct(relPos,relPos)-(s1.radius+s1.radius)*(s2.radius+s2.radius)
if (a>0.) then
set b = b/a
set c = c/a
if (b*b - c)>=0. then
set r = SquareRoot(b*b - c)
if (r>=b) then
set t = - b - r
endif
endif
elseif c<0 then
set t = 0.
endif
if t<=PHYS_TIME_STEP then
if t<o1.firstCollTime then
set o1.firstCollTime = t
endif
if t<o2.firstCollTime then
set o2.firstCollTime = t
endif
call relPos.addScaled(relVel,t)
call relPos.normalise()
set curColl = collision.create(o1,o2)
call curColl.addCollisionPoint(relPos.copyScaled(s1.radius),0,relPos.copyScaled(-s2.radius),0,relPos,0)
else
call relPos.destroy()
endif
call relVel.destroy()
endfunction
function findCollisions_BoxBox takes object o1, shapeBox s1, object o2, shapeBox s2 returns nothing
endfunction
function findCollisions_CylinderCylinder takes object o1, shapeCylinder s1, object o2, shapeCylinder s2 returns nothing
endfunction
function findCollisions_ObjectObject takes object o1, object o2 returns nothing
local shapeListNode ln1
local shapeListNode ln2
if o1.c.collshape==0 or o2.c.collshape==0 then
return
endif
set curColl = 0
set ln1 = o1.c.collshape.first
loop
exitwhen ln1==0
set ln2 = o2.c.collshape.first
loop
exitwhen ln2==0
if ln1.form==SHAPE_SPHERE and ln2.form==SHAPE_SPHERE then
call findCollisions_SphereSphere(o1,ln1,o2,ln2)
elseif ln1.form==SHAPE_BOX and ln2.form==SHAPE_BOX then
call findCollisions_BoxBox(o1,ln1,o2,ln2)
elseif ln1.form==SHAPE_CYLINDER and ln2.form==SHAPE_CYLINDER then
call findCollisions_CylinderCylinder(o1,ln1,o2,ln2)
else
call DebugMsg("Unknown collision shape pair")
endif
set ln2 = ln2.next
endloop
set ln1 = ln1.next
endloop
endfunction
function findCollisions_ParticleSphere takes particle p1, object o2, shapeSphere s2 returns nothing
local vector relVel = vector.createDifference(o2.velTmp,p1.vel)
local vector relPos = vector.createDifference(o2.pos,p1.pos)
local real t = 1000.
local real a
local real b
local real c
local real r
call relPos.addRotatedByQuaternion(s2.relPos,o2.orient)
set a = scalarProduct(relVel,relVel)
set b = scalarProduct(relVel,relPos)
set c = scalarProduct(relPos,relPos)-s2.radius*s2.radius
if (a>0.) then
set b = b/a
set c = c/a
if ((b*b - c)>=0.) then
set r = SquareRoot(b*b - c)
if (r>=b) then
set t = - b - r
endif
endif
elseif c<0 then
set t = 0.
endif
if t<=PHYS_TIME_STEP then
call relPos.addScaled(relVel,t)
call relPos.normalise()
if curColl==0 then
set curColl = collision.pcreate(p1,o2)
endif
call curColl.addCollisionPoint(0,0,relPos.copyScaled(-s2.radius),0,relPos,0)
if t<p1.firstCollTime then
set p1.firstCollTime = t
endif
if t<o2.firstCollTime then
set o2.firstCollTime = t
endif
else
call relPos.destroy()
endif
call relVel.destroy()
endfunction
function findCollisions_ParticleBox takes particle p1, object o2, shapeBox s2 returns nothing
// Go to the object's frame of reference
local vector relVel = vector.createDifference(o2.velTmp,p1.vel).rotateByQuaternionInv(o2.orient)
local vector relPos = vector.createDifference(o2.pos,p1.pos).rotateByQuaternionInv(o2.orient).add(s2.relPos)
local vector normal
local real tmin
local real tmax
local real tymin
local real tymax
local real tzmin
local real tzmax
local integer colldim = 1
// Go to the box's frame of reference
call relVel.rotateByQuaternion(s2.orient)
call relPos.rotateByQuaternion(s2.orient)
if relVel.x>0. then
set tmin = (-relPos.x - s2.size.x)/relVel.x
set tmax = (-relPos.x + s2.size.x)/relVel.x
elseif relVel.x<0. then
set tmin = (-relPos.x + s2.size.x)/relVel.x
set tmax = (-relPos.x - s2.size.x)/relVel.x
elseif s2.size.x<relPos.x or s2.size.x<-relPos.x then
call relVel.destroy()
call relPos.destroy()
return
else
set tmin = -1000.
set tmax = 1000.
endif
if relVel.y>0. then
set tymin = (-relPos.y - s2.size.y)/relVel.y
set tymax = (-relPos.y + s2.size.y)/relVel.y
elseif relVel.y<0. then
set tymin = (-relPos.y + s2.size.y)/relVel.y
set tymax = (-relPos.y - s2.size.y)/relVel.y
elseif s2.size.y<relPos.y or s2.size.y<-relPos.y then
call relVel.destroy()
call relPos.destroy()
return
else
set tymin = -1000.
set tymax = 1000.
endif
if tmin>tymax or tymin>tmax then
call relVel.destroy()
call relPos.destroy()
return
endif
if relVel.z>0. then
set tzmin = (-relPos.z - s2.size.z)/relVel.z
set tzmax = (-relPos.z + s2.size.z)/relVel.z
elseif relVel.z<0. then
set tzmin = (-relPos.z + s2.size.z)/relVel.z
set tzmax = (-relPos.z - s2.size.z)/relVel.z
elseif s2.size.z<relPos.z or s2.size.z<-relPos.z then
call relVel.destroy()
call relPos.destroy()
return
else
set tzmin = -1000.
set tzmax = 1000.
endif
if tymin>tmin then
set tmin=tymin
set colldim = 2
endif
if tzmin>tmin then
set tmin=tzmin
set colldim = 3
endif
if tymax<tmax then
set tmax=tymax
endif
if tzmax<tmax then
set tmax=tzmax
endif
if tmax<tmin or tmax<0. or tmin>PHYS_TIME_STEP then
call relVel.destroy()
call relPos.destroy()
return
endif
if tmin<0. then
set tmin=0.
endif
// We have a collision and need to return the normal back
if colldim==1 then
if relVel.x<0. then
set normal = vector.create(1,0,0)
else
set normal = vector.create(-1,0,0)
endif
elseif colldim==2 then
if relVel.y<0. then
set normal = vector.create(0,1,0)
else
set normal = vector.create(0,-1,0)
endif
else
if relVel.z<0. then
set normal = vector.create(0,0,1)
else
set normal = vector.create(0,0,-1)
endif
endif
// Go to global frame of reference
call normal.rotateByQuaternionInv(s2.orient)
call normal.rotateByQuaternion(o2.orient)
if curColl==0 then
set curColl = collision.pcreate(p1,o2)
endif
call relVel.setDifference(p1.vel,o2.velTmp)
call relPos.setDifference(p1.pos,o2.pos).addScaled(relVel,tmin)
call relVel.destroy()
call curColl.addCollisionPoint(0,0,relPos,0,normal,0)
if tmin<p1.firstCollTime then
set p1.firstCollTime = tmin
endif
if tmin<o2.firstCollTime then
set o2.firstCollTime = tmin
endif
endfunction
function findCollisions_ParticleCylinder takes particle p1, object o2, shapeCylinder s2 returns nothing
// Go to the object's frame of reference
local vector relVel = vector.createDifference(o2.velTmp,p1.vel).rotateByQuaternionInv(o2.orient)
local vector relPos = vector.createDifference(o2.pos,p1.pos).rotateByQuaternionInv(o2.orient).add(s2.relPos)
local vector normal
local real tzmin
local real tzmax
local integer colldim = 1
local real t = 1000.
local real a
local real b
local real c
local real r
// Go to the box's frame of reference
call relVel.rotateByQuaternion(s2.orient)
call relPos.rotateByQuaternion(s2.orient)
set a = relVel.x*relVel.x+relVel.y*relVel.y
set b = relVel.x*relPos.x+relVel.y*relPos.y
set c = relPos.x*relPos.x+relPos.y*relPos.y-s2.radius*s2.radius
if a>0. then
set b = b/a
set c = c/a
if (b*b - c)>=0. then
set r = SquareRoot(b*b - c)
if r>=b then
set t = -b-r
endif
endif
elseif c<0 then
set t = 0.
endif
if relVel.z>0. then
set tzmin = (-relPos.z - s2.sizez)/relVel.z
set tzmax = (-relPos.z + s2.sizez)/relVel.z
elseif relVel.z<0. then
set tzmin = (-relPos.z + s2.sizez)/relVel.z
set tzmax = (-relPos.z - s2.sizez)/relVel.z
elseif s2.sizez<relPos.z or s2.sizez<-relPos.z then
call relVel.destroy()
call relPos.destroy()
return
else
set tzmin = -1000.
set tzmax = 1000.
endif
if tzmin>t then
set colldim=3
set t = tzmin
endif
if tzmax<t or tzmax<0. or t>PHYS_TIME_STEP then
call relVel.destroy()
call relPos.destroy()
return
endif
if t<0. then
set t=0.
endif
// We have a collision and need to return the coordinates back
if colldim==1 then
set normal = relPos.copy()
call normal.addScaled(relVel,t)
set normal.z=0.
call normal.normalise()
else
if relVel.z<0. then
set normal = vector.create(0,0,1)
else
set normal = vector.create(0,0,-1)
endif
endif
// Go to global frame of reference
call normal.rotateByQuaternionInv(s2.orient)
call normal.rotateByQuaternion(o2.orient)
if curColl==0 then
set curColl = collision.pcreate(p1,o2)
endif
call relPos.setDifference(p1.pos,o2.pos)
call relVel.setDifference(p1.vel,o2.velTmp)
call relPos.addScaled(relVel,t)
call relVel.destroy()
call curColl.addCollisionPoint(0,0,relPos,0,normal,0)
if t<p1.firstCollTime then
set p1.firstCollTime = t
endif
if t<o2.firstCollTime then
set o2.firstCollTime = t
endif
endfunction
function findCollisions_ParticleObject_CheckBoundingCylinder takes particle p1, object o2 returns boolean
// Go to the object's frame of reference
local vector relVel = vector.createDifference(o2.velTmp,p1.vel).rotateByQuaternionInv(o2.orient)
local vector relPos = vector.createDifference(o2.pos,p1.pos).rotateByQuaternionInv(o2.orient)
local vector normal
local real tzmin
local real tzmax
local real t = 1000.
local real a
local real b
local real c
local real r
local real sizez = o2.c.collshape.boundingSizez
set a = relVel.x*relVel.x+relVel.y*relVel.y
set b = relVel.x*relPos.x+relVel.y*relPos.y
set c = relPos.x*relPos.x+relPos.y*relPos.y-o2.c.collshape.boundingRadius*o2.c.collshape.boundingRadius
if a>0. then
set b = b/a
set c = c/a
if (b*b - c)>=0. then
set r = SquareRoot(b*b - c)
if r>=b then
set t = -b-r
endif
endif
elseif c<0 then
set t = 0.
endif
if relVel.z>0. then
set tzmin = (-relPos.z - sizez)/relVel.z
set tzmax = (-relPos.z + sizez)/relVel.z
elseif relVel.z<0. then
set tzmin = (-relPos.z + sizez)/relVel.z
set tzmax = (-relPos.z - sizez)/relVel.z
elseif sizez<relPos.z or sizez<-relPos.z then
call relVel.destroy()
call relPos.destroy()
return false
else
set tzmin = -1000.
set tzmax = 1000.
endif
if tzmin>t then
set t = tzmin
endif
call relVel.destroy()
call relPos.destroy()
return not( tzmax<t or tzmax<0. or t>PHYS_TIME_STEP )
endfunction
function findCollisions_ParticleObject_CheckBoundingBox takes particle p1, object o2 returns boolean
// Go to the object's frame of reference
local vector relVel = vector.createDifference(o2.velTmp,p1.vel).rotateByQuaternionInv(o2.orient)
local vector relPos = vector.createDifference(o2.pos,p1.pos).rotateByQuaternionInv(o2.orient)
local vector size = o2.c.collshape.boundingSize
local real tmin
local real tmax
local real tymin
local real tymax
local real tzmin
local real tzmax
if relVel.x>0. then
set tmin = (-relPos.x - size.x)/relVel.x
set tmax = (-relPos.x + size.x)/relVel.x
elseif relVel.x<0. then
set tmin = (-relPos.x + size.x)/relVel.x
set tmax = (-relPos.x - size.x)/relVel.x
elseif size.x<relPos.x or size.x<-relPos.x then
call relVel.destroy()
call relPos.destroy()
return false
else
set tmin = -1000.
set tmax = 1000.
endif
if relVel.y>0. then
set tymin = (-relPos.y - size.y)/relVel.y
set tymax = (-relPos.y + size.y)/relVel.y
elseif relVel.y<0. then
set tymin = (-relPos.y + size.y)/relVel.y
set tymax = (-relPos.y - size.y)/relVel.y
elseif size.y<relPos.y or size.y<-relPos.y then
call relVel.destroy()
call relPos.destroy()
return false
else
set tymin = -1000.
set tymax = 1000.
endif
if tmin>tymax or tymin>tmax then
call relVel.destroy()
call relPos.destroy()
return false
endif
if relVel.z>0. then
set tzmin = (-relPos.z - size.z)/relVel.z
set tzmax = (-relPos.z + size.z)/relVel.z
elseif relVel.z<0. then
set tzmin = (-relPos.z + size.z)/relVel.z
set tzmax = (-relPos.z - size.z)/relVel.z
elseif size.z<relPos.z or size.z<-relPos.z then
call relVel.destroy()
call relPos.destroy()
return false
else
set tzmin = -1000.
set tzmax = 1000.
endif
if tymin>tmin then
set tmin=tymin
endif
if tzmin>tmin then
set tmin=tzmin
endif
if tymax<tmax then
set tmax=tymax
endif
if tzmax<tmax then
set tmax=tzmax
endif
call relVel.destroy()
call relPos.destroy()
return not( tmax<tmin or tmax<0. or tmin>PHYS_TIME_STEP )
endfunction
function findCollisions_ParticleObject_CheckBoundingSphere takes particle p1, object o2 returns boolean
local vector relVel = vector.createDifference(o2.velTmp,p1.vel)
local vector relPos = vector.createDifference(o2.pos,p1.pos)
local real a
local real b
local real c
local boolean ret = false
set a = scalarProduct(relVel,relVel)
set b = scalarProduct(relVel,relPos)
set c = scalarProduct(relPos,relPos)-o2.c.collshape.boundingRadius*o2.c.collshape.boundingRadius
if a>0. then
set b = b/a
set c = c/a
if (b*b - c)>=0. then
if b<=0 or c<=0 then
set ret = (PHYS_TIME_STEP+b)>=0 or b*b-c>=(PHYS_TIME_STEP+b)*(PHYS_TIME_STEP+b)
endif
endif
elseif c<0. then
set ret = true
endif
call relPos.destroy()
call relVel.destroy()
return ret
endfunction
function findCollisions_ParticleObject_CheckBoundings takes particle p1, object o2 returns boolean
if o2.c.collshape.boundingForm==SHAPE_SPHERE then
return findCollisions_ParticleObject_CheckBoundingSphere(p1,o2)
elseif o2.c.collshape.boundingForm==SHAPE_BOX then
return findCollisions_ParticleObject_CheckBoundingBox(p1,o2)
elseif o2.c.collshape.boundingForm==SHAPE_CYLINDER then
return findCollisions_ParticleObject_CheckBoundingCylinder(p1,o2)
endif
call DebugMsg("Unknown bounding volume")
return false
endfunction
function findCollisions_ParticleObject takes particle p1, object o2 returns nothing
local shapeListNode ln2
local real tmin = 0
if o2.c.collshape==0 or (o2==p1.sourceObj and p1.age<1.) then
return
endif
set tmin = (p1.pos.distTo(o2.pos)-o2.c.collshape.boundingRadius)/(PHYS_MAX_OBJECT_SPEED+p1.speed)
if tmin<p1.colltimeMin then
set p1.colltimeMin=tmin
endif
if tmin>PHYS_TIME_STEP or not findCollisions_ParticleObject_CheckBoundings(p1,o2) then
return
endif
set curColl = 0
set ln2 = o2.c.collshape.first
loop
exitwhen ln2==0
if ln2.form==SHAPE_SPHERE then
call findCollisions_ParticleSphere(p1,o2,ln2.sub)
elseif ln2.form==SHAPE_BOX then
call findCollisions_ParticleBox(p1,o2,ln2.sub)
elseif ln2.form==SHAPE_CYLINDER then
call findCollisions_ParticleCylinder(p1,o2,ln2.sub)
else
call DebugMsg("Unknown collision shape pair")
endif
set ln2 = ln2.next
endloop
endfunction
function findCollisions_ParticleTerrain takes particle p returns nothing
local real t = 1000.
local real terrZ = GetTerrainZ(p.pos.x,p.pos.y)
local vector normal
if p.vel.z<0 then
set t = (terrZ-p.pos.z)/p.vel.z
elseif p.pos.z<terrZ then
set t = 0
endif
if t<=PHYS_TIME_STEP then
set curColl = collision.pcreate(p,0)
set normal = GetTerrainNormal(p.pos.x,p.pos.y)
call normal.scale(-1)
call curColl.addCollisionPoint(0,0,0,0,normal,0)
if t<p.firstCollTime then
set p.firstCollTime = t
endif
endif
endfunction
function findCollisions_ObjectTerrain takes object o returns nothing
local listpoint p = o.c.firstP
local vector pWorld
local vector normal
local vector frictDir
local real t
local real r
local real terrZ
local vector v1
local vector v2
local vector vel
set curColl = 0
loop
exitwhen p==0
if p.landingGearRetractedOffset!=0 then
if o.ctrl.landingGearPos==0. then
return
endif
set pWorld = p.pos.copy().addScaled(p.landingGearRetractedOffset,1-o.ctrl.landingGearPos)
elseif p.attachTo==ELEVATOR then
set pWorld = p.pos.copy().rotateAroundYAxis(o.c.elevatorBaseAngle-o.c.elevatorMaxControlAngle*o.ctrl.rudders.y)
call pWorld.add(o.c.elevatorModelPos)
else
set pWorld = p.pos.copy()
endif
call pWorld.rotateByQuaternion(o.orientTmp).add(o.pos)
set terrZ = GetSurfaceZ(pWorld.x,pWorld.y)
if o.velTmp.z<0. then
set t = (terrZ-pWorld.z)/o.velTmp.z
elseif pWorld.z<terrZ then
set t = 0.
else
set t = 1000.
endif
if p.displacement!=0. then
set r = 5*GetVolumeMassInSphere(pWorld.z,p.displacementRadius)/(4/3*bj_PI*p.displacementRadius*p.displacementRadius*p.displacementRadius)
if o.broken then
set r = r*.3
endif
call pWorld.subtract(o.pos)
set normal = vector.create(0,0,p.displacement*r)
call o.addForce(pWorld,normal)
call normal.destroy()
call pWorld.add(o.pos)
endif
if PHYS_DISPLAY_COLLISIONPOINTS then
set v1 = pWorld.copy()
call v1.addScaled(o.vel,PHYS_TIME_STEP)
if t<=PHYS_TIME_STEP then
call DebugDot(v1,"00ff00")
else
call DebugDot(v1,"0000ff")
endif
call v1.destroy()
endif
if t<=PHYS_TIME_STEP then
set normal = GetSurfaceNormal(pWorld.x,pWorld.y).scale(-1.)
call pWorld.subtract(o.pos)
if curColl == 0 then
set curColl = collision.create(o,0)
endif
set frictDir = 0
if p.landingGearFrictDir!=0 then
if o.ctrl.brakes<.5 then
set frictDir = p.landingGearFrictDir.copy()
if p.landingGearSteering*o.ctrl.rudders.z!=0 then
call frictDir.rotateAroundZAxis(-p.landingGearSteering*o.ctrl.rudders.z*bj_DEGTORAD)
endif
call frictDir.rotateByQuaternion(o.orientTmp)
endif
call curColl.addCollisionPoint(pWorld,p.landingGearRetractedOffset.copyScaled(-o.ctrl.landingGearVel),0,0,normal,frictDir)
elseif p.attachTo==ELEVATOR then
set v2 = o.c.elevatorModelPos.copy().rotateByQuaternion(o.orient)
set v1 = vector.createDifference(pWorld,v2)
call v2.setXYZ(0,o.ctrl.ruddersVel.y*o.c.elevatorMaxControlAngle,0).rotateByQuaternion(o.orient)
set vel = vector.createProduct(v1,v2)
if scalarProduct(vel,normal)>0 then
set o.ctrl.rudders.y = o.ctrl.rudders.y-o.ctrl.ruddersVel.y*PHYS_TIME_STEP
call vel.destroy()
set vel = 0
endif
call curColl.addCollisionPoint(pWorld,vel,0,0,normal,frictDir)
call v1.destroy()
call v2.destroy()
else
call curColl.addCollisionPoint(pWorld,0,0,0,normal,frictDir)
endif
if t<o.firstCollTime then
set o.firstCollTime = t
endif
else
call pWorld.destroy()
endif
set p = p.next
endloop
endfunction
function collisionDetection_Object takes object o returns nothing
local listnode n2 = physObjectList.first
loop
exitwhen n2==0
//call findCollisions_ObjectObject(o,n2.content)
set n2 = n2.next
endloop
call findCollisions_ObjectTerrain(o)
endfunction
function collisionDetection_Particle takes particle p returns nothing
local listnode n2 = physObjectList.first
if p.colltimeMin<=PHYS_TIME_STEP then
set p.speed = p.vel.length()
loop
exitwhen n2==0
call findCollisions_ParticleObject(p,n2.content)
set n2 = n2.next
endloop
endif
call findCollisions_ParticleTerrain(p)
set p.colltimeMin = p.colltimeMin - PHYS_TIME_STEP
endfunction
function collisionDetection takes nothing returns nothing
local listnode n1 = physParticleList.first
call RegisterThread("Collision Detection")
loop
exitwhen n1==0
call collisionDetection_Particle(n1.content)
set n1 = n1.next
endloop
set n1 = physObjectList.first
loop
exitwhen n1==0
call collisionDetection_Object(n1.content)
set n1 = n1.next
endloop
call UnregisterThread("Collision Detection")
endfunction
endlibrary
//TESH.scrollpos=184
//TESH.alwaysfold=0
library physCollisionResponse uses physObjects, physParticles, quaternions, matrices, vectors
globals
list collisionList
endglobals
struct collisionpoint
vector rel1
vector rel2
vector velOn1
vector velOn2
vector normal
vector angVelChange1
vector angVelChange2
vector angMomChange1
vector angMomChange2
vector frictDir
real denominator
collisionpoint next
static method create takes vector rel1, integer velOn1, vector rel2, integer velOn2, vector normal, vector frictDir returns collisionpoint
// All Coordinates in World-Coordinates
local collisionpoint p = collisionpoint.allocate()
set p.rel1 = rel1
set p.rel2 = rel2
set p.velOn1 = velOn1
set p.velOn2 = velOn2
set p.normal = normal
set p.next = 0
set p.angMomChange1 = 0
set p.angVelChange1 = 0
set p.angMomChange2 = 0
set p.angVelChange2 = 0
set p.frictDir = frictDir
return p
endmethod
method onDestroy takes nothing returns nothing
if .rel1!=0 then
call .rel1.destroy()
endif
if .rel2!=0 then
call .rel2.destroy()
endif
if .angMomChange1!=0 then
call .angMomChange1.destroy()
call .angVelChange1.destroy()
endif
if .angMomChange2!=0 then
call .angMomChange2.destroy()
call .angVelChange2.destroy()
endif
if .frictDir!=0 then
call .frictDir.destroy()
endif
if .velOn1!=0 then
call .velOn1.destroy()
endif
if .velOn2!=0 then
call .velOn2.destroy()
endif
call .normal.destroy()
endmethod
endstruct
struct collision
real e
particle p1 // Either particle or object
object o1 // Only one variable written
object o2
collisionpoint cp
static method create takes object o1, object o2 returns collision
local collision coll = collision.allocate()
set coll.p1 = 0
set coll.o1 = o1
set coll.o2 = o2
set coll.e = 0.
set coll.cp = 0
call collisionList.insertBehind(coll)
return coll
endmethod
static method pcreate takes particle p1, object o2 returns collision
local collision coll = collision.allocate()
set coll.p1 = p1
set coll.o1 = 0
set coll.o2 = o2
set coll.e = 1.
set coll.cp = 0
call collisionList.insertBehind(coll)
return coll
endmethod
method addCollisionPoint takes vector rel1, vector velOn1, vector rel2, vector velOn2, vector normal, vector frictDir returns collisionpoint
local collisionpoint p = collisionpoint.create(rel1,velOn1,rel2,velOn2,normal,frictDir)
if .cp==0 then
set .cp = p
else
set p.next = .cp
set .cp = p
endif
return p
endmethod
method prepare takes nothing returns nothing
local collisionpoint p = .cp
local vector linVelFromAngVel
loop
exitwhen p==0
set p.denominator = 0.
if .o1!=0 then
set p.angMomChange1 = vector.createProduct(p.rel1,p.normal)
set p.angVelChange1 = p.angMomChange1.copy().transformByMatrix(.o1.inertiaWorldInv)
set linVelFromAngVel = vector.createProduct(p.angVelChange1,p.rel1)
set p.denominator = p.denominator + 1./.o1.c.mass + scalarProduct(linVelFromAngVel,p.normal)
call linVelFromAngVel.destroy()
elseif .p1!=0 then
set p.denominator = p.denominator + 1./.p1.c.mass
if .p1.c.explodeOnHit then
set .p1.age = 1000.
if .o2!=0 then
//call .o2.damage(50)
//call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl",.o2.u,"origin"))
else
//call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl",.p1.pos.x,.p1.pos.y))
endif
endif
endif
if .o2!=0 then
set p.angMomChange2 = vector.createProduct(p.rel2,p.normal)
set p.angVelChange2 = p.angMomChange2.copy().transformByMatrix(.o2.inertiaWorldInv)
set linVelFromAngVel = vector.createProduct(p.angVelChange2,p.rel2)
set p.denominator = p.denominator + 1./.o2.c.mass + scalarProduct(linVelFromAngVel,p.normal)
call linVelFromAngVel.destroy()
endif
set p = p.next
endloop
endmethod
method respond takes boolean elastic returns nothing
local vector vdiff = vector.create(0,0,0)
local real Jmod
local collisionpoint p = .cp
local real hitSpeed
local real slideSpeed
local real elasticityFactor = 0.
if elastic then
set elasticityFactor = 1.
endif
loop
exitwhen p==0
call vdiff.setXYZ(0,0,0)
if .o1!=0 then
call vdiff.add(.o1.vel)
call vdiff.addProduct(.o1.angVel,p.rel1)
elseif .p1!=0 then
call vdiff.add(.p1.vel)
endif
if p.velOn1!=0 then
call vdiff.add(p.velOn1)
endif
if p.velOn2!=0 then
call vdiff.subtract(p.velOn2)
endif
if .o2!=0 then
call vdiff.subtract(.o2.vel)
call vdiff.addProduct(p.rel2,.o2.angVel)
endif
// Calculate perpendicular component
set hitSpeed = scalarProduct(vdiff,p.normal)
set Jmod = (.e*elasticityFactor+1.)*hitSpeed/p.denominator
if Jmod>0 then
// Calculate slide vector
call vdiff.subtractScaled(p.normal,hitSpeed)
if p.frictDir!=0 then
call vdiff.setVecScaled(p.frictDir,scalarProduct(p.frictDir,vdiff))
endif
set slideSpeed = vdiff.length()+1.
call vdiff.scale(-Jmod/slideSpeed)
if .o1!=0 then
call .o1.vel.addScaled(p.normal,-Jmod/.o1.c.mass)
call .o1.angVel.addScaled(p.angVelChange1,-Jmod)
call .o1.addImpulse(p.rel1,vdiff)
elseif .p1!=0 then
call .p1.vel.addScaled(p.normal,-Jmod/.p1.c.mass)
call .p1.vel.add(vdiff)
endif
call vdiff.scale(-1)
if .o2!=0 then
call .o2.vel.addScaled(p.normal,Jmod/.o2.c.mass)
call .o2.angVel.addScaled(p.angVelChange2,Jmod)
call .o2.addImpulse(p.rel1,vdiff)
endif
endif
set p = p.next
endloop
call vdiff.destroy()
endmethod
method onDestroy takes nothing returns nothing
local collisionpoint p = .cp
local collisionpoint pdest
loop
exitwhen p==0
set pdest = p
set p = p.next
call pdest.destroy()
endloop
endmethod
endstruct
function collisionResponsePrepare takes nothing returns nothing
local collision coll
call collisionList.toFirst()
loop
exitwhen collisionList.outOfList()
set coll = collisionList.getContent()
call coll.prepare()
call collisionList.toNext()
endloop
endfunction
function collisionResponse takes integer enumerations, boolean elastic returns nothing
local collision coll
local integer i = 1
call RegisterThread("Collision Response")
loop
exitwhen i > enumerations
call collisionList.toFirst()
loop
exitwhen collisionList.outOfList()
set coll = collisionList.getContent()
call coll.respond(elastic)
call collisionList.toNext()
endloop
set i = i + 1
endloop
call UnregisterThread("Collision Response")
endfunction
function collisionResponseDestroy takes nothing returns nothing
local collision coll
call collisionList.toFirst()
loop
exitwhen collisionList.outOfList()
set coll = collisionList.getContent()
call coll.destroy()
call collisionList.pop()
endloop
endfunction
endlibrary
//TESH.scrollpos=608
//TESH.alwaysfold=0
library physHelpers uses physCollisionDetection, lists
function GetMissileTarget takes particle p returns object
local vector dir = p.vel.copy()
local vector relPos
local object o = 0
local listnode n
local real vel = p.vel.length()
local real dsq
local real dsqmin = 0
local object omin = 0
call dir.normalise()
set n = physObjectList.first
loop
exitwhen n==0
set o = n.content
if o!=p.sourceObj then
set relPos = vector.createDifference(o.pos,p.pos)
if scalarProduct(p.vel,relPos)>0 then
call relPos.subtractScaled(p.vel,relPos.length()/vel)
set dsq = scalarProduct(relPos,relPos)
if omin==0 or dsq<dsqmin then
set omin=o
set dsqmin=dsq
endif
endif
call relPos.destroy()
endif
set n = n.next
endloop
call dir.destroy()
return omin
endfunction
function MGInterceptTarget takes particle p, real bulletVel, vector firedir, real maxangle, object targ returns nothing
local vector relPos = vector.createDifference(p.pos,targ.pos)
local vector relVel = vector.createDifference(targ.vel,p.vel)
local real relVelLength = relVel.length()
local real dsq = relPos.lengthSq()
local real y = scalarProduct(relPos,relVel)/relVelLength
local real targetVel_sq = relVel.lengthSq()
local real bulletVel_sq = bulletVel * bulletVel
local real t1 = -1.
local real t2 = -1.
local real r
local real speed_coeff = bulletVel_sq / targetVel_sq - 1.0
local real delta
local vector dir1
local vector dir2
local vector dir3
if (RAbsBJ(speed_coeff) <= 0.001) then
set t2 = dsq / (2.*y*relVelLength)
else
set delta = y * y + speed_coeff * dsq
if delta>=0. then
set delta = SquareRoot(delta)
set t1 = (-y + delta) / (speed_coeff*relVelLength)
set t2 = (-y - delta) / (speed_coeff*relVelLength)
endif
endif
if t1<0. and t2<0. then
call relPos.destroy()
call relVel.destroy()
call p.vel.addScaled(firedir,bulletVel)
return
endif
set dir1 = relPos.copyScaled(-1)
call dir1.addScaled(relVel,t1)
set dir2 = relPos.copyScaled(-1)
call dir2.addScaled(relVel,t2)
//Now get the vector closer to firedir
if t1<0. or (t2>=0. and t2<t1) then
call dir1.destroy()
set dir1 = dir2
set t1 = t2
else
call dir2.destroy()
endif
call dir1.normalise()
set dir1.z = dir1.z+.5*PHYS_GRAVITY*t1*t1/bulletVel
call dir1.addScaled(p.targetObj.accelOld,.5*t1*t1/bulletVel)
call dir1.normalise()
set r = scalarProduct(dir1,firedir)
if r<Cos(maxangle) then
call dir1.scale(.97/Cos(maxangle))
set dir2 = dir1.copy().subtract(firedir).setLength(Sin(maxangle))
call dir1.setVec(firedir).scale(Cos(maxangle)).add(dir2)
call dir2.destroy()
endif
call dir1.scale(bulletVel)
if p.c==BOMB then
call dir1.randomise(.2)
else
call dir1.randomise(.01)
endif
call p.vel.add(dir1)
call relPos.destroy()
call relVel.destroy()
call dir1.destroy()
endfunction
function MGIntercept takes particle p, vector firedir, real maxangle returns nothing
local real bulletVel = firedir.length()
local vector n = firedir.copy().normalise()
set p.targetObj = GetMissileTarget(p)
if p.targetObj!=0 then
call MGInterceptTarget(p,bulletVel,n,maxangle,p.targetObj)
else
call n.destroy()
if p.c==BOMB then
set n = firedir.copy().randomise(.2)
else
set n = firedir.copy().randomise(.01)
endif
call p.vel.add(n)
endif
call n.destroy()
endfunction
function MissileFollow takes particle p returns nothing
local vector relPos
local vector direction = p.vel.copy()
local vector relPosTemp
local vector targetAccel = VECTOR0
local vector targetVel
local real missileVel = p.vel.length()
local real missileAccel = p.c.accel
local real parallelDist
local real perpendicularDist
local real t
local real dist
local integer i
if p.targetP!=0 then
set relPos = vector.createDifference(p.targetP.pos,p.pos)
set dist = relPos.length()
set targetVel = p.targetP.vel
else
set relPos = vector.createDifference(p.targetObj.pos,p.pos)
set dist = relPos.length()
if dist<p.targetObj.nearestMissileDist then
set p.targetObj.nearestMissileDist=dist
endif
set targetVel = p.targetObj.vel
set targetAccel = p.targetObj.accelOld
endif
set relPosTemp = relPos.copy()
if missileVel!=0. then
call direction.scale(1/missileVel)
else
call direction.setXYZ(0,0,1)
endif
set parallelDist = scalarProduct(direction,relPos)
if parallelDist<=0. or (p.targetP==0 and p.targetObj.flareDistraction>0.) then
set p.targetObj.followingMissiles = p.targetObj.followingMissiles-1
call relPos.destroy()
call relPosTemp.destroy()
call direction.destroy()
set p.targetObj=0
return
endif
set i = 1
loop
exitwhen i > 5
if missileAccel!=0. then
set t = -missileVel/missileAccel + SquareRoot((missileVel/missileAccel)*(missileVel/missileAccel)+2*relPos.length()/missileAccel)
else
set t = relPos.length()/missileVel
endif
call relPos.setVec(relPosTemp).addScaled(targetVel,t).addScaled(targetAccel,.5*t*t)
set relPos.z = relPos.z+.5*PHYS_GRAVITY*t*t
if relPos.z>PHYS_BOUND_MAX_Z-p.pos.z then
set relPos.z=PHYS_BOUND_MAX_Z-p.pos.z
endif
set i = i + 1
endloop
call relPosTemp.setVec(relPos)
call relPosTemp.subtractScaled(direction,parallelDist)
set perpendicularDist = relPosTemp.length()
// relPos is now the target direction
call relPos.normalise()
if perpendicularDist!=0 then
call relPosTemp.scale(1./perpendicularDist)
else
call relPosTemp.setXYZ(0,0,1)
endif
call p.vel.addScaled(relPosTemp,missileVel*RMinBJ(p.c.aim*PHYS_TIME_STEP,perpendicularDist/parallelDist))
call p.vel.setLength(missileVel+missileAccel*PHYS_TIME_STEP)
call relPos.destroy()
call relPosTemp.destroy()
call direction.destroy()
endfunction
function AIFollow takes object ai, object target returns nothing
local vector aiUp = vector.create(0,0,1).rotateByQuaternion(ai.orient)
local vector aiSide
local vector relPos
local vector v
local integer aipid = GetPlayerId(GetOwningPlayer(ai.u))
local real r
local real d
local boolean onAttack = false
set ai.ctrl.enginePowerAim=1.
if (ai.pos.z<2000 and ai.c!=DESTROYER) or target==0 then
set relPos=vector.create(-ai.vel.x,-ai.vel.y,-1)
if ai.pos.z<2000 then
set relPos.z = -relPos.length()
endif
if target==0 then
if GetRandomInt(0,40)==0 then
call IssueImmediateOrder(playerController[aipid],"attack")
endif
endif
else
set relPos = vector.createDifference(ai.pos,target.pos)
set d = relPos.length()
call relPos.subtractScaled(target.vel,d/(ai.vel.length()+1000.))
if scalarProduct(relPos,ai.vel)<0 then
// Moving to the target
set d=d-1500
if d<0 then
set d = 0
endif
set onAttack = true
//else
// Circling back
endif
set relPos.z=relPos.z-.1*d
endif
set d = relPos.length()
set aiSide = vector.createProduct(aiUp,ai.vel)
call aiSide.setLength(1)
//set aiSide = vector.create(0,1,0).rotateByQuaternion(ai.orient)
// Andere Technik verfolgen, wenn die AI schon hinter dem Ziel ist, dann eher in XY-Ebene drehen
set v = ai.angVel.copy().rotateByQuaternionInv(ai.orient)
set r = 5.*(-4.*scalarProduct(relPos,aiSide)/d+v.x)
if r>1. then
set r=1.
elseif r<-1. then
set r=-1.
endif
set ai.ctrl.ruddersAim.x=r
set r = 15.*(3.*scalarProduct(relPos,aiUp)/d-v.y)
if r>1. then
set r=1.
elseif r<-1. then
set r=-1.
endif
set ai.ctrl.ruddersAim.y=r
set r = 10.*(scalarProduct(relPos,aiSide)/d+v.z)
if r>1. then
set r=1.
elseif r<-1. then
set r=-1.
endif
set ai.ctrl.ruddersAim.z=r
call v.destroy()
if onAttack then
if relPos.lengthSq()<4096*4096 then
if GetRandomInt(0,40)==0 then
call IssueImmediateOrder(playerController[aipid],"attack")
endif
endif
if relPos.lengthSq()<1500*1500 then
if GetRandomInt(0,40)==0 then
call IssueImmediateOrder(playerController[aipid],"attackonce")
endif
endif
endif
if ai.nearestMissileDist<1024 then
call IssueImmediateOrder(playerController[aipid],"holybolt")
endif
call aiUp.destroy()
call aiSide.destroy()
call relPos.destroy()
endfunction
function FireBomb takes object o returns nothing
local vector relPos
local vector pos
local vector accelvec
local vector velAtPos
local particle p
local real r
set o.ctrl.weaponShots3 = o.ctrl.weaponShots3 - 1
set relPos = vector.create(0,0,-2*o.c.modelScale)
call relPos.rotateByQuaternion(o.orient)
set pos = vector.createSum(relPos,o.pos)
set velAtPos = vector.createProduct(o.angVel,relPos).add(o.vel)
set p = particle.create(Player(0),BOMB,pos,velAtPos.copy())
set p.sourceObj = o
set p.targetObj = 0
set accelvec = vector.create(0,0,-5).rotateByQuaternion(o.orient)
set r = 89*bj_DEGTORAD
call MGIntercept(p,accelvec,r)
call accelvec.destroy()
set accelvec = vector.createDifference(velAtPos,p.vel).scale(p.c.mass)
call o.addImpulse(relPos,accelvec)
if p.targetObj!=0 then
set o.targ = p.targetObj
endif
call velAtPos.destroy()
call accelvec.destroy()
call relPos.destroy()
endfunction
function FireBullet takes object o returns nothing
local vector relPos
local vector pos
local vector accelvec
local vector velAtPos
local particle p
local real r
set o.ctrl.weaponShots1 = o.ctrl.weaponShots1 - 1
set relPos = o.c.posMG.copy()
if o.mgSlotA then
set relPos.y = -relPos.y
endif
set o.mgSlotA = not o.mgSlotA
call relPos.rotateByQuaternion(o.orient)
set pos = vector.createSum(relPos,o.pos)
set velAtPos = vector.createProduct(o.angVel,relPos).add(o.vel)
set p = particle.create(Player(0),BULLET,pos,velAtPos.copy())
set p.sourceObj = o
set p.targetObj = 0
set accelvec = o.c.velMG.copy().rotateByQuaternion(o.orient)
set r = o.c.MGMaxTurnDeg*bj_DEGTORAD
call MGIntercept(p,accelvec,r)
call accelvec.destroy()
set accelvec = vector.createDifference(velAtPos,p.vel).scale(p.c.mass)
call o.addImpulse(relPos,accelvec)
if p.targetObj!=0 then
set o.targ = p.targetObj
endif
call velAtPos.destroy()
call accelvec.destroy()
call relPos.destroy()
endfunction
function FireMissile takes object o returns nothing
local vector relPos
local vector pos
local vector accelvec
local vector velAtPos
local particle p
set o.ctrl.weaponShots2 = o.ctrl.weaponShots2 - 1
set relPos = o.c.posMissiles.copy()
set accelvec = o.c.velMissiles.copy()
if o.missileSlotA then
set relPos.y = -relPos.y
set accelvec.y = -accelvec.y
endif
set o.missileSlotA = not o.missileSlotA
call relPos.rotateByQuaternion(o.orient)
set pos = vector.createSum(relPos,o.pos)
call accelvec.rotateByQuaternion(o.orient)
set velAtPos = vector.createProduct(o.angVel,relPos)
call velAtPos.add(o.vel)
call accelvec.add(velAtPos)
set p = particle.create(Player(0),MISSILE,pos,accelvec)
set p.sourceObj = o
set p.targetObj = GetMissileTarget(p)
if p.targetObj!=0 then
set p.targetObj.followingMissiles = p.targetObj.followingMissiles+1
set o.targ = p.targetObj
endif
set accelvec = vector.createDifference(velAtPos,p.vel)
call accelvec.scale(p.c.mass)
call o.addImpulse(relPos,accelvec)
call velAtPos.destroy()
call relPos.destroy()
call accelvec.destroy()
endfunction
function FireFlares takes object o returns nothing
local vector relPos
local vector pos
local vector accelvec
local vector velAtPos
local particle p
local particle flare1
local particle flare2
set o.ctrl.flareShots = o.ctrl.flareShots - 1
set relPos = o.c.posFlares.copy()
set accelvec = o.c.velFlares.copy()
call relPos.rotateByQuaternion(o.orient)
set pos = vector.createSum(relPos,o.pos)
call accelvec.rotateByQuaternion(o.orient).randomise(.2)
set velAtPos = vector.createProduct(o.angVel,relPos).add(o.vel)
call accelvec.add(velAtPos)
set p = particle.create(Player(0),FLARE,pos,accelvec)
set flare1 = p
set p.sourceObj = o
set p.targetObj = 0
set accelvec = vector.createDifference(velAtPos,p.vel).scale(p.c.mass)
call o.addImpulse(relPos,accelvec)
call velAtPos.destroy()
call relPos.destroy()
call accelvec.destroy()
set relPos = o.c.posFlares.copy()
set accelvec = o.c.velFlares.copy()
set relPos.y = -relPos.y
set accelvec.y = -accelvec.y
call relPos.rotateByQuaternion(o.orient)
set pos = vector.createSum(relPos,o.pos)
call accelvec.rotateByQuaternion(o.orient).randomise(.2)
set velAtPos = vector.createProduct(o.angVel,relPos).add(o.vel)
call accelvec.add(velAtPos)
set p = particle.create(Player(0),FLARE,pos,accelvec)
set flare2 = p
set p.sourceObj = o
set p.targetObj = 0
set accelvec = vector.createDifference(velAtPos,p.vel).scale(p.c.mass)
call o.addImpulse(relPos,accelvec)
call velAtPos.destroy()
call relPos.destroy()
call accelvec.destroy()
set o.flareDistraction = 1.
call physParticleList.toFirst()
loop
exitwhen physParticleList.outOfList()
set p = physParticleList.getContent()
if p.targetObj==o then
if GetRandomInt(0,1)==0 then
set p.targetP = flare1
else
set p.targetP = flare2
endif
set p.targetObj=0
endif
call physParticleList.toNext()
endloop
set o.followingMissiles = 0
endfunction
function UpdateMultiboard takes object o returns nothing
local integer pid = GetPlayerId(GetOwningPlayer(o.u))
local real r2 = PHYS_GRAVITY*(8-5*o.pos.z/3800.)
local vector accelvec
local real r
local string s
set o.accel.z = o.accel.z+PHYS_GRAVITY
call o.setWingClouds(o.accel.lengthSq()>r2*r2)
set r = bj_PI/8+Atan2(o.orient.w*o.orient.z + o.orient.z*o.orient.w + o.orient.y*o.orient.x + o.orient.x*o.orient.y,o.orient.w*o.orient.w - o.orient.z*o.orient.z - o.orient.y*o.orient.y + o.orient.x*o.orient.x)
if r<0 then
set r = r+2*bj_PI
endif
set r = 4*r/bj_PI
call MultiboardSetItemValueFast( playerBoard[pid], 1, 1, I2S(Round(o.vel.length()*.8*3.6*.1)*10)+" km/h ("+PHYS_DIRECTION_STRINGS[R2I(r)]+")" )
call MultiboardSetItemValueFast( playerBoard[pid], 1, 2, I2S(Round(o.pos.z*.8*.1)*10)+" m" )
set accelvec = vector.createDifference(o.vel,o.velOld)
call o.accelOld.setVecScaled(accelvec,.2/PHYS_TIME_STEP)
set accelvec.z = accelvec.z+PHYS_GRAVITY*PHYS_TIME_STEP*5.
set r = accelvec.length()/(PHYS_GRAVITY*PHYS_TIME_STEP*5.)
call accelvec.destroy()
call o.velOld.setVec(o.vel)
set r = r + 0.05
call MultiboardSetItemValueFast( playerBoard[pid], 1, 3, I2S(R2I(r))+"."+I2S(R2I((r-R2I(r))*10.))+" G" )
set r2 = o.vel.length()
if r2>0 then
set accelvec = vector.create(0,0,1)
call accelvec.rotateByQuaternion(o.orient)
set r = -Asin(scalarProduct(accelvec,o.vel)/r2)*bj_RADTODEG
call accelvec.destroy()
else
set r = 0
endif
call MultiboardSetItemValueFast( playerBoard[pid], 1, 4, I2S(R2I(r))+" °" )
set r = bj_PI/8+Atan2(physWind.y,physWind.x)
if r<0 then
set r = r+2*bj_PI
endif
set r = 4*r/bj_PI
call MultiboardSetItemValueFast( playerBoard[pid], 1, 5, I2S(Round(physWind.length()*.8*3.6*.1)*10)+" km/h ("+PHYS_DIRECTION_STRINGS[R2I(r)]+")" )
call MultiboardSetItemValueFast( playerBoard[pid], 1, 7, I2S(R2I(o.ctrl.enginePower*100.))+"%" )
call MultiboardSetItemValueFast( playerBoard[pid], 1, 8, I2S(R2I(o.ctrl.landingGearPos*100.))+"%" )
call MultiboardSetItemValueFast( playerBoard[pid], 1, 9, I2S(R2I(o.ctrl.brakes*100.))+"%" )
call MultiboardSetItemValueFast( playerBoard[pid], 1, 10, I2S(R2I(o.ctrl.rudders.x*100.))+"%")
call MultiboardSetItemValueFast( playerBoard[pid], 1, 11, I2S(R2I(o.ctrl.rudders.y*100.))+"%")
call MultiboardSetItemValueFast( playerBoard[pid], 1, 12, I2S(R2I(o.ctrl.rudders.z*100.))+"%")
if o.followingMissiles==0 then
call MultiboardSetItemValueFast( playerBoard[pid], 0, 14, " No Missile" )
call MultiboardSetItemValueFast( playerBoard[pid], 1, 14, "Safe" )
else
if physInterfaceAlertRed then
set s = " |cffff0000"
else
set s = " |cffffffff"
endif
if o.followingMissiles==1 then
call MultiboardSetItemValueFast( playerBoard[pid], 0, 14, s+"1 Missile|r" )
else
call MultiboardSetItemValueFast( playerBoard[pid], 0, 14, s+I2S(o.followingMissiles)+" Missiles|r" )
endif
call MultiboardSetItemValueFast( playerBoard[pid], 1, 14, s+I2S(Round(o.nearestMissileDist*.8*.1)*10)+" m|r" )
endif
set o.nearestMissileDist=100000000.
endfunction
function UpdateControlVariables takes object o returns nothing
local object first = physObjectList.first.content
local integer pid = GetPlayerId(GetOwningPlayer(o.u))
local real r
local real state
local real controlScale = o.c.speedFullRudderPitch*o.c.speedFullRudderPitch/(o.vel.lengthSq()+1)
if controlScale>1. then
set controlScale=1.
else
set controlScale=SquareRoot(controlScale)
endif
if not playerLimitRudders[pid] then
set controlScale = 1.
endif
if o.broken then
set r=0
else
set r=o.ctrl.enginePowerAim
endif
if o.ctrl.enginePower>r then
set o.ctrl.enginePower = o.ctrl.enginePower-.25*PHYS_TIME_STEP
if o.ctrl.enginePower<r then
set o.ctrl.enginePower = r
endif
elseif o.ctrl.enginePower<r then
set o.ctrl.enginePower = o.ctrl.enginePower+.25*PHYS_TIME_STEP
if o.ctrl.enginePower>r then
set o.ctrl.enginePower = r
endif
endif
set o.engineSound.pitch = o.ctrl.enginePower*o.c.engineSoundPitch
set r = o.ctrl.ruddersAim.x
if r>controlScale then
set r = controlScale
elseif r<-controlScale then
set r = -controlScale
endif
set state = o.ctrl.rudders.x
if state>r then
set state = state-5.*controlScale*PHYS_TIME_STEP
if state<r then
set state = r
endif
elseif state<r then
set state = state+5.*controlScale*PHYS_TIME_STEP
if state>r then
set state = r
endif
endif
set o.ctrl.ruddersVel.x = (state-o.ctrl.rudders.x)/PHYS_TIME_STEP
set o.ctrl.rudders.x = state
set r = o.ctrl.ruddersAim.y
if r>controlScale then
set r = controlScale
elseif r<-controlScale then
set r = -controlScale
endif
set state = o.ctrl.rudders.y
if state>r then
set state = state-5.*controlScale*PHYS_TIME_STEP
if state<r then
set state = r
endif
elseif state<r then
set state = state+5.*controlScale*PHYS_TIME_STEP
if state>r then
set state = r
endif
endif
set o.ctrl.ruddersVel.y = (state-o.ctrl.rudders.y)/PHYS_TIME_STEP
set o.ctrl.rudders.y = state
set r = o.ctrl.ruddersAim.z
if r>controlScale then
set r = controlScale
elseif r<-controlScale then
set r = -controlScale
endif
set state = o.ctrl.rudders.z
if state>r then
set state = state-5.*controlScale*PHYS_TIME_STEP
if state<r then
set state = r
endif
elseif state<r then
set state = state+5.*controlScale*PHYS_TIME_STEP
if state>r then
set state = r
endif
endif
set o.ctrl.ruddersVel.z = (state-o.ctrl.rudders.z)/PHYS_TIME_STEP
set o.ctrl.rudders.z = state
if o.ctrl.wantLandingGears then
if o.landingGears==null then
call o.addLandingGears()
endif
set state = o.ctrl.landingGearPos+PHYS_TIME_STEP
if state>1. then
set state = 1.
endif
else
if o.landingGears!=null then
call DestroyEffect(o.landingGears)
set o.landingGears=null
endif
set state = o.ctrl.landingGearPos-PHYS_TIME_STEP
if state<0. then
set state = 0.
endif
endif
set o.ctrl.landingGearVel=(state-o.ctrl.landingGearPos)/PHYS_TIME_STEP
set o.ctrl.landingGearPos=state
endfunction
function ObjectControl takes object o returns nothing
local integer pid = GetPlayerId(GetOwningPlayer(o.u))
local vector angVelRel
local real r
if playerAIControl[pid] then
call AIFollow(o,o.targ)
else
set o.ctrl.ruddersAim.x = 0.
if arrowRightPressed(pid) then
set o.ctrl.ruddersAim.x = o.ctrl.ruddersAim.x-1
endif
if arrowLeftPressed(pid) then
set o.ctrl.ruddersAim.x = o.ctrl.ruddersAim.x+1
endif
set o.ctrl.ruddersAim.y = 0.
if arrowUpPressed(pid) then
set o.ctrl.ruddersAim.y = o.ctrl.ruddersAim.y+1
endif
if arrowDownPressed(pid) then
set o.ctrl.ruddersAim.y = o.ctrl.ruddersAim.y-1
endif
set o.ctrl.ruddersAim.z = o.ctrl.zRotate
if playerAssistance[pid] then
//set r = 10*PHYS_GRAVITY/(o.vel.length()+1)
//set r = (o.ctrl.ruddersAim.x*bj_PI*.75+angVelRel.x)
set r = o.vel.lengthSq()
if r>50*50 then
set r=50/SquareRoot(r)
else
set r = 1
endif
set angVelRel = o.angVel.copy().rotateByQuaternionInv(o.orient)
set o.ctrl.ruddersAim.x = 5*(o.ctrl.ruddersAim.x*bj_PI*.75+angVelRel.x)*r
set o.ctrl.ruddersAim.y = 15*(o.ctrl.ruddersAim.y*bj_PI*.75-angVelRel.y)*r
set o.ctrl.ruddersAim.z = 10*(o.ctrl.ruddersAim.z*bj_PI*.75+angVelRel.z)*r
if o.ctrl.ruddersAim.x>1 then
set o.ctrl.ruddersAim.x=1
elseif o.ctrl.ruddersAim.x<-1 then
set o.ctrl.ruddersAim.x=-1
endif
if o.ctrl.ruddersAim.y>1 then
set o.ctrl.ruddersAim.y=1
elseif o.ctrl.ruddersAim.y<-1 then
set o.ctrl.ruddersAim.y=-1
endif
if o.ctrl.ruddersAim.z>1 then
set o.ctrl.ruddersAim.z=1
elseif o.ctrl.ruddersAim.z<-1 then
set o.ctrl.ruddersAim.z=-1
endif
call angVelRel.destroy()
endif
endif
call UpdateControlVariables(o)
endfunction
endlibrary
//TESH.scrollpos=116
//TESH.alwaysfold=0
library physMain initializer physInit uses physHelpers
globals
list physObjectList
list physParticleList
object physCtrlObject
integer physInterfaceRefresh = 0
boolean physInterfaceAlertRed = false
vector physWind
string array PHYS_DIRECTION_STRINGS
timer physMainLoopTimer
endglobals
function physLoop_Part1 takes nothing returns nothing
local object o
call RegisterThread("physLoop - Part 1")
if physInterfaceRefresh==0 then
set physInterfaceAlertRed = not physInterfaceAlertRed
endif
// Simulate Wind
if physWind.length()>PHYS_WIND_PERMANENT_POWER then
call physWind.scale(.99)
else
call physWind.scale(1.02)
endif
call physWind.addXYZ(PHYS_WIND_GUST_POWER*GetRandomReal(-.1,.1),PHYS_WIND_GUST_POWER*GetRandomReal(-.1,.1),PHYS_WIND_GUST_POWER*GetRandomReal(-.03,.03))
// Calculate forces and predicted positions/velocities
call physObjectList.toFirst()
loop
exitwhen physObjectList.outOfList()
set o = physObjectList.getContent()
set o.flareDistraction = o.flareDistraction-PHYS_TIME_STEP
call ObjectControl(o)
// Forces
set o.accel.z = o.accel.z-PHYS_GRAVITY
if o.c.simulationTrig!=null then
set physCtrlObject = o
call TriggerEvaluate(o.c.simulationTrig)
endif
if scalarProduct(o.angAccel,o.angAccel)>16.*16. then
call o.angAccel.setLength(16.)
endif
if scalarProduct(o.accel,o.accel)>800.*800. then
call o.accel.setLength(800.)
endif
// Temp
call o.velTmp.setVec(o.vel).addScaled(o.accel,PHYS_TIME_STEP)
call o.angVelTmp.setVec(o.angVel).addScaled(o.angAccel,PHYS_TIME_STEP)
call o.posTmp.setVec(o.pos).addScaled(o.velTmp,PHYS_TIME_STEP)
call o.orientTmp.setQuat(o.orient)
call o.orientTmp.rotateByVectorScaled(o.angVelTmp,PHYS_TIME_STEP)
set o.firstCollTime = 1000.
call physObjectList.toNext()
endloop
call collisionDetection()
call collisionResponsePrepare()
call collisionResponse(2,true)
set physInterfaceRefresh = physInterfaceRefresh + 1
if physInterfaceRefresh>=5 then
set physInterfaceRefresh = 0
endif
// Add acceleration to speed, reset temporary acceleration variables
call physObjectList.toFirst()
loop
exitwhen physObjectList.outOfList()
set o = physObjectList.getContent()
call o.vel.addScaled(o.accel,PHYS_TIME_STEP)
call o.angVel.addScaled(o.angAccel,PHYS_TIME_STEP)
if physInterfaceRefresh==0 then
call UpdateMultiboard(o)
endif
call o.accel.setXYZ(0,0,0)
call o.angAccel.setXYZ(0,0,0)
call physObjectList.toNext()
endloop
call UnregisterThread("physLoop - Part 1")
endfunction
function physLoop takes nothing returns nothing
local object o
local particle p
local vector angMom = vector.create(0,0,0)
local real r
call ReleaseDebugDots()
call ExecuteFunc("physLoop_Part1")
call collisionResponse(1,false)
call collisionResponseDestroy()
call RegisterThread("physLoop - Part 2")
// Calculate new positions
call physObjectList.toFirst()
loop
exitwhen physObjectList.outOfList()
set o = physObjectList.getContent()
// Translate
call angMom.setTransformedByMatrix(o.angVel,o.inertiaWorldInv)
if o.firstCollTime<1. and o.firstCollTime>0. then
call o.pos.addScaled(o.velTmp,o.firstCollTime)
else
set o.firstCollTime = 0.
endif
call o.pos.addScaled(o.vel,PHYS_TIME_STEP-o.firstCollTime)
call o.orient.rotateByVectorScaled(o.angVel,PHYS_TIME_STEP-o.firstCollTime)
call o.orient.normalise()
call o.inertiaWorld.destroy()
call o.inertiaWorldInv.destroy()
set o.inertiaWorld = o.c.inertia.copy()
call o.inertiaWorld.rotateByQuaternion(o.orient)
set o.inertiaWorldInv = o.c.inertiaInv.copy()
call o.inertiaWorldInv.rotateByQuaternion(o.orient)
//set o.inertiaWorldInv = o.inertiaWorld.copyInverted()
call o.angVel.setTransformedByMatrix(angMom,o.inertiaWorld)
if o.pos.x>PHYS_BOUND_MAX_X then
set o.pos.x = PHYS_BOUND_MIN_X+1.
endif
if o.pos.x<PHYS_BOUND_MIN_X then
set o.pos.x = PHYS_BOUND_MAX_X-1.
endif
if o.pos.y>PHYS_BOUND_MAX_Y then
set o.pos.y = PHYS_BOUND_MIN_Y+1.
endif
if o.pos.y<PHYS_BOUND_MIN_Y then
set o.pos.y = PHYS_BOUND_MAX_Y-1.
endif
if o.pos.z>PHYS_BOUND_MAX_Z then
set o.pos.z = PHYS_BOUND_MAX_Z
endif
call o.updateAnimation()
// Fire
if physInterfaceRefresh==0 then
if o.ctrl.weaponShots1>0 then
call FireBullet(o)
endif
if o.ctrl.weaponShots3>0 then
call FireBomb(o)
endif
if o.ctrl.flareShots>0 then
call FireFlares(o)
endif
endif
if o.ctrl.weaponShots2>0 then
call FireMissile(o)
endif
call physObjectList.toNext()
endloop
call angMom.destroy()
call physParticleList.toFirst()
loop
exitwhen physParticleList.outOfList()
set p = physParticleList.getContent()
if p.age!=0. then
if p.firstCollTime<1. and p.firstCollTime>0. then
call p.pos.addScaled(p.velTmp,o.firstCollTime)
else
set p.firstCollTime = 0.
endif
if p.age<=p.c.lifespan then
call p.pos.addScaled(p.vel,PHYS_TIME_STEP-p.firstCollTime)
endif
endif
set p.age = p.age + PHYS_TIME_STEP
set p.vel.z = p.vel.z - PHYS_GRAVITY*PHYS_TIME_STEP
if (p.targetObj!=0 or p.targetP!=0) and p.c.aim!=0. then
call MissileFollow(p)
elseif p.c.accel!=0. then
set r = p.vel.length()
if r!=0. then
call p.vel.scale((r+p.c.accel*PHYS_TIME_STEP)/r)
else
call p.vel.setXYZ(0,0,p.c.accel*PHYS_TIME_STEP)
endif
endif
if p.c.friction!=0. then
call p.vel.subtract(physWind).scale(Pow(1.-p.c.friction,GetVolumeDensity(p.pos.z)*PHYS_TIME_STEP)).add(physWind)
endif
call p.velTmp.setVec(p.vel)
if p.pos.x>PHYS_BOUND_MAX_X then
set p.pos.x = PHYS_BOUND_MIN_X
endif
if p.pos.x<PHYS_BOUND_MIN_X then
set p.pos.x = PHYS_BOUND_MAX_X
endif
if p.pos.y>PHYS_BOUND_MAX_Y then
set p.pos.y = PHYS_BOUND_MIN_Y
endif
if p.pos.y<PHYS_BOUND_MIN_Y then
set p.pos.y = PHYS_BOUND_MAX_Y
endif
if p.age>p.c.lifespan or (p.pos.z<WATER_HEIGHT and p.c.explodeInWater) then
call p.destroy()
call physParticleList.pop()
else
call p.updateAnimation()
call physParticleList.toNext()
endif
endloop
call SelectUnit(playerController[GetPlayerId(GetLocalPlayer())],true)
call UnregisterThread("physLoop - Part 2")
endfunction
function physInit takes nothing returns nothing
set physObjectList = list.create()
set physParticleList = list.create()
set physWind = vector.create(0,0,0)
set soundWind = physWind
set collisionList = list.create()
set physMainLoopTimer = CreateTimer()
set PHYS_DIRECTION_STRINGS[0] = "E"
set PHYS_DIRECTION_STRINGS[1] = "NE"
set PHYS_DIRECTION_STRINGS[2] = "N"
set PHYS_DIRECTION_STRINGS[3] = "NW"
set PHYS_DIRECTION_STRINGS[4] = "W"
set PHYS_DIRECTION_STRINGS[5] = "SW"
set PHYS_DIRECTION_STRINGS[6] = "S"
set PHYS_DIRECTION_STRINGS[7] = "SE"
call TimerStart(physMainLoopTimer,PHYS_TIME_STEP,true,function physLoop )
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library physProperties
globals
constant real PHYS_TIME_STEP = .04
constant real PHYS_GRAVITY = 12.5
constant real PHYS_AIR_DENSITY = .6144
constant real PHYS_WATER_DENSITY = 500.
constant real PHYS_BOUND_MIN_X = -15000.
constant real PHYS_BOUND_MAX_X = 15000.
constant real PHYS_BOUND_MIN_Y = -15000.
constant real PHYS_BOUND_MAX_Y = 15000.
constant real PHYS_BOUND_MIN_Z = -100.
constant real PHYS_BOUND_MAX_Z = 3800.
constant real PHYS_WIND_GUST_POWER = 15.
constant real PHYS_WIND_PERMANENT_POWER = 15.
constant real PHYS_MAX_OBJECT_SPEED = 1000.
constant boolean PHYS_BOUND_REPEAT = true
constant boolean PHYS_OBJECT_COLLISION = false
constant boolean PHYS_DISPLAY_FORCES = false
constant boolean PHYS_DISPLAY_COLLISIONPOINTS= false
endglobals
endlibrary
//TESH.scrollpos=94
//TESH.alwaysfold=0
library F22Lib initializer init uses physHelpers
globals
class F22
endglobals
private function Ctrl takes nothing returns nothing
local object o = physCtrlObject
local vector frictvec
local vector relPos
local vector accelvec
local real r
local real r2
// Front Wing
set frictvec = vector.create(0,0,1)
call frictvec.rotateAroundYAxis(-1*bj_DEGTORAD)
set relPos = vector.create(24*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,12)
// Main Wings
call relPos.setXYZ(-7*o.c.modelScale,-22*o.c.modelScale,0)
call o.addWing(relPos,frictvec,13)
if not o.broken then
call relPos.setXYZ(-7*o.c.modelScale,22*o.c.modelScale,0)
call o.addWing(relPos,frictvec,13)
endif
// Roll Rudders
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundYAxis(-o.ctrl.rudders.x*30*bj_DEGTORAD)
call relPos.setXYZ(-20*o.c.modelScale,-22*o.c.modelScale,0)
call o.addWing(relPos,frictvec,6)
set frictvec.z=-frictvec.z
call relPos.setXYZ(-20*o.c.modelScale,22*o.c.modelScale,0)
call o.addWing(relPos,frictvec,6)
// Height Rudders
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundYAxis((-o.ctrl.rudders.y*40+1)*bj_DEGTORAD)
if o.broken then
call frictvec.rotateAroundYAxis(10*bj_DEGTORAD)
endif
call relPos.setXYZ(-33*o.c.modelScale,-14*o.c.modelScale,0)
call o.addWing(relPos,frictvec,8)
call relPos.setXYZ(-33*o.c.modelScale,14*o.c.modelScale,0)
call o.addWing(relPos,frictvec,8)
// Side Rudders
call frictvec.setXYZ(0,1,0)
if not o.broken then
call relPos.setXYZ(31*o.c.modelScale,0,o.c.modelScale)
call o.addWing(relPos,frictvec,4)
endif
call frictvec.rotateAroundZAxis(o.ctrl.rudders.z*5*bj_DEGTORAD)
if o.broken then
call frictvec.rotateAroundZAxis(20*bj_DEGTORAD)
endif
call relPos.setXYZ(-21*o.c.modelScale,11*o.c.modelScale,5.5*o.c.modelScale)
call o.addWing(relPos,frictvec,5)
call relPos.setXYZ(-21*o.c.modelScale,-11*o.c.modelScale,5.5*o.c.modelScale)
call o.addWing(relPos,frictvec,5)
// Frontal Friction
call frictvec.setXYZ(1,0,0)
call o.addWing(VECTOR0,frictvec,1+1*o.ctrl.brakes)
if o.ctrl.landingGearPos!=0 then
call relPos.setXYZ(0,0,-4*o.c.modelScale)
call o.addWing(relPos,frictvec,1)
endif
call frictvec.destroy()
set r = -o.ctrl.rudders.y*20+o.ctrl.rudders.x*20
set r2= -o.ctrl.rudders.y*20-o.ctrl.rudders.x*20
if r>20 then
set r = 20
elseif r<-20 then
set r = -20
endif
if r2>20 then
set r2 = 20
elseif r2<-20 then
set r2 = -20
endif
call relPos.setXYZ(-27*o.c.modelScale,3.4,0)
set accelvec = vector.create(275*o.ctrl.enginePower,0,0)
call accelvec.rotateAroundYAxis(r*bj_DEGTORAD)
call accelvec.rotateByQuaternion(o.orient)
call relPos.rotateByQuaternion(o.orient)
call o.addForce(relPos,accelvec)
call relPos.setXYZ(-27*o.c.modelScale,-3.4,0)
call accelvec.setXYZ(275*o.ctrl.enginePower,0,0)
call accelvec.rotateAroundYAxis(r2*bj_DEGTORAD)
call accelvec.rotateByQuaternion(o.orient)
call relPos.rotateByQuaternion(o.orient)
call o.addForce(relPos,accelvec)
call relPos.destroy()
call accelvec.destroy()
endfunction
private function init takes nothing returns nothing
set F22 = class.create()
set F22.mass = 20.
set F22.inertia = matrix.create(375,0,0, 0,875,0, 0,0,875)
set F22.inertiaInv = F22.inertia.copyInverted()
set F22.modelName = "war3mapImported\\F22_base.mdx"
call F22.setElevator("war3mapImported\\F22_elev.mdx",vector.create(-27.6,0,.5),0,bj_DEGTORAD*40)
call F22.setEngineSound("war3mapImported\\engineJet.wav", 1, .6 )
call F22.setLandingGearsModel("war3mapImported\\Landing Gears.mdx","origin")
set F22.simulationCode = function Ctrl
set F22.unitType = 'h000'
set F22.cockpitCam = vector.create(24,0,9.5)
set F22.hitpoints = 100.
call F22.addCollisionPoint(BODY,vector.create(-13,33,.5))
call F22.addCollisionPoint(BODY,vector.create(-13,-33,.5))
call F22.addCollisionPoint(BODY,vector.create(52,0,0))
call F22.addCollisionPoint(BODY,vector.create(-24,14,15))
call F22.addCollisionPoint(BODY,vector.create(-24,-14,15))
call F22.addCollisionPoint(BODY,vector.create(-22,7.5,-4))
call F22.addCollisionPoint(BODY,vector.create(-22,-7.5,-4))
call F22.addCollisionPoint(BODY,vector.create(23.7,9,-4))
call F22.addCollisionPoint(BODY,vector.create(23.7,-9,-4))
call F22.addCollisionPoint(BODY,vector.create(32,0,7.3))
call F22.addCollisionPoint(ELEVATOR,vector.create(-10,23,0))
call F22.addCollisionPoint(ELEVATOR,vector.create(-10,-23,0))
call F22.addLandingGear(vector.create(29,0,-11),vector.create(0,0,10),vector.create(0,1,0),3)
call F22.addLandingGear(vector.create(-3,-15,-10),vector.create(0,0,9),vector.create(0,1,0),0)
call F22.addLandingGear(vector.create(-3,15,-10),vector.create(0,0,9),vector.create(0,1,0),0)
set F22.collshape = shape.create()
call F22.collshape.addNewBox(vector.create(-11,0,.5),vector.create(22,22,2),quaternion.createEuler(0,0,45*bj_DEGTORAD))
call F22.collshape.addNewBox(vector.create(17,0,.5),vector.create(9,9,4),quaternion.create(0,0,0,1))
call F22.collshape.addNewBox(vector.create(17,0,.5),vector.create(9,9,4),quaternion.create(0,0,0,1))
call F22.collshape.addNewBox(vector.create(34,0,.5),vector.create(15,4,4),quaternion.create(0,0,0,1))
call F22.collshape.addNewBox(vector.create(-34,15,.5),vector.create(6,6,2),quaternion.create(0,0,0,1))
call F22.collshape.addNewBox(vector.create(-34,-15,.5),vector.create(6,6,2),quaternion.create(0,0,0,1))
call F22.collshape.addNewBox(vector.create(-34,-15,.5),vector.create(6,6,2),quaternion.create(0,0,0,1))
call F22.collshape.addNewBox(vector.create(-21,10,8.5),vector.create(6,2,8),quaternion.createEuler(28*bj_DEGTORAD,0,0))
call F22.collshape.addNewBox(vector.create(-21,-10,8.5),vector.create(6,2,8),quaternion.createEuler(-28*bj_DEGTORAD,0,0))
call F22.collshape.addBoundingVolume(SHAPE_SPHERE)
set F22.cloud1PosStr = "hand left"
set F22.cloud2PosStr = "hand right"
set F22.cloud3PosStr = "head"
set F22.posMG = vector.create(51,0,-3.)
set F22.velMG = vector.create(1000,0,0)
set F22.MGMaxTurnDeg = 10
set F22.posMissiles = vector.create(1,13.5,-5.)
set F22.velMissiles = vector.create(10,10,-10)
set F22.posFlares = vector.create(0,0,0)
set F22.velFlares = vector.create(0,100,-10)
call F22.scaleVisual(.25)
set F22.speedFullRudderPitch = 135.
endfunction
endlibrary
//TESH.scrollpos=73
//TESH.alwaysfold=0
library MIG29Lib initializer init uses physHelpers
globals
class MIG29
endglobals
private function Ctrl takes nothing returns nothing
local object o = physCtrlObject
local vector frictvec
local vector relPos
local vector accelvec
// Front Wing
set frictvec = vector.create(0,0,1)
call frictvec.rotateAroundYAxis(-1*bj_DEGTORAD)
set relPos = vector.create(30*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,5.5)
// Main Wings
call relPos.setXYZ(-9*o.c.modelScale,-20*o.c.modelScale,0)
call o.addWing(relPos,frictvec,6.8)
if not o.broken then
call relPos.setXYZ(-9*o.c.modelScale,20*o.c.modelScale,0)
call o.addWing(relPos,frictvec,6.8)
endif
// Roll Rudders
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundYAxis(-o.ctrl.rudders.x*30*bj_DEGTORAD)
call relPos.setXYZ(-14*o.c.modelScale,-25*o.c.modelScale,0)
call o.addWing(relPos,frictvec,3)
set frictvec.z=-frictvec.z
call relPos.setXYZ(-14*o.c.modelScale,25*o.c.modelScale,0)
call o.addWing(relPos,frictvec,3)
// Height Rudders
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundYAxis((-o.ctrl.rudders.y*40+1)*bj_DEGTORAD)
if o.broken then
call frictvec.rotateAroundYAxis(10*bj_DEGTORAD)
endif
call relPos.setXYZ(-35*o.c.modelScale,-15*o.c.modelScale,0)
call o.addWing(relPos,frictvec,3)
call relPos.setXYZ(-35*o.c.modelScale,15*o.c.modelScale,0)
call o.addWing(relPos,frictvec,3)
// Side Rudders
call frictvec.setXYZ(0,1,0)
if not o.broken then
call relPos.setXYZ(22*o.c.modelScale,0,2*o.c.modelScale)
call o.addWing(relPos,frictvec,5)
endif
call frictvec.rotateAroundZAxis(o.ctrl.rudders.z*5*bj_DEGTORAD)
if o.broken then
call frictvec.rotateAroundZAxis(20*bj_DEGTORAD)
endif
call relPos.setXYZ(-25*o.c.modelScale,10*o.c.modelScale,2.5*o.c.modelScale)
call o.addWing(relPos,frictvec,4)
call relPos.setXYZ(-25*o.c.modelScale,-10*o.c.modelScale,2.5*o.c.modelScale)
call o.addWing(relPos,frictvec,4)
// Frontal Friction
call frictvec.setXYZ(1,0,0)
call o.addWing(VECTOR0,frictvec,.4+.4*o.ctrl.brakes)
if o.ctrl.landingGearPos!=0 then
call relPos.setXYZ(0,0,-4*o.c.modelScale)
call o.addWing(relPos,frictvec,.4)
endif
call frictvec.destroy()
set accelvec = vector.create(250*o.ctrl.enginePower,0,0)
call accelvec.rotateByQuaternion(o.orient)
call relPos.rotateByQuaternion(o.orient)
call o.addForce(VECTOR0,accelvec)
call relPos.destroy()
call accelvec.destroy()
endfunction
private function init takes nothing returns nothing
set MIG29 = class.create()
set MIG29.mass = 16.
set MIG29.inertia = matrix.create(350,0,0, 0,800,0, 0,0,800)
set MIG29.inertiaInv = MIG29.inertia.copyInverted()
set MIG29.modelName = "war3mapImported\\MIG29_base.mdx"
call MIG29.setElevator("war3mapImported\\MIG29_elev.mdx",vector.create(-23.5*1.2,0,.6*1.2),0,bj_DEGTORAD*40)
call MIG29.setEngineSound("war3mapImported\\engineJet.wav", 1, .5 )
call MIG29.setLandingGearsModel("war3mapImported\\Landing Gears.mdx","origin")
set MIG29.simulationCode = function Ctrl
set MIG29.unitType = 'h000'
set MIG29.cockpitCam = vector.create(24,0,9.5)
set MIG29.hitpoints = 100.
call MIG29.addCollisionPoint(BODY,vector.create(12.8,-7.3,-5))
call MIG29.addCollisionPoint(BODY,vector.create(12.8,7.3,-5))
call MIG29.addCollisionPoint(BODY,vector.create(-32,7.3,-3.5))
call MIG29.addCollisionPoint(BODY,vector.create(-32,-7.3,-3.5))
call MIG29.addCollisionPoint(BODY,vector.create(52.5,0,.2))
call MIG29.addCollisionPoint(BODY,vector.create(27.6,0,9.4))
call MIG29.addCollisionPoint(BODY,vector.create(-20,33,0))
call MIG29.addCollisionPoint(BODY,vector.create(-20,-33,0))
call MIG29.addCollisionPoint(BODY,vector.create(-31.5,11,17.2))
call MIG29.addCollisionPoint(BODY,vector.create(-31.5,-11,17.2))
call MIG29.addCollisionPoint(ELEVATOR,vector.create(-12.6,-21.2,-1.2))
call MIG29.addCollisionPoint(ELEVATOR,vector.create(-12.6,21.2,-1.2))
call MIG29.addLandingGear(vector.create(29,0,-11),vector.create(0,0,10),vector.create(0,1,0),3)
call MIG29.addLandingGear(vector.create(-3,-15,-10),vector.create(0,0,9),vector.create(0,1,0),0)
call MIG29.addLandingGear(vector.create(-3,15,-10),vector.create(0,0,9),vector.create(0,1,0),0)
set MIG29.collshape = shape.create()
call MIG29.collshape.addNewBox(vector.create(0,0,.5),vector.create(11,11,2),quaternion.createEuler(0,0,45*bj_DEGTORAD))
call MIG29.collshape.addNewBoxBetween(vector.create(-31.5,9,-5),vector.create(19.5,-9,2),quaternion.create(0,0,0,1))
call MIG29.collshape.addNewBoxBetween(vector.create(46,3,-1),vector.create(7,-3,7),quaternion.create(0,0,0,1))
call MIG29.collshape.addNewBoxBetween(vector.create(-33,11,15),vector.create(-21,9,2),quaternion.create(0,0,0,1))
call MIG29.collshape.addNewBoxBetween(vector.create(-33,-11,15),vector.create(-21,-9,2),quaternion.create(0,0,0,1))
call MIG29.collshape.addNewBox(vector.create(-33,16,1),vector.create(5,5,2),quaternion.create(0,0,0,1))
call MIG29.collshape.addNewBox(vector.create(-33,-16,1),vector.create(5,5,2),quaternion.create(0,0,0,1))
call MIG29.collshape.addBoundingVolume(SHAPE_SPHERE)
set MIG29.cloud1PosStr = "hand left"
set MIG29.cloud2PosStr = "hand right"
set MIG29.cloud3PosStr = "head"
set MIG29.posMG = vector.create(51,0,-3.)
set MIG29.velMG = vector.create(1000,0,0)
set MIG29.MGMaxTurnDeg = 10
set MIG29.posMissiles = vector.create(1,13.5,-5.)
set MIG29.velMissiles = vector.create(10,10,-10)
set MIG29.posFlares = vector.create(0,0,0)
set MIG29.velFlares = vector.create(0,100,-10)
call MIG29.scaleVisual(.25/1.2)
set MIG29.speedFullRudderPitch = 170.
endfunction
endlibrary
//TESH.scrollpos=75
//TESH.alwaysfold=0
library A10Lib initializer init uses physHelpers
globals
class A10
endglobals
private function Ctrl takes nothing returns nothing
local object o = physCtrlObject
local vector frictvec
local vector relPos
local vector accelvec
// Front Wing
set frictvec = vector.create(0,0,1)
call frictvec.rotateAroundYAxis((-3.5-3*o.ctrl.landingGearPos)*bj_DEGTORAD)
set relPos = vector.create(23*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,4)
call relPos.setXYZ(-23*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,4)
// Main Wings
if not o.broken then
call relPos.setXYZ(2.2*o.c.modelScale,-24*o.c.modelScale,-3*o.c.modelScale)
call o.addWing(relPos,frictvec,9)
endif
call relPos.setXYZ(2.2*o.c.modelScale,24*o.c.modelScale,-3*o.c.modelScale)
call o.addWing(relPos,frictvec,9)
// Roll Rudders
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundYAxis(-o.ctrl.rudders.x*30*bj_DEGTORAD)
call relPos.setXYZ(-3*o.c.modelScale,-24*o.c.modelScale,-3*o.c.modelScale)
call o.addWing(relPos,frictvec,4)
set frictvec.z=-frictvec.z
call relPos.setXYZ(-3*o.c.modelScale,24*o.c.modelScale,-3*o.c.modelScale)
call o.addWing(relPos,frictvec,4)
// Height Rudders
call frictvec.setXYZ(0,0,1)
call relPos.setXYZ(-36*o.c.modelScale,0,.5*o.c.modelScale)
call o.addWing(relPos,frictvec,2)
call frictvec.rotateAroundYAxis(-(o.ctrl.rudders.y*45-1)*bj_DEGTORAD)
if o.broken then
call frictvec.rotateAroundYAxis(-10*bj_DEGTORAD)
endif
call o.addWing(relPos,frictvec,2)
// Side Rudders
call frictvec.setXYZ(0,1,0)
call relPos.setXYZ(20*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,4)
call relPos.setXYZ(-20*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,2)
call frictvec.rotateAroundZAxis(o.ctrl.rudders.z*5*bj_DEGTORAD)
if o.broken then
call frictvec.rotateAroundZAxis(-10*bj_DEGTORAD)
endif
call relPos.setXYZ(-34*o.c.modelScale,14*o.c.modelScale,0)
call o.addWing(relPos,frictvec,3)
call relPos.setXYZ(-34*o.c.modelScale,-14*o.c.modelScale,0)
call o.addWing(relPos,frictvec,3)
// Frontal Friction
call frictvec.setXYZ(1,0,0)
call o.addWing(VECTOR0,frictvec,.6+o.ctrl.brakes*.6)
if o.ctrl.landingGearPos!=0 then
call relPos.setXYZ(0,0,-4*o.c.modelScale)
call o.addWing(relPos,frictvec,.3)
endif
call relPos.destroy()
call frictvec.destroy()
set accelvec = vector.create(150*o.ctrl.enginePower,0,0)
call accelvec.rotateByQuaternion(o.orient)
call o.addForce(VECTOR0,accelvec)
call accelvec.destroy()
endfunction
private function init takes nothing returns nothing
set A10 = class.create()
set A10.mass = 15.
set A10.inertia = matrix.create(188,0,0, 0,375,0, 0,0,562)
set A10.inertiaInv = A10.inertia.copyInverted()
set A10.modelName = "war3mapImported\\A10_base.mdx"
call A10.setElevator("war3mapImported\\A10_elev.mdx",vector.create(-35.3,0,.55),0,bj_DEGTORAD*45)
call A10.setEngineSound("war3mapImported\\engineJet.wav", 1, .4 )
call A10.setLandingGearsModel("war3mapImported\\Landing Gears.mdx","foot")
set A10.simulationCode = function Ctrl
set A10.unitType = 'h000'
set A10.cockpitCam = vector.create(293,0,43)
set A10.hitpoints = 200.
call A10.addCollisionPoint(BODY,vector.create(-3,45,-.5))
call A10.addCollisionPoint(BODY,vector.create(-3,-45,-.5))
call A10.addCollisionPoint(BODY,vector.create(-31,14,-3))
call A10.addCollisionPoint(BODY,vector.create(-31,-14,-3))
call A10.addCollisionPoint(BODY,vector.create(30,0,-4.2))
call A10.addCollisionPoint(BODY,vector.create(-38,0,-2.5))
call A10.addCollisionPoint(BODY,vector.create(44,0,-1))
call A10.addCollisionPoint(BODY,vector.create(27,0,8))
call A10.addCollisionPoint(BODY,vector.create(-37,14,11))
call A10.addCollisionPoint(BODY,vector.create(-37,-14,11))
call A10.addLandingGear(vector.create(29,0,-13),vector.create(0,0,10),vector.create(0,1,0),5)
call A10.addLandingGear(vector.create(-3,-15,-12),vector.create(0,0,9),vector.create(0,1,0),0)
call A10.addLandingGear(vector.create(-3,15,-12),vector.create(0,0,9),vector.create(0,1,0),0)
set A10.collshape = shape.create()
call A10.collshape.addNewBox(vector.create(-4,0,-.7),vector.create(8,45,2),quaternion.create(0,0,0,1))
call A10.collshape.addNewBox(vector.create(1,0,1.3),vector.create(40,3.7,5.5),quaternion.create(0,0,0,1))
call A10.collshape.addNewBox(vector.create(-34,0,.6),vector.create(4,14,2),quaternion.create(0,0,0,1))
call A10.collshape.addNewBox(vector.create(-34,14.5,4.4),vector.create(5.5,2,6.5),quaternion.create(0,0,0,1))
call A10.collshape.addNewBox(vector.create(-34,-14.5,4.4),vector.create(5.5,2,6.5),quaternion.create(0,0,0,1))
call A10.collshape.addNewCylinder(vector.create(-17,7,4),4.3,8,quaternion.createEuler(0,90*bj_DEGTORAD,0))
call A10.collshape.addNewCylinder(vector.create(-17,-7,4),4.3,8,quaternion.createEuler(0,90*bj_DEGTORAD,0))
call A10.collshape.addBoundingVolume(SHAPE_BOX)
set A10.cloud1PosStr = "weapon left"
set A10.cloud2PosStr = "weapon right"
set A10.cloud3PosStr = "chest"
set A10.posMG = vector.create(42.5,0,-3.5)
set A10.velMG = vector.create(1000,0,0)
set A10.MGMaxTurnDeg = 10
set A10.posMissiles = vector.create(1,14.0,-5.)
set A10.velMissiles = vector.create(10,0,-15)
set A10.posFlares = vector.create(0,0,0)
set A10.velFlares = vector.create(0,100,-10)
call A10.scaleVisual(.25)
set A10.speedFullRudderPitch = 100.
endfunction
endlibrary
//TESH.scrollpos=66
//TESH.alwaysfold=0
library B2Lib initializer init uses physHelpers
globals
class B2
endglobals
private function Ctrl takes nothing returns nothing
local object o = physCtrlObject
local vector frictvec
local vector relPos
local vector accelvec
// Main Wing
set frictvec = vector.create(0,0,1)
call frictvec.rotateAroundYAxis((-.5-1.5*o.ctrl.landingGearPos)*bj_DEGTORAD)
set relPos = vector.create(16*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,60)
call relPos.setXYZ(5*o.c.modelScale,23*o.c.modelScale,0)
call o.addWing(relPos,frictvec,45)
call relPos.setXYZ(5*o.c.modelScale,-23*o.c.modelScale,0)
call o.addWing(relPos,frictvec,45)
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundYAxis(-.5*bj_DEGTORAD)
call relPos.setXYZ(-12*o.c.modelScale,23*o.c.modelScale,0)
call o.addWing(relPos,frictvec,45)
call relPos.setXYZ(-12*o.c.modelScale,-23*o.c.modelScale,0)
call o.addWing(relPos,frictvec,45)
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundYAxis(o.ctrl.rudders.x*15*bj_DEGTORAD)
call relPos.setXYZ(-10*o.c.modelScale,50*o.c.modelScale,0)
call o.addWing(relPos,frictvec,21)
set frictvec.z=-frictvec.z
call relPos.setXYZ(-10*o.c.modelScale,-50*o.c.modelScale,0)
call o.addWing(relPos,frictvec,21)
// Height Rudders
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundYAxis(-o.ctrl.rudders.y*30*bj_DEGTORAD)
call relPos.setXYZ(-14*o.c.modelScale,-20*o.c.modelScale,0*o.c.modelScale)
call o.addWing(relPos,frictvec,7)
call relPos.setXYZ(-14*o.c.modelScale,20*o.c.modelScale,0*o.c.modelScale)
call o.addWing(relPos,frictvec,7)
// Side Rudders
call frictvec.setXYZ(0,1,0)
call relPos.setXYZ(10*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,4)
call relPos.setXYZ(-20*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,4)
// Frontal Friction
call frictvec.setXYZ(1,0,0)
call o.addWing(VECTOR0,frictvec,1.6+o.ctrl.brakes*3.2)
if o.ctrl.rudders.z>0. then
call relPos.setXYZ(-20*o.c.modelScale,-60*o.c.modelScale,0)
call o.addWing(relPos,frictvec,o.ctrl.rudders.z)
elseif o.ctrl.rudders.z<0. then
call relPos.setXYZ(-20*o.c.modelScale,60*o.c.modelScale,0)
call o.addWing(relPos,frictvec,-o.ctrl.rudders.z)
endif
if o.ctrl.landingGearPos!=0 then
call relPos.setXYZ(0,0,-4*o.c.modelScale)
call o.addWing(relPos,frictvec,.8)
endif
call relPos.destroy()
call frictvec.destroy()
set accelvec = vector.create(1000*o.ctrl.enginePower,0,0)
call accelvec.rotateByQuaternion(o.orient)
call o.addForce(VECTOR0,accelvec)
call accelvec.destroy()
endfunction
private function init takes nothing returns nothing
set B2 = class.create()
set B2.mass = 100.
set B2.inertia = matrix.create(11250,0,0, 0,4700,0, 0,0,11250)
set B2.inertiaInv = B2.inertia.copyInverted()
set B2.modelName = "war3mapImported\\B-2.mdx"
call B2.setEngineSound("war3mapImported\\engineJet.wav", 1, 1 )
call B2.setLandingGearsModel("war3mapImported\\Landing Gears.mdx","origin")
set B2.simulationCode = function Ctrl
set B2.unitType = 'h000'
set B2.cockpitCam = vector.create(23.3,0,2.5)
set B2.hitpoints = 300.
call B2.addCollisionPoint(BODY,vector.create(28,0,0))
call B2.addCollisionPoint(BODY,vector.create(12,0,-4.2))
call B2.addCollisionPoint(BODY,vector.create(-2.5,0,-4.2))
call B2.addCollisionPoint(BODY,vector.create(15.6,0,6.8))
call B2.addCollisionPoint(BODY,vector.create(-2.3,0,6.3))
call B2.addCollisionPoint(BODY,vector.create(-25.6,76,-.5))
call B2.addCollisionPoint(BODY,vector.create(-25.6,-76,-.5))
call B2.addCollisionPoint(BODY,vector.create(-29.5,19.5,-.5))
call B2.addCollisionPoint(BODY,vector.create(-29.5,-19.5,-.5))
call B2.addLandingGear(vector.create(29,0,-11),vector.create(0,0,10),vector.create(0,1,0),5)
call B2.addLandingGear(vector.create(-3,-15,-10),vector.create(0,0,9),vector.create(0,1,0),0)
call B2.addLandingGear(vector.create(-3,15,-10),vector.create(0,0,9),vector.create(0,1,0),0)
set B2.collshape = shape.create()
call B2.collshape.addNewBox(vector.create(6,0,.5),vector.create(13,13,5),quaternion.create(0,0,0,1))
call B2.collshape.addNewBox(vector.create(-2,32.3,.5),vector.create(45,7,1.5),quaternion.createEuler(0,0,60*bj_DEGTORAD))
call B2.collshape.addNewBox(vector.create(-2,-32.3,.5),vector.create(45,7,1.5),quaternion.createEuler(0,0,-60*bj_DEGTORAD))
call B2.collshape.addNewBox(vector.create(-9.25,0,.5),vector.create(14.25,33.32,1.5),quaternion.create(0,0,0,1))
call B2.collshape.addBoundingVolume(SHAPE_BOX)
set B2.cloud1PosStr = "hand left"
set B2.cloud2PosStr = "hand right"
set B2.cloud3PosStr = "head"
set B2.posMG = vector.create(33,0,0)
set B2.velMG = vector.create(1000,0,0)
set B2.MGMaxTurnDeg = 10
set B2.posMissiles = vector.create(7,21,-5)
set B2.velMissiles = vector.create(10,0,-10)
set B2.posFlares = vector.create(0,0,0)
set B2.velFlares = vector.create(0,100,-10)
call B2.scaleVisual(.4317)
set B2.speedFullRudderPitch = 130.
endfunction
endlibrary
//TESH.scrollpos=58
//TESH.alwaysfold=0
library ME109Lib initializer init uses physHelpers
globals
class ME109
endglobals
private function Ctrl takes nothing returns nothing
local object o = physCtrlObject
local vector frictvec
local vector relPos
local vector accelvec
// Front Wing
set frictvec = vector.create(0,0,1)
set relPos = vector.create(0,0,0)
call o.addWing(VECTOR0,frictvec,1)
// Main Wings
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundXAxis(-2*bj_DEGTORAD)
call frictvec.rotateAroundYAxis(-4*bj_DEGTORAD)
call relPos.setXYZ(14*o.c.modelScale,-62*o.c.modelScale,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,3)
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundXAxis(2*bj_DEGTORAD)
call frictvec.rotateAroundYAxis(-4*bj_DEGTORAD)
call relPos.setXYZ(14*o.c.modelScale,62*o.c.modelScale,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,3)
// Roll Rudders
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundYAxis(-o.ctrl.rudders.x*15*bj_DEGTORAD)
call relPos.setXYZ(-10*o.c.modelScale,-62*o.c.modelScale,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,1)
set frictvec.z=-frictvec.z
call relPos.setXYZ(-10*o.c.modelScale,62*o.c.modelScale,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,1)
// Height Rudders
call frictvec.setXYZ(0,0,1)
call relPos.setXYZ(-104*o.c.modelScale,0,20*o.c.modelScale)
call o.addWing(relPos,frictvec,1)
call frictvec.rotateAroundYAxis(-o.ctrl.rudders.y*35*bj_DEGTORAD)
call o.addWing(relPos,frictvec,1)
// Side Rudders
call frictvec.setXYZ(0,1,0)
call relPos.setXYZ(45*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,.6)
call relPos.setXYZ(-45*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,.6)
call frictvec.rotateAroundZAxis(o.ctrl.rudders.z*10*bj_DEGTORAD)
call relPos.setXYZ(-104*o.c.modelScale,0,20*o.c.modelScale)
call o.addWing(relPos,frictvec,.6)
// Frontal Friction
call frictvec.setXYZ(1,0,0)
call o.addWing(VECTOR0,frictvec,.2+o.ctrl.brakes*.2)
if o.ctrl.landingGearPos!=0 then
call relPos.setXYZ(0,0,-4*o.c.modelScale)
call o.addWing(relPos,frictvec,.06)
endif
call relPos.destroy()
call frictvec.destroy()
set accelvec = vector.create(30*o.ctrl.enginePower,0,0)
call accelvec.rotateByQuaternion(o.orient)
call o.addForce(VECTOR0,accelvec)
call accelvec.destroy()
endfunction
private function init takes nothing returns nothing
set ME109 = class.create()
set ME109.mass = 4.
set ME109.inertia = matrix.create(25,0,0, 0,50,0, 0,0,50)
set ME109.inertiaInv = ME109.inertia.copyInverted()
set ME109.modelName = "war3mapImported\\ME109_base.mdx"
call ME109.setElevator("war3mapImported\\ME109_elev.mdx",vector.create(-106,0,20.8),0,bj_DEGTORAD*40)
call ME109.setEngineSound("war3mapImported\\engineProp.wav", 1, .5 )
call ME109.setLandingGearsModel("war3mapImported\\Landing Gears Me109.mdx","origin")
set ME109.simulationCode = function Ctrl
set ME109.unitType = 'h000'
set ME109.cockpitCam = vector.create(13,0,15)
set ME109.hitpoints = 50.
call ME109.addCollisionPoint(BODY,vector.create(-17,125,-2))
call ME109.addCollisionPoint(BODY,vector.create(-17,-125,-2))
call ME109.addCollisionPoint(BODY,vector.create(35,54,-6))
call ME109.addCollisionPoint(BODY,vector.create(35,-54,-6))
call ME109.addCollisionPoint(BODY,vector.create(79,0,0))
call ME109.addCollisionPoint(BODY,vector.create(33,-8,-14))
call ME109.addCollisionPoint(BODY,vector.create(33,8,-14))
call ME109.addCollisionPoint(BODY,vector.create(-23,-8,-14))
call ME109.addCollisionPoint(BODY,vector.create(-23,8,-14))
call ME109.addCollisionPoint(BODY,vector.create(-122,0,10))
call ME109.addCollisionPoint(BODY,vector.create(-103,0,37))
call ME109.addCollisionPoint(BODY,vector.create(-103,-38,20))
call ME109.addCollisionPoint(BODY,vector.create(-103,38,20))
call ME109.addCollisionPoint(BODY,vector.create(13,0,19))
call ME109.addLandingGear(vector.create(15,-30,-40),vector.create(0,-13,38),vector.create(0,1,0),0)
call ME109.addLandingGear(vector.create(15,30,-40),vector.create(0,13,38),vector.create(0,1,0),0)
call ME109.addLandingGear(vector.create(-116,0,-3.8),vector.create(0,0,10),vector.create(0,1,0),-5)
set ME109.collshape = shape.create()
call ME109.collshape.addNewBoxBetween(vector.create(23,128,-1),vector.create(-12,-128,-11),quaternion.create(0,0,0,1))
call ME109.collshape.addNewBoxBetween(vector.create(66,10,-11),vector.create(-55,-10,10),quaternion.create(0,0,0,1))
call ME109.collshape.addNewBoxBetween(vector.create(16,6.6,18),vector.create(-100,-6.6,0),quaternion.create(0,0,0,1))
call ME109.collshape.addNewBoxBetween(vector.create(-94,3,34),vector.create(-122,-3,7),quaternion.create(0,0,0,1))
call ME109.collshape.addNewBox(vector.create(-106,0,-20),vector.create(7,39,3),quaternion.create(0,0,0,1))
call ME109.collshape.addBoundingVolume(SHAPE_SPHERE)
set ME109.posMG = vector.create(35,54,-6.5)
set ME109.velMG = vector.create(1000,0,0)
set ME109.MGMaxTurnDeg = 10
set ME109.posMissiles = vector.create(11,30,-22.5)
set ME109.velMissiles = vector.create(10,0,-15)
set ME109.posFlares = vector.create(0,0,0)
set ME109.velFlares = vector.create(0,100,-10)
call ME109.scaleVisual(.5*.0987)
set ME109.speedFullRudderPitch = 100.
endfunction
endlibrary
//TESH.scrollpos=66
//TESH.alwaysfold=0
library BOMBERLib initializer init uses physHelpers
globals
class BOMBER
endglobals
private function Ctrl takes nothing returns nothing
local object o = physCtrlObject
local vector frictvec
local vector relPos
local vector accelvec
// Front Wing
set frictvec = vector.create(0,0,1)
set relPos = vector.create(60*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,8)
call relPos.setXYZ(-60*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,8)
// Main Wings
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundYAxis((-4-4*o.ctrl.landingGearPos)*bj_DEGTORAD)
call relPos.setXYZ(5*o.c.modelScale,-51*o.c.modelScale,-5*o.c.modelScale)
call o.addWing(relPos,frictvec,28)
call relPos.setXYZ(-10*o.c.modelScale,-51*o.c.modelScale,-5*o.c.modelScale)
call frictvec.rotateAroundYAxis(-o.ctrl.rudders.x*40*bj_DEGTORAD)
call o.addWing(relPos,frictvec,6)
call frictvec.setXYZ(0,0,1)
call frictvec.rotateAroundYAxis((-4-4*o.ctrl.landingGearPos)*bj_DEGTORAD)
call relPos.setXYZ(5*o.c.modelScale,51*o.c.modelScale,-5*o.c.modelScale)
call o.addWing(relPos,frictvec,28)
call relPos.setXYZ(-10*o.c.modelScale,51*o.c.modelScale,-5*o.c.modelScale)
call frictvec.rotateAroundYAxis(o.ctrl.rudders.x*40*bj_DEGTORAD)
call o.addWing(relPos,frictvec,6)
call frictvec.setXYZ(0,0,1)
// Height Rudders
call frictvec.rotateAroundYAxis(-o.ctrl.rudders.y*15*bj_DEGTORAD)
call relPos.setXYZ(-72*o.c.modelScale,-23*o.c.modelScale,10*o.c.modelScale)
call o.addWing(relPos,frictvec,10)
call relPos.setXYZ(-72*o.c.modelScale,23*o.c.modelScale,10*o.c.modelScale)
call o.addWing(relPos,frictvec,10)
// Side Rudders
call frictvec.setXYZ(0,1,0)
call relPos.setXYZ(60*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,8)
call relPos.setXYZ(-60*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,8)
call frictvec.rotateAroundZAxis(o.ctrl.rudders.z*10*bj_DEGTORAD)
call relPos.setXYZ(-74*o.c.modelScale,0,28*o.c.modelScale)
call o.addWing(relPos,frictvec,8)
// Frontal Friction
call frictvec.setXYZ(1,0,0)
call o.addWing(VECTOR0,frictvec,8+o.ctrl.brakes*8)
if o.ctrl.landingGearPos!=0 then
call relPos.setXYZ(0,0,-4*o.c.modelScale)
call o.addWing(relPos,frictvec,1)
endif
call relPos.destroy()
call frictvec.destroy()
set accelvec = vector.create(800*o.ctrl.enginePower,0,0)
call accelvec.rotateByQuaternion(o.orient)
call o.addForce(VECTOR0,accelvec)
call accelvec.destroy()
endfunction
private function init takes nothing returns nothing
set BOMBER = class.create()
set BOMBER.mass = 50.
set BOMBER.inertia = matrix.create(7500,0,0, 0,10000,0, 0,0,10000)
set BOMBER.inertiaInv = BOMBER.inertia.copyInverted()
set BOMBER.modelName = "war3mapImported\\Bomber_noelev.mdx"
call BOMBER.setElevator("war3mapImported\\Bomber_elev.mdx",vector.create(-66,0,11),0,bj_DEGTORAD*15)
call BOMBER.setEngineSound("war3mapImported\\engineJet.wav", .7, 1.5 )
call BOMBER.setLandingGearsModel("war3mapImported\\Landing Gears.mdx","foot")
set BOMBER.simulationCode = function Ctrl
set BOMBER.unitType = 'h000'
set BOMBER.cockpitCam = vector.create(61,0,10.5)
set BOMBER.hitpoints = 300.
call BOMBER.addCollisionPoint(BODY,vector.create(80,0,0))
call BOMBER.addCollisionPoint(BODY,vector.create(-81,0,11))
call BOMBER.addCollisionPoint(BODY,vector.create(-84,0,38))
call BOMBER.addCollisionPoint(BODY,vector.create(-13,-90,-1))
call BOMBER.addCollisionPoint(BODY,vector.create(-13,90,-1))
call BOMBER.addCollisionPoint(BODY,vector.create(64,-6.5,-6.5))
call BOMBER.addCollisionPoint(BODY,vector.create(64,6.5,-6.5))
call BOMBER.addCollisionPoint(BODY,vector.create(-6,-6.5,-6.5))
call BOMBER.addCollisionPoint(BODY,vector.create(-6,6.5,-6.5))
call BOMBER.addCollisionPoint(BODY,vector.create(-60,0,0))
call BOMBER.addCollisionPoint(BODY,vector.create(55,0,13))
call BOMBER.addCollisionPoint(ELEVATOR,vector.create(-12.5,-37,0))
call BOMBER.addCollisionPoint(ELEVATOR,vector.create(-12.5,37,0))
call BOMBER.addLandingGear(vector.create(29,0,-13),vector.create(0,0,10),vector.create(0,1,0),5)
call BOMBER.addLandingGear(vector.create(-3,-15,-12),vector.create(0,0,9),vector.create(0,1,0),0)
call BOMBER.addLandingGear(vector.create(-3,15,-12),vector.create(0,0,9),vector.create(0,1,0),0)
set BOMBER.collshape = shape.create()
call BOMBER.collshape.addNewSphere(vector.create(54,0,3),10.3)
call BOMBER.collshape.addNewCylinder(vector.create(13,0,3),10.3,41,quaternion.createEuler(0,90*bj_DEGTORAD,0))
call BOMBER.collshape.addNewCylinder(vector.create(-43.5,0,5.15),8.15,15.5,quaternion.createEuler(0,90*bj_DEGTORAD,0))
call BOMBER.collshape.addNewBoxBetween(vector.create(-59.5,0,7),vector.create(-82,0,38),quaternion.create(0,0,0,1))
call BOMBER.collshape.addNewBox(vector.create(-70,0,11),vector.create(10,33,3),quaternion.create(0,0,0,1))
call BOMBER.collshape.addNewBox(vector.create(-8,-44,-1.5),vector.create(10,47,4),quaternion.createEuler(0,0,10*bj_DEGTORAD))
call BOMBER.collshape.addNewBox(vector.create(-8,44,-1.5),vector.create(10,47,4),quaternion.createEuler(0,0,-10*bj_DEGTORAD))
call BOMBER.collshape.addBoundingVolume(SHAPE_BOX)
set BOMBER.posMG = vector.create(0,0,0)
set BOMBER.velMG = vector.create(1000,0,0)
set BOMBER.MGMaxTurnDeg = 10
set BOMBER.posMissiles = vector.create(0,0,0)
set BOMBER.velMissiles = vector.create(10,10,-10)
set BOMBER.posFlares = vector.create(0,0,0)
set BOMBER.velFlares = vector.create(0,100,-10)
call BOMBER.scaleVisual(.3)
set BOMBER.speedFullRudderPitch = 100.
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library DESTROYERLib initializer init uses physHelpers
globals
class DESTROYER
endglobals
private function Ctrl takes nothing returns nothing
local object o = physCtrlObject
local vector frictvec
local vector relPos
local vector accelvec
// Main Wing
set frictvec = vector.create(0,0,1)
set relPos = vector.create(160*o.c.modelScale,10*o.c.modelScale,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,20)
call relPos.setXYZ(160*o.c.modelScale,-10*o.c.modelScale,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,20)
call relPos.setXYZ(-160*o.c.modelScale,10*o.c.modelScale,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,20)
call relPos.setXYZ(-160*o.c.modelScale,-10*o.c.modelScale,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,20)
// Side Rudders
call frictvec.setXYZ(0,1,0)
call relPos.setXYZ(160*o.c.modelScale,0,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,40)
call relPos.setXYZ(-160*o.c.modelScale,0,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,40)
call frictvec.rotateAroundZAxis(o.ctrl.rudders.z*30*bj_DEGTORAD)
call relPos.setXYZ(-250*o.c.modelScale,0,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,20)
// Frontal Friction
call frictvec.setXYZ(1,0,0)
call relPos.setXYZ(0,0,-10*o.c.modelScale)
call o.addWing(relPos,frictvec,30)
call frictvec.destroy()
call relPos.setXYZ(-250*o.c.modelScale,0,-10*o.c.modelScale)
set accelvec = vector.create(40*o.ctrl.enginePower,0,0)
call accelvec.rotateAroundZAxis(o.ctrl.rudders.z*5*bj_DEGTORAD)
call accelvec.rotateByQuaternion(o.orient)
call relPos.rotateByQuaternion(o.orient)
call accelvec.scale(GetVolumeDensity(o.pos.z+relPos.z))
call o.addForce(relPos,accelvec)
call relPos.destroy()
call accelvec.destroy()
endfunction
private function init takes nothing returns nothing
set DESTROYER = class.create()
set DESTROYER.mass = 4500.
set DESTROYER.inertia = matrix.create(2000000,0,0, 0,20000000,0, 0,0,20000000)
set DESTROYER.inertiaInv = DESTROYER.inertia.copyInverted()
set DESTROYER.modelName = "war3mapImported\\Destroyer.mdx"
call DESTROYER.setEngineSound("war3mapImported\\engineJet.wav", .5, 1 )
set DESTROYER.simulationCode = function Ctrl
set DESTROYER.unitType = 'h000'
set DESTROYER.cockpitCam = vector.create(18.5,0,16.8)
set DESTROYER.hitpoints = 600.
call DESTROYER.addCollisionPointWithDisplacement(vector.create(0,0,-20),4,7)
call DESTROYER.addCollisionPointWithDisplacement(vector.create(182,0,-20),4,7)
call DESTROYER.addCollisionPointWithDisplacement(vector.create(-238,0,-20),4,7)
call DESTROYER.addCollisionPointWithDisplacement(vector.create(224,19,0),7,10)
call DESTROYER.addCollisionPointWithDisplacement(vector.create(224,-19,0),7,10)
call DESTROYER.addCollisionPointWithDisplacement(vector.create(-224,19,0),7,10)
call DESTROYER.addCollisionPointWithDisplacement(vector.create(-224,-19,0),7,10)
call DESTROYER.addCollisionPointWithDisplacement(vector.create(0,19,0),7,10)
call DESTROYER.addCollisionPointWithDisplacement(vector.create(0,-19,0),7,10)
call DESTROYER.addCollisionPointWithDisplacement(vector.create(260,0,20),7,10)
call DESTROYER.addCollisionPointWithDisplacement(vector.create(-250,0,20),7,10)
call DESTROYER.addCollisionPoint(BODY,vector.create(56,0,123))
call DESTROYER.addCollisionPoint(BODY,vector.create(-119,0,57))
call DESTROYER.addCollisionPoint(BODY,vector.create(-119,0,57))
set DESTROYER.collshape = shape.create()
call DESTROYER.collshape.addNewBox(vector.create(9.5,0,1),vector.create(241.5,29,22),quaternion.create(0,0,0,1))
call DESTROYER.collshape.addNewBox(vector.create(10,0,38),vector.create(180,22,16),quaternion.create(0,0,0,1))
call DESTROYER.collshape.addNewCylinder(vector.create(58,0,80),10,35,quaternion.create(0,0,0,1))
call DESTROYER.collshape.addBoundingVolume(SHAPE_BOX)
set DESTROYER.posMG = vector.create(205,3.7,34)
set DESTROYER.velMG = vector.create(0,0,1000)
set DESTROYER.MGMaxTurnDeg = 80
set DESTROYER.posMissiles = vector.create(7,0,65)
set DESTROYER.velMissiles = vector.create(0,0,20)
set DESTROYER.posFlares = vector.create(0,0,0)
set DESTROYER.velFlares = vector.create(0,60,60)
call DESTROYER.scaleVisual(.32)
set DESTROYER.speedFullRudderPitch = 1000.
endfunction
endlibrary
//TESH.scrollpos=49
//TESH.alwaysfold=0
library COBRALib initializer init uses physHelpers
globals
class COBRA
endglobals
private function Ctrl takes nothing returns nothing
local object o = physCtrlObject
local vector frictvec
local vector relPos
local vector accelvec
// Front Wing
set frictvec = vector.create(0,0,1)
set relPos = vector.create(40*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,2.4)
// Main Wings
call relPos.setXYZ(0,-40*o.c.modelScale,0)
call o.addWing(relPos,frictvec,3.2)
call relPos.setXYZ(0,40*o.c.modelScale,0)
call o.addWing(relPos,frictvec,3.2)
// Height Rudders
call relPos.setXYZ(-115*o.c.modelScale,0,-1.7*o.c.modelScale)
call o.addWing(relPos,frictvec,1.6)
// Side Rudders
call frictvec.setXYZ(0,1,0)
call relPos.setXYZ(-195*o.c.modelScale,0,22*o.c.modelScale)
call o.addWing(relPos,frictvec,.8)
call relPos.setXYZ(60*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,1.6)
call relPos.setXYZ(-60*o.c.modelScale,0,0)
call o.addWing(relPos,frictvec,1.6)
call relPos.setXYZ(0,0,20*o.c.modelScale)
call o.addWing(relPos,frictvec,1.6)
call relPos.setXYZ(0,0,-20*o.c.modelScale)
call o.addWing(relPos,frictvec,1.6)
// Frontal Friction
call frictvec.setXYZ(1,0,0)
call o.addWing(VECTOR0,frictvec,.8)
call frictvec.destroy()
call relPos.setXYZ(0,0,6)
set accelvec = vector.create(0,0,350*o.ctrl.enginePower)
call accelvec.rotateAroundXAxis(-o.ctrl.rudders.x*4*bj_DEGTORAD)
call accelvec.rotateAroundYAxis(o.ctrl.rudders.y*4*bj_DEGTORAD)
call accelvec.rotateByQuaternion(o.orient)
call relPos.rotateByQuaternion(o.orient)
call o.addForce(relPos,accelvec)
call relPos.destroy()
call accelvec.destroy()
set accelvec = vector.create(0,0,-.5*o.ctrl.rudders.z)
call accelvec.rotateByQuaternion(o.orient)
call o.angAccel.add(accelvec)
call accelvec.destroy()
endfunction
private function init takes nothing returns nothing
set COBRA = class.create()
set COBRA.mass = 20.
set COBRA.inertia = matrix.create(82,0,0, 0,164,0, 0,0,164)
set COBRA.inertiaInv = COBRA.inertia.copyInverted()
set COBRA.modelName = "war3mapImported\\Cobra.mdx"
call COBRA.setEngineSound("war3mapImported\\engineHeli.wav", 1, .5 )
set COBRA.simulationCode = function Ctrl
set COBRA.unitType = 'h000'
set COBRA.cockpitCam = vector.create(42,0,13)
set COBRA.hitpoints = 50.
call COBRA.addCollisionPoint(BODY,vector.create(-200,0,-7))
call COBRA.addCollisionPoint(BODY,vector.create(-207,0,43))
call COBRA.addCollisionPoint(BODY,vector.create(-75,-9,-21))
call COBRA.addCollisionPoint(BODY,vector.create(-75,9,-21))
call COBRA.addCollisionPoint(BODY,vector.create(57,-9,-21))
call COBRA.addCollisionPoint(BODY,vector.create(57,9,-21))
call COBRA.addCollisionPoint(BODY,vector.create(84,-4,4))
call COBRA.addCollisionPoint(BODY,vector.create(84,4,4))
call COBRA.addCollisionPoint(BODY,vector.create(-4,-4,31))
call COBRA.addCollisionPoint(BODY,vector.create(-4,4,31))
call COBRA.addCollisionPoint(BODY,vector.create(38,-22,-33))
call COBRA.addCollisionPoint(BODY,vector.create(38,22,-33))
call COBRA.addCollisionPoint(BODY,vector.create(-45,-22,-33))
call COBRA.addCollisionPoint(BODY,vector.create(-45,22,-33))
set COBRA.collshape = shape.create()
call COBRA.collshape.addNewBoxBetween(vector.create(82.6,9.5,7),vector.create(-199,-9.5,-18),quaternion.create(0,0,0,1))
call COBRA.collshape.addNewBoxBetween(vector.create(40,9.5,29),vector.create(-71,-9.5,7),quaternion.create(0,0,0,1))
call COBRA.collshape.addNewBoxBetween(vector.create(0,36,1.2),vector.create(-22,-36,-4.2),quaternion.create(0,0,0,1))
call COBRA.collshape.addNewBoxBetween(vector.create(-177,4,2.5),vector.create(-230,-4,60),quaternion.create(0,0,0,1))
call COBRA.collshape.addBoundingVolume(SHAPE_SPHERE)
set COBRA.posMG = vector.create(104,0,-17.8)
set COBRA.velMG = vector.create(1000,0,0)
set COBRA.MGMaxTurnDeg = 10
set COBRA.posMissiles = vector.create(20,20.7,-9.5)
set COBRA.velMissiles = vector.create(10,0,0)
set COBRA.posFlares = vector.create(0,0,0)
set COBRA.velFlares = vector.create(0,100,-10)
call COBRA.scaleVisual(1.25*14./284.)
set COBRA.speedFullRudderPitch = 1000.
endfunction
endlibrary
//TESH.scrollpos=14
//TESH.alwaysfold=0
library PARTICLESLib initializer init uses physHelpers
globals
pclass FLARE
pclass BULLET
pclass MISSILE
pclass BOMB
endglobals
public function init takes nothing returns nothing
set BULLET = pclass.create()
set BULLET.modelName = "war3mapImported\\Bullet.mdx"
set BULLET.mass = 0.001
set BULLET.scale = 0.03
set BULLET.lifespan = 2
set BULLET.explodeOnHit = true
set BULLET.explodeInWater = true
set FLARE = pclass.create()
set FLARE.modelName = "war3mapImported\\Flare.mdx"//"Abilities\\Weapons\\FaerieDragonMissile\\FaerieDragonMissile.mdl"
set FLARE.mass = 0.01
set FLARE.friction = .3
set FLARE.lifespan = 3
set FLARE.scale = 0.3
set MISSILE = pclass.create()
set MISSILE.modelName = "war3mapImported\\Rocket3.mdx"
set MISSILE.mass = .08
set MISSILE.scale = 0.2
set MISSILE.accel = 60.
set MISSILE.lifespan = 15
set MISSILE.turnRateDeg = 35.
set MISSILE.explodeOnHit = true
set MISSILE.explodeInWater = true
set BOMB = pclass.create()
set BOMB.modelName = "war3mapImported\\Bomb.mdx"
set BOMB.mass = .1
set BOMB.scale = 0.3
set BOMB.friction = .02
set BOMB.lifespan = 15
set BOMB.turnRateDeg = 6.
set BOMB.explodeOnHit = true
set BOMB.explodeInWater = true
endfunction
endlibrary
//TESH.scrollpos=48
//TESH.alwaysfold=0
globals
dialog array OptionsMenu
button array OptionsMenu_Reset
button array OptionsMenu_Assistance
button array OptionsMenu_LimitRudders
button array OptionsMenu_AIControl
button array OptionsMenu_ChangeAircraft
endglobals
function ChangeAircraft takes object o returns nothing
local integer pid = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
local class oldclass = o.c
if o.elevu!=null then
call DestroyEffect(o.eleve)
call RemoveUnit(o.elevu)
set o.elevu=null
endif
call DestroyEffect(o.e)
call RemoveUnit(o.u)
call o.engineSound.destroyWhenDone()
call DestroyImage(o.shadow)
if o.landingGears!=null then
call DestroyEffect(o.landingGears)
set o.landingGears = null
endif
set o.c = o.c + 1
if o.c.modelName==null then
set o.c=1
endif
set o.u = CreateUnit(GetTriggerPlayer(),o.c.unitType,o.pos.x,o.pos.y,0.)
set o.e = AddSpecialEffectTarget(o.c.modelName,o.u,"origin")
call SetUnitAnimation(o.u,"stand")
call SetUnitPathing(o.u,false)
call SetUnitTimeScale(o.u,1000.)
call SetUnitScale(o.u,o.c.modelScale,o.c.modelScale,o.c.modelScale)
call UnitAddAbility(o.u,'Amrf')
call o.updateAnimation()
call UnitRemoveAbility(o.u,'Amrf')
call o.inertiaWorld.destroy()
call o.inertiaWorldInv.destroy()
call o.addShadow()
call o.addSound()
call o.addElevatorModel()
set o.inertiaWorld = o.c.inertia.copy()
call o.inertiaWorld.rotateByQuaternion(o.orient)
set o.inertiaWorldInv = o.inertiaWorld.copyInverted()
set o.hp = o.hp*o.c.hitpoints/oldclass.hitpoints
if playerControlledObj[pid]==o then
//call SetUnitState(playerController[pid],UNIT_STATE_LIFE,RMaxBJ(o.hp,1))
endif
call o.removeGroundPenetration()
endfunction
function Bool2OnOff takes boolean b returns string
if b then
return "On"
endif
return "Off"
endfunction
function RefreshOptionsMenu takes integer pid returns nothing
local string assistanceStr = "|cff999999Assistance:|r |cffffffff"+Bool2OnOff(playerAssistance[pid])+"|r |cff999999(|r|cffffcc00Q|r|cff999999)|r"
local string limitRuddersStr = "|cff999999Limit Rudders:|r |cffffffff"+Bool2OnOff(playerLimitRudders[pid])+"|r |cff999999(|r|cffffcc00W|r|cff999999)|r"
local string aiControlStr = "|cff999999AI Control:|r |cffffffff"+Bool2OnOff(playerAIControl[pid])+"|r |cff999999(|r|cffffcc00E|r|cff999999)|r"
call DialogClear(OptionsMenu[pid])
set OptionsMenu_Assistance[pid] = DialogAddButton(OptionsMenu[pid],assistanceStr,81)
set OptionsMenu_LimitRudders[pid] = DialogAddButton(OptionsMenu[pid],limitRuddersStr,87)
set OptionsMenu_AIControl[pid] = DialogAddButton(OptionsMenu[pid],aiControlStr,69)
set OptionsMenu_ChangeAircraft[pid] = DialogAddButton(OptionsMenu[pid],"|cff999999Change Vehicle (|r|cffffcc00R|r|cff999999)|r",82)
set OptionsMenu_Reset[pid] = DialogAddButton(OptionsMenu[pid],"|cff999999Reset Position (|r|cffffcc00A|r|cff999999)|r",65)
call DialogAddButton(OptionsMenu[pid],"|cff999999Done (|r|cffffcc00S|r|cff999999)|r",83)
endfunction
function Trig_Menu_Clicked takes nothing returns nothing
local integer pid = GetPlayerId(GetTriggerPlayer())
local object obj = playerControlledObj[pid]
if GetClickedButton()==OptionsMenu_Reset[pid] then
set obj.pos.z = 1500.
call obj.vel.setLength(100)
elseif GetClickedButton()==OptionsMenu_Assistance[pid] then
set playerAssistance[pid] = not playerAssistance[pid]
elseif GetClickedButton()==OptionsMenu_LimitRudders[pid] then
set playerLimitRudders[pid] = not playerLimitRudders[pid]
elseif GetClickedButton()==OptionsMenu_AIControl[pid] then
set playerAIControl[pid] = not playerAIControl[pid]
elseif GetClickedButton()==OptionsMenu_ChangeAircraft[pid] then
call ChangeAircraft(obj)
endif
endfunction
function Trig_Menu_Actions takes nothing returns nothing
call RefreshOptionsMenu(GetPlayerId(GetTriggerPlayer()))
call DialogDisplay(GetTriggerPlayer(),OptionsMenu[GetPlayerId(GetTriggerPlayer())],true)
endfunction
//===========================================================================
function InitTrig_Menu takes nothing returns nothing
local integer i = 0
local trigger t = CreateTrigger()
set gg_trg_Menu = CreateTrigger( )
loop
exitwhen i>11
set playerAssistance[i] = true
set OptionsMenu[i] = DialogCreate()
call TriggerRegisterDialogEvent(t,OptionsMenu[i])
call TriggerRegisterPlayerEvent(gg_trg_Menu, Player(i), EVENT_PLAYER_END_CINEMATIC)
set i = i + 1
endloop
call TriggerAddAction(t,function Trig_Menu_Clicked)
call TriggerAddAction( gg_trg_Menu, function Trig_Menu_Actions )
endfunction
//TESH.scrollpos=33
//TESH.alwaysfold=0
library physControllers initializer physControllers_Init
globals
unit array playerController
object array playerControlledObj
endglobals
function ControlReaction takes nothing returns nothing
local integer abil = GetSpellAbilityId()
local object obj = playerControlledObj[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]
if abil=='A000' then
// Accelerate Main Engine
set obj.ctrl.enginePowerAim = obj.ctrl.enginePowerAim + .33333
if obj.ctrl.enginePowerAim>1. then
set obj.ctrl.enginePowerAim=1.
endif
elseif abil=='A001' then
// Decelerate Main Engine
set obj.ctrl.enginePowerAim = obj.ctrl.enginePowerAim - .33333
if obj.ctrl.enginePowerAim<0. then
set obj.ctrl.enginePowerAim=0.
endif
elseif abil=='A002' then
// Turn Right
set obj.ctrl.zRotate = obj.ctrl.zRotate + 1.
if obj.ctrl.zRotate>1. then
set obj.ctrl.zRotate=1.
endif
elseif abil=='A003' then
// Turn Left
set obj.ctrl.zRotate = obj.ctrl.zRotate - 1.
if obj.ctrl.zRotate<-1. then
set obj.ctrl.zRotate=-1.
endif
elseif abil=='A004' then
// Fire missile
set obj.ctrl.weaponShots2 = 1
elseif abil=='A005' then
// Change Camera
set obj.ctrl.cam = obj.ctrl.cam+1
if obj.ctrl.cam>4 then
set obj.ctrl.cam=0
endif
elseif abil=='A007' then
// Drop Bombs
set obj.ctrl.weaponShots3 = 10
elseif abil=='A008' then
// Fire machine gun
set obj.ctrl.weaponShots1 = 20
elseif abil=='A009' then
// Landing Gears
set obj.ctrl.wantLandingGears = not obj.ctrl.wantLandingGears
if obj.ctrl.wantLandingGears then
call obj.addLandingGears()
else
call DestroyEffect(obj.landingGears)
set obj.landingGears = null
endif
elseif abil=='A00A' then
// Toggle Brakes
set obj.ctrl.brakes = 1.-obj.ctrl.brakes
elseif abil=='A00B' then
// Toggle Brakes
set obj.ctrl.flareShots = 5
endif
endfunction
function physControllers_Init takes nothing returns nothing
local integer i = 0
local trigger t = CreateTrigger()
loop
exitwhen i>11
set playerController[i] = CreateUnit(Player(i),'h002',mapMaxX,mapMaxY,0)
set i = i + 1
endloop
call SelectUnit(playerController[GetPlayerId(GetLocalPlayer())],true)
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( t, function ControlReaction )
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Init_Actions takes nothing returns nothing
call SetSkyModel( "Environment\\Sky\\FoggedSky\\FoggedSky.mdl" )
call SetFloatGameState(GAME_STATE_TIME_OF_DAY, 12)
call SetTimeOfDayScale( 0 )
call EnableDragSelect(false, false)
call EnablePreSelect(false, false)
call EnableSelect(false, false)
call EnableOcclusion(false)
set bj_useDawnDuskSounds = false
call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_AMBIENTSOUNDS, 0.00 )
call PreloadSound3d("war3mapImported\\engineJet.wav")
call PreloadSound3d("war3mapImported\\engineProp.wav")
call PreloadSound3d("war3mapImported\\engineHeli.wav")
call SetCloudCount(25)
call CinematicFadeBJ( bj_CINEFADETYPE_FADEIN, 1.00, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )
endfunction
//===========================================================================
function InitTrig_Init takes nothing returns nothing
set gg_trg_Init = CreateTrigger( )
call TriggerAddAction( gg_trg_Init, function Trig_Init_Actions )
endfunction
//TESH.scrollpos=45
//TESH.alwaysfold=0
globals
multiboard array playerBoard
boolean array playerAssistance
boolean array playerLimitRudders
boolean array playerAIControl
endglobals
function Trig_Multiboard_Actions takes nothing returns nothing
local integer i = 0
local multiboard mb
local multiboarditem mbitem
local object o
loop
exitwhen i>11
set mb = CreateMultiboard()
call MultiboardSetRowCount(mb, 15)
call MultiboardSetColumnCount(mb, 2)
call MultiboardSetTitleText(mb, "")
set playerBoard[i] = mb
call MultiboardSetItemValueFast( mb, 0, 0, "|cff999999Flight Information|r" )
call MultiboardSetItemValueFast( mb, 0, 1, " Speed" )
call MultiboardSetItemValueFast( mb, 1, 1, "0 km/h (N)" )
call MultiboardSetItemValueFast( mb, 0, 2, " Altitude" )
call MultiboardSetItemValueFast( mb, 1, 2, "0 m" )
call MultiboardSetItemValueFast( mb, 0, 3, " Acceleration" )
call MultiboardSetItemValueFast( mb, 1, 3, "1.0 G" )
call MultiboardSetItemValueFast( mb, 0, 4, " Pitch" )
call MultiboardSetItemValueFast( mb, 1, 4, "0 °" )
call MultiboardSetItemValueFast( mb, 0, 5, " Wind" )
call MultiboardSetItemValueFast( mb, 1, 5, "0 km/h (N)" )
call MultiboardSetItemValueFast( mb, 0, 6, "|cff999999Controls|r" )
call MultiboardSetItemValueFast( mb, 0, 7, " Throttle" )
call MultiboardSetItemValueFast( mb, 1, 7, "0%" )
call MultiboardSetItemValueFast( mb, 0, 8, " Landing Gears" )
call MultiboardSetItemValueFast( mb, 1, 8, "0%" )
call MultiboardSetItemValueFast( mb, 0, 9, " Brakes" )
call MultiboardSetItemValueFast( mb, 1, 9, "0%" )
call MultiboardSetItemValueFast( mb, 0, 10, " Ailerons" )
call MultiboardSetItemValueFast( mb, 1, 10, "0%" )
call MultiboardSetItemValueFast( mb, 0, 11, " Elevators" )
call MultiboardSetItemValueFast( mb, 1, 11, "0%" )
call MultiboardSetItemValueFast( mb, 0, 12, " Rudder" )
call MultiboardSetItemValueFast( mb, 1, 12, "0%" )
call MultiboardSetItemValueFast( mb, 0, 13, "|cff999999Intelligence|r" )
call MultiboardSetItemStyleBJ( mb, 0, 0, true, false )
call MultiboardSetItemWidthBJ( mb, 1, 0, 9 )
call MultiboardSetItemWidthBJ( mb, 2, 0, 7 )
set i = i + 1
endloop
call MultiboardDisplay(playerBoard[GetPlayerId(GetLocalPlayer())], true)
set i = 0
loop
exitwhen i>11
set playerAIControl[i] = false
set playerLimitRudders[i] = true
set playerAssistance[i] = true
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
if GetPlayerController(Player(i))==MAP_CONTROL_USER then
set o = object.createOnGround(Player(i),F22,-3584,i*512,0)
//set o = object.createOnGround(Player(i),DESTROYER,-3584,i*512,0)
//set o = object.create(Player(i),DESTROYER,vector.create(3000,2000+i*51,0),0,0,0)
else
set playerAIControl[i] = true
if GetRandomInt(0,1)==0 then
set o = object.create(Player(i),DESTROYER,vector.create(3000,2000+i*51,0),0,0,0)
else
set o = object.create(Player(i),F22,vector.create(3000,2000+i*51,3000),0,0,0)
endif
//set o = object.createOnGround(Player(i),F22,-3584,i*512,0)
//set o = object.create(Player(i),MIG29,vector.create(4000,-7000+i*51,4000),0,0,0)
set o.ctrl.wantLandingGears = false
//set o.targ = 1
endif
set playerControlledObj[i] = o
call CreateFogModifierRectBJ( true, Player(i), FOG_OF_WAR_VISIBLE, GetWorldBounds() )
endif
set i = i + 1
endloop
endfunction
//===========================================================================
function InitTrig_Multiboard takes nothing returns nothing
set gg_trg_Multiboard = CreateTrigger( )
call TriggerAddAction( gg_trg_Multiboard, function Trig_Multiboard_Actions )
call TriggerRegisterTimerEventSingle(gg_trg_Multiboard,0)
endfunction