#include "script/common.lua" local train = FindShape("train") local explosivebox = FindShapes("explosivebox", true) local railtrigger = FindTrigger("railtrigger") local gameovertrigger = FindTrigger("gameovertrigger") local breakpoint = nil local stopped = false local starttrailpoint = FindLocation("starttrailpoint", true) local oceanTrigger = FindTrigger("ocean") function rnd(mi, ma) return math.random(1000)/1000*(ma-mi) + mi end function rndVec(t) return Vec(rnd(-t, t), rnd(-t, t), rnd(-t, t)) end function init() vehicle = FindVehicle() blinkShape = FindShape("blink") detonatorShape = FindShape("detonator") target = FindBody("target") frame = 0 win = false winTimer = 0 explosionPos = Vec() deadCamDist = 10 deadTime = 0 deadExplosion = false deadExplosion2 = false deadExplosion3 = false end function update(dt) frame = frame + 1 if dead then deadCamDist = deadCamDist + 0.03 return end if frame%30 > 15 then SetShapeEmissiveScale(blinkShape, 1) else SetShapeEmissiveScale(blinkShape, 0) end end function tickExplosion(dt) deadTime = deadTime + dt if deadTime > 0.3 and not deadExplosion then Explosion(explosionPos, 4.0) SetString("level.state", "fail_dead") deadExplosion = true end if deadTime > 0.6 and not deadExplosion2 then Explosion(VecAdd(explosionPos, Vec(-2, 0, 2)), 4.0) deadExplosion2 = true end if deadTime > 0.9 and not deadExplosion3 then Explosion(VecAdd(explosionPos, Vec(-4, 0, -2)), 4.0) deadExplosion3 = true end local target = explosionPos local dir = VecNormalize(Vec(1, 1, -1)) local eye = VecAdd(target, VecScale(dir, deadCamDist)) local t = Transform(eye, QuatLookAt(eye, target)) SetCameraTransform(t, 90) SetTimeScale(0.2) ParticleTile(5) ParticleCollide(0) ParticleColor(1, 0.6, 0.4, 1, 0.3, 0.2) ParticleEmissive(6.0, 0.0, "easeout") ParticleAlpha(math.min(1.0, deadTime), 0) ParticleRadius(0.3, 5.0) for i=1, 5 do SpawnParticle(target, Vec(rnd(-5, 5), rnd(0, 2), rnd(-5,5)), rnd(0.5, 1.0)*(1.0+deadTime)*2.0) end ParticleReset() ParticleType("plain") ParticleColor(0.8, 0.75, 0.7) ParticleAlpha(math.min(1.0, deadTime), 0) ParticleRadius(0.4, 3.0) for i=1, 5 do SpawnParticle(target, Vec(rnd(-8, 8), rnd(0, 2), rnd(-8,8)), rnd(0.5, 1.0)*(1.0+deadTime)*2.0) end PointLight(VecAdd(target, Vec(0, 1, 0)), 1, 0.5, 0.2, 1000*math.min(1.0, deadTime)) end function tick(dt) local vt = GetVehicleTransform(vehicle) if dead then tickExplosion(dt) end if win then winTimer = winTimer + dt local target = winPos local dir = VecNormalize(Vec(1, 0.5, -1)) local eye = VecAdd(target, VecScale(dir, 40.0)) local t = Transform(eye, QuatLookAt(eye, target)) SetCameraTransform(t, 90) if winTimer > 1.0 then SetString("level.state", "win") end end if not stopped then DriveVehicle(vehicle, 1.0, 0) if not dead and not win then local mi, ma = GetShapeBounds(detonatorShape) local origin = VecLerp(mi, ma, 0.5) local dir = TransformToParentVec(vt, Vec(0, 0, -1)) QueryRejectShape(detonatorShape) QueryRequire("physical large") local LINE_DIST = 10 local hit, dist = QueryRaycast(origin, dir, LINE_DIST) if not hit then dist = LINE_DIST end local current = math.mod(GetTime(), 1.0) - 0.5 for i=1, LINE_DIST do local p0 = VecAdd(origin, VecScale(dir, current)) local d = math.min(current + 0.5, dist) local p1 = VecAdd(origin, VecScale(dir, d)) DrawLine(p0, p1, 1, 1, 1, 0.5 * (1.0-(i/LINE_DIST))) current = current + 1.0 if current > dist then break end end end if not dead then local fwd = TransformToParentVec(vt, Vec(-1, 0, 0)) local vb = GetVehicleBody(vehicle) local com = TransformToParentPoint(GetBodyTransform(vb), Vec(0, 0, -3)) fwd[2] = 0 fwd = VecNormalize(fwd) ConstrainVelocity(vb, 0, com, fwd, 1, 0, 10000) end --if not dead and not win and IsVehicleInTrigger(oceanTrigger, vehicle) then --win = true --winPos = vt.pos --SetTag(target, "target", "cleared") --end end end function update(dt) if not stopped then UnderHeistCheck() end if IsPointInTrigger(gameovertrigger, GetShapeWorldTransform(train).pos) and GetString("level.state") == "" then SetString("level.state", "fail") end --if GetBool("level.alarm") and not GetBool("challenge.balloon1") and GetFloat("level.alarmtimer") < 30 then --SetBool("challenge.balloon1", true) --end end function handleCommand(cmd) local words = splitString(cmd, " ") if not dead then if #words == 5 then if words[1] == "explosion" then local x = tonumber(words[3]) local y = tonumber(words[4]) local z = tonumber(words[5]) for i = 1, #explosivebox do if VecLength(VecSub(Vec(x,y,z), GetShapeWorldTransform(explosivebox[i]).pos)) < 3 and not dead then explosionPos = Vec(x,y,z) deadCamDist = 8 deadTime = 0 dead = true end end if not dead then if IsPointInTrigger(railtrigger, Vec(x,y,z)) then if VecLength(VecSub(GetLocationTransform(starttrailpoint).pos, GetShapeWorldTransform(train).pos)) < VecLength(VecSub(GetLocationTransform(starttrailpoint).pos, Vec(x,y,z))) then if breakpoint ~= nil and VecLength(VecSub(GetLocationTransform(starttrailpoint).pos, Vec(x,y,z))) < VecLength(VecSub(GetLocationTransform(starttrailpoint).pos, breakpoint)) then breakpoint = Vec(x,y,z) elseif breakpoint == nil then breakpoint = Vec(x,y,z) end end end end end elseif #words == 8 then if words[1] == "shot" then local x = tonumber(words[3]) local y = tonumber(words[4]) local z = tonumber(words[5]) for i = 1, #explosivebox do local hit, point = GetShapeClosestPoint(explosivebox[i], Vec(x,y,z)) if not dead and hit and VecLength(VecSub(Vec(x,y,z),point)) < 0.08 then explosionPos = Vec(x,y,z) deadCamDist = 8 deadTime = 0 dead = true end end end end end end function UnderHeistCheck() if VecLength(VecSub(GetShapeWorldTransform(train).pos, breakpoint)) < 10 then if not GetBool("level.alarm") then SetFloat("level.alarmtimer", 60) SetBool("level.alarm", true) end stopped = true end for i = 1, #explosivebox do if GetPlayerGrabShape() == explosivebox[i] and not GetBool("level.alarm") then SetFloat("level.alarmtimer", 60) SetBool("level.alarm", true) end end end