coolDown = 0 bulletsFired = 0 timeSinceSeen = 999 lastSeenPos = Vec(0,0,0) lastAngle = 1 emission = nil function init() turret = FindBody("turret") turretShape = FindShape("turret") target = FindBody("head") hinge = FindJoint("hinge") eye = FindLight("eye") activate = FindTrigger("activate") turndirection = -1 emission = 0 --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("silenced0.ogg", 5) end function canSeeRobot() --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 the robot local robotPos if GetBool("level.espionagealarm") then robotPos = GetPlayerCameraTransform().pos else robotPos = GetBodyTransform(target).pos end local dirToRobot = VecNormalize(VecSub(robotPos, origin)) local distToRobot = VecLength(VecSub(robotPos, origin)) --The robot is seen when in front of turret and visible if VecDot(forward, dirToRobot) > 0 then QueryRejectBody(target) if QueryRaycast(origin, dirToRobot, distToRobot,0,true) then --Raycast hit something, that means the robot is not seen return false else --Raycast does not hit anything, the robot is seen! return true end else --Tthe robot is 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", 0.4) end function tick(dt) if not IsPointInTrigger(activate, GetPlayerCameraTransform().pos) then SetShapeEmissiveScale(turretShape,0) return end emission = emission - dt*2 --Check if seen local seen = canSeeRobot() if seen then if GetBool("level.espionagealarm") then lastSeenPos = GetPlayerCameraTransform().pos else lastSeenPos = GetBodyTransform(target).pos end timeSinceSeen = 0 else timeSinceSeen = timeSinceSeen + dt end --Turn towards the robot 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 then coolDown = coolDown - dt if coolDown < 0.20 then emission = 1 end if coolDown < 0 then fire() if not GetBool("level.espionagealarm") then bulletsFired = bulletsFired + 1 end if bulletsFired >= 5 then coolDown = 3.0 bulletsFired = 0 else coolDown = 0.14 end 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 the robot lastAngle = angle else --Robot not seen, keep oscilating between 25 and -25 degrees local turnangle = GetJointMovement(hinge) if turnangle > 25 and turndirection < 0 then turndirection = 0.5 end if turnangle < -25 and turndirection > 0 then turndirection = -0.5 end SetJointMotor(hinge, turndirection, 100) end SetShapeEmissiveScale(turretShape,emission) end