-- LUA Script - precede every function and global member with lowercase name of script + '_main' local mooseVars = {} local Q = require "scriptbank\\quatlib" math.randomseed(os.time()) local sin = math.sin local cos = math.cos local rad = math.rad local deg = math.deg local abs = math.abs local min = math.min local max = math.max local asin = math.asin local atan = math.atan2 local modf = math.modf local sqrt = math.sqrt local random = math.random -- make sure random number generator is seeded random(); random(); random() local aim_sprite = nil function moose_init(e) Include("quatlib.lua") aim_sprite = CreateSprite(LoadImage ( "scriptbank\\Moose\\aim_sprite.png")) SetSpriteOffset(aim_sprite, -1 , 2) SetSpriteSize (aim_sprite, -1 , 4) SetSpriteDepth (aim_sprite, 0) SetSpritePosition (aim_sprite, 200, 200) end function MooseAddRocket(e) for k,v in pairs(mooseVars) do for i = 1,8 do if v.rockets[i] == nil then mooseVars[k].rockets[i] = e return true end end end return false end function MooseAddTurret(e) for k, v in pairs(mooseVars) do if v.turret == nil then v.turret = {Ent = e, cyAng = 0, tyAng = 0, cpAng = -5, tpAng = -5} return k end end return nil end function MooseAddCanopy(e) for k, v in pairs(mooseVars) do if v.canopy == nil then v.canopy = {Ent = e, Ang = 75, open = true} return k end end return nil end function MooseAddGun(e, side) for k, v in pairs(mooseVars) do if v.guns[side] == nil then StopAnimation(e) v.guns[side] = {Ent = e, animating = false, p = {x = 0, y = 0, z = 0}} return k end end return nil end local function CreateJoint(curAng, tgtAng, inc, maxVal) return {c = curAng, t = tgtAng, i = inc, m = maxVal, reached = true} end local function AngleReached(joint) return joint.reached end function MooseAddThigh(e, side) for k, v in pairs(mooseVars) do if v.thighs[side] == nil then v.thighs[side] = {Ent = e, x = 0, y = 0, z = 0, Joint1 = CreateJoint(45, 45, 0, 45), Joint2 = CreateJoint(0, 0, 0, 45)} return k end end return nil end function MooseAddShin(e) for k, v in pairs(mooseVars) do if v.shins['L'] == nil then v.shins['L'] = {Ent = e, x = 0, y = 0, z = 0, Joint = CreateJoint(-45, -45, 0, 45)} return k elseif v.shins['R'] == nil then v.shins['R'] = {Ent = e, x = 0, y = 0, z = 0, Joint = CreateJoint(-45, -45, 0, 45)} return k end end return nil end local function SetJoint(j, t, speed) if t > j.m then j.t = j.m elseif t < -j.m then j.t = -j.m else j.t = t end j.reached = false -- increment calculated based on 60FPS if j.t > j.c then j.i = ((j.t - j.c) / 600) * speed elseif j.c > j.t then j.i = ((j.c - j.t) / 600) * speed else -- angle already there j.i = 0 j.reached = true end end local function DoJoint(j) if j.t > j.c then if j.c < j.m then j.c = j.c + j.i end if j.t <= j.c then j.c = j.t j.reached = true end elseif j.t < j.c then if j.c > -j.m then j.c = j.c - j.i end if j.t >= j.c then j.c = j.t j.reached = true end else j.reached = true end end function MooseAddFoot(e) for k, v in pairs(mooseVars) do if v.feet['L'] == nil then v.feet['L'] = {Ent = e, Obj = g_Entity[e].obj, grounded = false, Joint = CreateJoint(0, 0, 0.02, rad(45))} return k elseif v.feet['R'] == nil then v.feet['R'] = {Ent = e, Obj = g_Entity[e].obj, grounded = false, Joint = CreateJoint(0, 0, 0.02, rad(45))} return k end end return nil end local function Rotate3D (x, y, z, xrot, yrot, zrot) function RotatePoint2D (x, y, Ang) -- Ang in radians local Sa, Ca = sin(Ang), cos(Ang) return x*Ca - y*Sa, x*Sa + y*Ca end local NX, NY, NZ = x, y, z -- X NZ, NY = RotatePoint2D (NZ, NY, -xrot) -- Y NX, NZ = RotatePoint2D (NX, NZ, -yrot) -- Z NY, NX = RotatePoint2D (NY, NX, -zrot) return NX, NY, NZ end local function GetHeightUnderfoot(f, xo, yo, zo) local x, y, z = f.pos.x + xo, f.pos.y + yo, f.pos.z + zo local gy = GetTerrainHeight(x, z) if gy >= y then return gy, gy - y else -- check if entity underfoot local obj = IntersectAll(x, y + 30, z, x, gy - 5, z, f.Obj) if obj and obj ~= 0 then local objy = GetIntersectCollisionY() if objy > gy then gy = objy end if gy >= y then return gy, gy - y else return gy, y - gy end else -- for now stick to terrain return gy, y - gy end end end local function FootAngle(f, xA, yA, zA) -- back of foot local xo, yo, zo = Rotate3D(0, -20, -10, xA, yA, zA) local h1, Y1 = GetHeightUnderfoot(f, xo, yo, zo) -- front of foot xo, yo, zo = Rotate3D(0, -20, 50, xA, yA, zA) local h2, Y2 = GetHeightUnderfoot(f, xo, yo, zo) -- centre of foot xo, yo, zo = Rotate3D(0, -20, 20, xA, yA, zA) local h3, Y3 = GetHeightUnderfoot(f, xo, yo, zo) local Ang = asin( (h2 - h1) / 60) local yOff = min(Y1, Y2, Y3) if yOff <= 0 then f.grounded = true else f.grounded = false yOff = 0 end f.ghl = max(h1, h2, h3) return Ang, yOff end local fo = {x = 0, y = -67.63, z = 4.52} local function PositionFoot(side, v, x, y, z, xA, yA, zA) local xO, yO, zO = Rotate3D (fo.x, fo.y, fo.z, xA, yA, zA) local foot = v.feet[side] foot.pos = {x = x + xO, y = y + yO, z = z + zO} -- rotate foot to match terrain or Entity under foot foot.Joint.t, yo = FootAngle(foot, xA, yA, zA) DoJoint(foot.Joint) if yo < 0 then foot.pos.y = foot.pos.y + yo end ResetPosition(foot.Ent, foot.pos.x, foot.pos.y, foot.pos.z) local quat = Q.Mul(v.quat, Q.FromEuler(foot.Joint.c, rad(v.thighs[side].Joint2.c),0)) local fxA, fyA, fzA = Q.ToEuler(quat) ResetRotation(foot.Ent, deg(fxA), deg(fyA), deg(fzA)) return yo end local so = {x = -0.55, y = -91.34, z = 5.78} local function PositionShin(side, v, x, y, z, xA, yA, zA) local xO, yO, zO = Rotate3D (so.x, so.y, so.z, xA, yA, zA) local shin = v.shins[side] local sx, sy, sz = x + xO, y + yO, z + zO shin.x, shin.y, shin.z = sx, sy, sz DoJoint(shin.Joint) local quat = Q.Mul(v.quat, Q.FromEuler(rad(shin.Joint.c),rad(v.thighs[side].Joint2.c),0)) local sxA, syA, szA = Q.ToEuler(quat) ResetRotation(shin.Ent, deg(sxA), deg(syA), deg(szA)) yo = PositionFoot(side, v, sx, sy, sz, sxA, syA, szA) ResetPosition(shin.Ent, sx, sy + yo, sz) return yo end local legOffsets = {['L'] = {x = -37.54, y = -0.3, z = 0.1}, ['R'] = {x = 37.54, y = -0.3, z = 0.1} } local function PositionLeg(side, v, xA, yA, zA) local lo = legOffsets[side] local xO, yO, zO = Rotate3D (lo.x, lo.y, lo.z, xA, yA, zA) local thigh = v.thighs[side] local tx, ty, tz = v.x + xO, v.y + yO, v.z + zO thigh.x, thigh.y, thigh.z = tx, ty, tz local quat = Q.FromEuler(rad(thigh.Joint1.c),rad(thigh.Joint2.c),0) DoJoint(thigh.Joint1) DoJoint(thigh.Joint2) local txA, tyA, tzA = Q.ToEuler(Q.Mul(v.quat, quat)) ResetRotation(thigh.Ent, deg(txA), deg(tyA), deg(tzA)) yo = PositionShin(side, v, tx, ty, tz, txA, tyA, tzA) ResetPosition(thigh.Ent, tx, ty + yo, tz) return yo end local hipMax = 10 local hipInc = 0.5 local function PositionMoose(e, v, xA, yA, zA) local leftFoot = v.feet['L'] local rightFoot = v.feet['R'] local hxA, hyA, hzA = xA, yA, zA if v.ftDown == 'L' then if v.hipLean > -hipMax then v.hipLean = v.hipLean - hipInc end elseif v.ftDown == 'R' then if v.hipLean < hipMax then v.hipLean = v.hipLean + hipInc end else v.hipLean = v.hipLean / 2 end local quat = Q.FromEuler(rad(v.turret.cpAng / 2), rad(v.rotAng), rad(v.hipLean)); hxA, hyA, hzA = Q.ToEuler(Q.Mul(v.quat, quat)) ResetRotation(e, deg(hxA), deg(hyA), deg(hzA)) local y1 = PositionLeg('L', v, hxA, hyA, hzA) local y2 = PositionLeg('R', v, hxA, hyA, hzA) if abs(y1) > abs(y2) then v.y = v.y + y1 else v.y = v.y + y2 end ResetPosition(e, v.x, v.y, v.z) if not leftFoot.grounded and not rightFoot.grounded or leftFoot.grounded and rightFoot.grounded then local lftd = leftFoot.pos.y - 20 - leftFoot.ghl local rftd = rightFoot.pos.y - 20 - rightFoot.ghl if lftd < rftd then v.y = v.y - lftd else v.y = v.y - rftd end end end local function DoRocket(e, x, y, z, xo, yo, zo, xA, yA, zA) local XO, YO, ZO = Rotate3D (xo, yo, zo, xA, yA, zA) ResetPosition(e, x + XO, y + YO, z + ZO) ResetRotation(e, deg(xA), deg(yA), deg(zA)) end local gunBarrelPosBot = {} local gunBarrelPosTop = {} local gbo = {['T'] = {x = 0, y = 10.3, z = 98}, ['B'] = {x = 0, y = 5.8, z = 70} } local function SaveBarrelPos (e, bar, gx, gy, gz, xA, yA, zA) local b = gbo[bar] local XO, YO, ZO = Rotate3D (b.x, b.y, b.z, xA, yA, zA) if bar == 'B' then gunBarrelPosBot[e] = {x = gx + XO, y = gy + YO, z = gz + ZO, xA = xA, yA = yA, zA = zA} else gunBarrelPosTop[e] = {x = gx + XO, y = gy + YO, z = gz + ZO, xA = xA, yA = yA, zA = zA} end end local gunRange = 5000 function MoosePositionMF(e, gun, barrel, firstTime) local pos = nil if barrel == 'B' then pos = gunBarrelPosBot[gun] else pos = gunBarrelPosTop[gun] end if pos ~= nil then ResetPosition(e, pos.x, pos.y, pos.z) if firstTime then local XO, YO, ZO = Rotate3D (0, 0, gunRange, pos.xA, pos.yA, pos.zA) MooseBhPos (pos.x, pos.y, pos.z, pos.x + XO, pos.y + YO, pos.z + ZO) local spd = random(25,35) if MooseTracerRound ~= nil then MooseTracerRound(pos.x, pos.y, pos.z, XO / spd, YO / spd, ZO / spd) end end end end local go = {['L'] = {x = 61, y = -16, z = 42}, ['R'] = {x = -61, y = -16, z = 41} } local function PositionGun(side, v, x, y, z, xA, yA, zA) local GO = go[side] local gun = v.guns[side] local XO, YO, ZO = Rotate3D (GO.x, GO.y, GO.z, xA, yA, zA) local gx, gy, gz = x + XO, y + YO, z + ZO ResetPosition(gun.Ent, gx, gy, gz) ResetRotation(gun.Ent, deg(xA), deg(yA), deg(zA)) gun.p = {x = gx, y = gy, z = gz} SaveBarrelPos(gun.Ent, 'T', gx, gy, gz, xA, yA, zA) SaveBarrelPos(gun.Ent, 'B', gx, gy, gz, xA, yA, zA) end local rp = {{x = -67.89, y = 40.07, z = -21.46}, {x = -56.57, y = 40.07, z = -21.46}, {x = -67.89, y = 30.88, z = -21.46}, {x = -56.45, y = 30.88, z = -21.46}, {x = 67.43, y = 40.07, z = -21.46}, {x = 55.40, y = 40.07, z = -21.46}, {x = 67.43, y = 30.43, z = -21.46}, {x = 55.40, y = 30.43, z = -21.46} } local function DisplayRockets(v, tx, ty, tz, txA, tyA, tzA) for i = 1,8 do if v.rockets[i] ~= nil then local r = rp[i] DoRocket(v.rockets[i], tx, ty, tz, r.x, r.y, r.z, txA, tyA, tzA) end end end local function WrapAngle(ang) if ang > 180 then return ang - 360 elseif ang < -180 then return ang + 360 end return ang end local function mf(val) return modf(val + 0.5) .. ", " end local function AttachPlayer( v, tx, ty, tz, xA, yA, zA ) local xo, yo, zo = Rotate3D( 10, 55, 10 - v.turret.cpAng / 2, xA, yA, zA ) SetFreezePosition( tx + xo, ty + yo, tz + zo ) if MooseAddJoystick ~= nil then xo, yo, zo = Rotate3D( 10, 80, 10, xA, yA, zA ) MooseAddJoystick(tx + xo, ty + yo, tz + zo, 15 - v.turret.cpAng, v.vmAng, 0) end if not v.lookAround then SetFreezeAngle( 15 - v.turret.cpAng, v.vmAng, 0 ) TransportToFreezePosition() SetSpritePosition (aim_sprite, 50, 30) if g_KeyPressR == 1 then xo, yo, zo = Rotate3D( 100, 100, -200, xA, yA, zA ) PositionCamera( 0, tx + xo, ty + yo, tz + zo) end else TransportToFreezePositionOnly() local paY = WrapAngle(g_PlayerAngY) local yoff = WrapAngle(v.vmAng - paY) local paX = WrapAngle(g_PlayerAngX) if yoff < 50 and yoff > -50 then SetSpritePosition (aim_sprite, 50 + yoff, 60 - paX * 1.5) else SetSpritePosition (aim_sprite, 200, 200) end end end local co = {x = -11.07, y = 104.9, z = 34.18} local function PositionCanopy(v, x, y, z, xA, yA, zA) local xO, yO, zO = Rotate3D (co.x, co.y, co.z, xA, yA, zA) ResetPosition(v.canopy.Ent, x + xO, y + yO, z + zO) local quat = Q.FromEuler(rad(v.canopy.Ang), 0, 0) quat = Q.Mul(v.turret.quat, quat) local txA, tyA, tzA = Q.ToEuler(quat) ResetRotation(v.canopy.Ent, deg(txA), deg(tyA), deg(tzA)) end local function PositionTurret(v, xA, yA, zA) local xO, yO, zO = Rotate3D (0, -0.5, 22.24, xA, yA, zA) local turret = v.turret local tx, ty, tz = v.x + xO, v.y + yO, v.z + zO ResetPosition(turret.Ent, tx, ty, tz) local quat = Q.FromEuler(rad(turret.cpAng),rad(turret.cyAng),0) turret.quat = Q.Mul(v.quat, quat) local txA, tyA, tzA = Q.ToEuler(turret.quat) ResetRotation(turret.Ent, deg(txA), deg(tyA), deg(tzA)) local mX, mY, mZ = Rotate3D( 0, 0, 1, txA, tyA, tzA ) v.vmAng = deg( atan( mX, mZ ) ) PositionCanopy( v, tx, ty, tz, txA, tyA, tzA) if v.playerOnBoard then AttachPlayer(v, tx, ty, tz, txA, tyA, tzA) end PositionGun('L', v, tx, ty, tz, txA, tyA, tzA) PositionGun('R', v, tx, ty, tz, txA, tyA, tzA) DisplayRockets(v, tx, ty, tz, txA, tyA, tzA) end local function GotEnts(e, v) if v.turret == nil then PromptLocal(e, "No turret!") return false end if v.canopy == nil then PromptLocal(e, "No canopy!") return false end if v.thighs['L'] == nil or v.thighs['R'] == nil then PromptLocal(e, "Not enough thigh entities!") return false end if v.shins['L'] == nil or v.shins['R'] == nil then PromptLocal(e, "Not enough shin entities!") return false end if v.feet['L'] == nil or v.feet['R'] == nil then PromptLocal(e, "Not enough feet entities!") return false end if v.guns['L'] == nil or v.guns['R'] == nil then PromptLocal(e, "Not enough guns entities!") return false end return true end local function fireRocket(v) local t = v.turret while true do local i = random(1,8) if v.rockets[i] ~= nil then if mrFire ~= nil then mrFire(v.rockets[i], t.quat, g_Entity[t.Ent].obj) v.rockets[i] = nil return end end end end local function rocketsLeft(v) for i = 1,8 do if v.rockets[i] ~= nil then return true end end return false end local maxSpeed = 2.5 local acceleration = 0.03 local turnQuat = Q.FromEuler(0, rad(0.05), 0) local function MoveMoose(v, xA, yA, zA) local mx, my, mz = Rotate3D (0, 0, maxSpeed / 10, xA, yA, zA) -- v.x, v.z = v.x + mx, v.z + mz -- v.quat = Q.Mul(v.quat, turnQuat) end local minVolume = 4000 * 4000 local volModifier = 0 local function SetVolume(Ent, num, x, z, Px, Pz) local dx, dz = Px - x, Pz - z local sqDist = dx*dx + dz*dz local vol = minVolume - sqDist if vol > 0 then vol = 60 + (37 * (vol / minVolume)) - volModifier else vol = 0 end SetSound(Ent, num) SetSoundVolume(vol) end local step = false local FstepTgt = 30 local RstepTgt = -30 local function MoveLegs(v, Px, Pz) local lT = v.thighs['L'] local rT = v.thighs['R'] local lS = v.shins ['L'] local rS = v.shins ['R'] -- AngleReached(lT.Joint1) if not step then v.ftDown = 'R' SetJoint (lT.Joint1, FstepTgt, maxSpeed * 2) SetJoint (lS.Joint, -40, maxSpeed * 3) SetJoint (rT.Joint1, -20, maxSpeed) SetJoint (rS.Joint, 0, maxSpeed * 2) PlaySound(rT.Ent, 0) SetVolume(rT.Ent, 0, rT.x, rT.z, Px, Pz) step = true return end if AngleReached(lT.Joint1) then if lT.Joint1.c > 0 then PlaySound(lT.Ent, 0) SetVolume(lT.Ent, 0, lT.x, lT.z, Px, Pz) SetJoint (lT.Joint1, RstepTgt, maxSpeed) v.ftDown = 'L' else SetJoint(lT.Joint1, FstepTgt, maxSpeed * 2) end end if AngleReached(rT.Joint1) then if rT.Joint1.c < 0 then SetJoint (rT.Joint1, FstepTgt, maxSpeed * 2) else PlaySound(rT.Ent, 0) SetVolume(rT.Ent, 0, rT.x, rT.z, Px, Pz) SetJoint (rT.Joint1, RstepTgt, maxSpeed) v.ftDown = 'R' end end if lT.Joint1.c < -10 and lS.Joint.t ~= -40 then SetJoint (lS.Joint, -40, maxSpeed * 3) PlaySound(lS.Ent, 0) SetVolume(lS.Ent, 0, lS.x, lS.z, Px, Pz) end if rT.Joint1.c < -10 and rS.Joint.t ~= -40 then SetJoint (rS.Joint, -40, maxSpeed * 3) PlaySound(rS.Ent, 0) SetVolume(rS.Ent, 0, rS.x, rS.z, Px, Pz) end if lT.Joint1.c > 20 and lS.Joint.t ~= 0 then SetJoint (lS.Joint, 0, maxSpeed * 3) end if rT.Joint1.c > 20 and rS.Joint.t ~= 0 then SetJoint (rS.Joint, 0, maxSpeed * 3) end end local function CloserThan(x1, z1, x2, z2, dist) local dx, dz = x1 - x2, z1 - z2 return dx*dx + dz*dz < dist * dist end local function HandleWeapons(e, v, Px, Pz) if rocketsLeft(v) and v.fireRocket then if not v.rocketFired then fireRocket(v) v.rocketFired = true end end if MfShoot ~= nil and v.shootGun then if random(1,5) == 3 then local gun = random(1,2) local bar = random(1,2) if gun == 1 then gun = 'L' else gun = 'R' end if bar == 1 then bar = 'T' else bar = 'B' end local g = v.guns[gun] MfShoot(g.Ent, bar) PlaySoundIfSilent(g.Ent, 0) SetVolume(g.Ent, 0, g.p.x, g.p.z, Px, Pz) end end end local EbutPressed = false local lastMMX, lastMMY = 0, 0 local turretMaxAng = 45 local turretInc = 0.5 local function HandlePlayerControl(v) if (bit32.band(g_MouseClickControl,1)) ~= 0 then v.shootGun = true else v.shootGun = false StopSound (v.guns['L'].Ent, 0) StopSound (v.guns['R'].Ent, 0) end if (bit32.band(g_MouseClickControl,2)) ~= 0 then if not v.fireRocket then v.fireRocket = true end else v.fireRocket = false v.rocketFired = false end if g_KeyPressE == 1 then if not EbutPressed then EbutPressed = true v.lookAround = not v.lookAround if v.lookAround then PromptDuration('Look around mode selected', 2000) end end else EbutPressed = false end if not v.lookAround then local mx, my = MouseMoveX(), MouseMoveY() if mx < 0 then if v.turret.tyAng > -turretMaxAng then v.turret.tyAng = v.turret.tyAng - turretInc end elseif mx > 0 then if v.turret.tyAng < turretMaxAng then v.turret.tyAng = v.turret.tyAng + turretInc end end local diff = v.turret.tyAng - v.turret.cyAng if abs(diff) > 0.01 then v.turret.cyAng = v.turret.cyAng + (diff / 20) end if my > 0 then if v.turret.tpAng < 25 then v.turret.tpAng = v.turret.tpAng + turretInc end elseif my < 0 then if v.turret.tpAng > -15 then v.turret.tpAng = v.turret.tpAng - turretInc end end diff = v.turret.tpAng - v.turret.cpAng if abs(diff) > 0.01 then v.turret.cpAng = v.turret.cpAng + diff / 20 end end end function moose_main(e) local v = mooseVars[e] if v == nil then local Ent = g_Entity[e] mooseVars[e] = {state = 'init', hipLean = 0, ftDown = 'N', thighs = {}, shins = {}, feet = {}, turret = nil, canopy = nil, rockets = {}, guns = {}, shootGun = false, fireRocket = false, rocketFired = false, x = Ent.x, z = Ent.z, y = Ent.y + 300, quat = Q.FromEuler(0, 0, 0), vmAng = 0, rotAng = 0, turnAng = 0, speed = 0, timer = math.huge, angleInc = 0.27, yAngInc = 0.17, playerOnBoard = false, lookAround = false } return end if v.state == 'init' and GotEnts(e, v) then v.state = 'idle' v.timer = g_Time + random(3000,5000) end if v.state == 'idle' and g_Time > v.timer then if CloserThan(v.x, v.z, g_PlayerPosX, g_PlayerPosZ, 150) then v.state = 'board' v.timer = g_Time + 2000 end end if v.state == 'board' then if g_Time > v.timer then v.playerOnBoard = true v.state = 'close' else Prompt("Boarding") v.firstPass = true end end if v.state ~= 'init' then local xA, yA, zA = Q.ToEuler(v.quat) if abs(yA) == 90 then yA = yA + 0.0001 end PositionMoose(e, v, xA, yA, zA) if v.turret ~= nil then PositionTurret(v, xA, yA, zA) end end if v.state == 'idle' then return end if v.state == 'close' then -- close canopy if v.canopy.open then if v.canopy.Ang > -3 then v.canopy.Ang = v.canopy.Ang - 1 elseif v.playerOnBoard then volModifier = 13 v.canopy.open = false end else v.state = 'stand' PromptDuration('Press E to toggle look around', 3000) end end if v.state == 'stand' then local Px, Pz = g_PlayerPosX, g_PlayerPosZ local lT = v.thighs['L'] local rT = v.thighs['R'] local lS = v.shins['L'] local rS = v.shins['R'] if lT.Joint1.c == 45 then SetJoint (lT.Joint1, 10, 3) PlaySound(lT.Ent, 0) SetJoint (rT.Joint1, 10, 3) PlaySound(rT.Ent, 0) SetJoint (lS.Joint, -10, 3) PlaySound(lS.Ent, 0) SetJoint (rS.Joint, -10, 3) PlaySound(rS.Ent, 0) end if not AngleReached(lT.Joint1) then SetVolume(lT.Ent, 0, lT.x, lT.z, Px, Pz) SetVolume(rT.Ent, 0, rT.x, rT.z, Px, Pz) SetVolume(lS.Ent, 0, lS.x, lS.z, Px, Pz) SetVolume(rS.Ent, 0, rS.x, rS.z, Px, Pz) else v.state = 'move' end end if v.state == 'move' then if v.playerOnBoard then HandlePlayerControl(v) end local Px, Pz = g_PlayerPosX, g_PlayerPosZ local xA, yA, zA = Q.ToEuler(v.quat) MoveMoose(v, xA, yA, zA) --MoveLegs(v, Px, Pz) --MoveTurret(v) HandleWeapons(e, v, Px, Pz) end end