coolDown = 0 timeSinceSeen = 999 lastSeenPos = Vec(0,0,0) lastAngle = 1 function init() --Find handle to radio turret = FindBody("turret") hinge = FindJoint("hinge") eye = FindLight("eye") --Find gun position in turret local coordinate frame local gun = FindLocation("gun") local gunWorldPos = GetLocationTransform(gun).pos local turretTransform = GetBodyTransform(turret) gunLocalPos = TransformToLocalPoint(turretTransform, gunWorldPos) --Load sound from game assets gunSound = LoadSound("tools/gun0.ogg") end function canSeePlayer() --Use the area light transform to determine visiblity local t = GetLightTransform(eye) local origin = TransformToParentPoint(t, Vec(0, 0, 0.1)) local forward = TransformToParentVec(t, Vec(0, 0, 1)) --Direction and distance to player local playerPos = GetPlayerCameraTransform().pos local dirToPlayer = VecNormalize(VecSub(playerPos, origin)) local distToPlayer = VecLength(VecSub(playerPos, origin)) --Player is seen when in front of turret and visible if VecDot(forward, dirToPlayer) > 0 then if QueryRaycast(origin, dirToPlayer, distToPlayer) then --Raycast hit something, that means player is not seen return false else --Raycast does not hit anything, player is seen! return true end else --Player behind turret return false end end --This function will return the signed angle to provided position. This is used --to figure out which direction to turn the turret. function getTurretAngleTo(pos) local t = GetLightTransform(eye) local origin = TransformToParentPoint(t, Vec(0, 0, 0.1)) local forward = TransformToParentVec(t, Vec(0, 0, 1)) local dirToPos = VecNormalize(VecSub(pos, origin)) --Compute angle between forward directino and direction to pos local angle = math.acos(VecDot(forward, dirToPos)) --Check sign of cross product y component to determine sign of angle if VecCross(dirToPos, forward)[2] > 0 then return angle else return -angle end end function fire() --Find world space gun position and direction using the turret transform local turretTransform = GetBodyTransform(turret) local gunWorldPos = TransformToParentPoint(turretTransform, gunLocalPos) local forward = TransformToParentVec(turretTransform, Vec(0, 0, -1)) --Play sound, flash light and shoot PlaySound(gunSound, gunWorldPos) PointLight(gunWorldPos, 1, 0.8, 0.6, 5) Shoot(gunWorldPos, forward, "bullet") end function tick(dt) --Check if seen and remember the last seen position local seen = canSeePlayer() if seen then lastSeenPos = GetPlayerCameraTransform().pos timeSinceSeen = 0 else timeSinceSeen = timeSinceSeen + dt end --Turn towards player and shoot for a while even if no longer seen if timeSinceSeen < 2 then local angle = getTurretAngleTo(lastSeenPos) --If the angle is small, engage the gun if timeSinceSeen < 1 and math.abs(angle) < 0.2 and GetPlayerHealth() > 0 then coolDown = coolDown - dt if coolDown < 0 then fire() coolDown = 0.2 end end --Turn turret angle = angle * 3 if angle < -2 then angle = -2 end if angle > 2 then angle = 2 end SetJointMotor(hinge, angle, 100) --Remember the last angle to player lastAngle = angle else --Player not seen, keep rotating in direction of the last known angle if lastAngle > 0 then SetJointMotor(hinge, 1, 100) else SetJointMotor(hinge, -1, 100) end end end