Guest User

Script.

a guest
Oct 30th, 2019
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.07 KB | None | 0 0
  1. local SwingTrack = nil
  2. local TuckTrack = nil
  3.  
  4. local SKI_MESH = 142468161
  5. local POLE_MESH = 142468332 -- PUT TO NIL OR 0 IF NO POLE WANTED
  6. local POLE_TEXTURE = 0 -- CHANGE ASAP
  7. local SKI_TX1 = 1664957640
  8. local SKI_TX2 = 1664957640
  9.  
  10. --- FRICTION COEFFIECIENTS ---
  11. local KineticWoodSnow = 0.1
  12. local KineticSkiSnow = 0.05
  13. local StaticWoodSnow = 0.14
  14. local StaticSkiSnow = 0.1
  15.  
  16. local BodyVelocity = nil
  17. local BodyGyro = nil
  18.  
  19. local Tool = script.Parent
  20. local Handle = Tool:WaitForChild('Handle')
  21.  
  22.  
  23. local SKI_SWING_ANIM = Tool:WaitForChild('Swing')
  24. local SKI_TUCK_ANIM = Tool:WaitForChild('Tuck')
  25.  
  26. local PlayersService = Game:GetService('Players')
  27.  
  28. local Character, Torso, LeftLeg, RightLeg = nil
  29. local Skis = {}
  30.  
  31. local function New(ty)
  32. return function(data)
  33. local obj = Instance.new(ty)
  34. for k, v in pairs(data) do
  35. if type(k) == 'number' then
  36. v.Parent = obj
  37. else
  38. if type(v) == 'function' then
  39. obj[k]:connect(v)
  40. else
  41. obj[k] = v
  42. end
  43. end
  44. end
  45. return obj
  46. end
  47. end
  48.  
  49. local function GetAssetUrl(assetId)
  50. return 'http://www.roblox.com/asset/?id=' .. tostring(assetId)
  51. end
  52.  
  53. local function GetCharacter()
  54. if PlayersService:GetPlayerFromCharacter(Tool.Parent) then
  55. return Tool.Parent
  56. end
  57. end
  58.  
  59. local function GetTorso()
  60. return GetCharacter() and GetCharacter():FindFirstChild('HumanoidRootPart')
  61. end
  62.  
  63. local function GetLeftLeg()
  64. return GetCharacter() and GetCharacter():FindFirstChild('Left Leg')
  65. end
  66.  
  67. local function GetRightLeg()
  68. return GetCharacter() and GetCharacter():FindFirstChild('Right Leg')
  69. end
  70.  
  71. local function GetPlayer()
  72. return PlayersService:GetPlayerFromCharacter(Tool.Parent)
  73. end
  74.  
  75. local function GetLA()
  76. return GetCharacter() and GetCharacter():FindFirstChild('Left Arm')
  77. end
  78.  
  79. local function GetRA()
  80. return GetCharacter() and GetCharacter():FindFirstChild('Right Arm')
  81. end
  82.  
  83. local NormalIdToSurfaceId =
  84. {
  85. [Enum.NormalId.Back] = 'BackSurface';
  86. [Enum.NormalId.Front] = 'FrontSurface';
  87. [Enum.NormalId.Left] = 'LeftSurface';
  88. [Enum.NormalId.Right] = 'RightSurface';
  89. [Enum.NormalId.Top] = 'TopSurface';
  90. [Enum.NormalId.Bottom] = 'BottomSurface';
  91. }
  92.  
  93. local function ClassifySurface(part, point)
  94. local psize = part.Size
  95. local localPoint = part.CFrame:pointToObjectSpace(point)
  96. local posDiff = psize/2 - localPoint
  97. local negDiff = psize/2 + localPoint
  98. local minDiff = Vector3.new(
  99. math.min(math.abs(posDiff.x), math.abs(negDiff.x)),
  100. math.min(math.abs(posDiff.y), math.abs(negDiff.y)),
  101. math.min(math.abs(posDiff.z), math.abs(negDiff.z)))
  102.  
  103. if minDiff.x <= math.min(minDiff.y, minDiff.z) then -- On x-axis
  104. if math.abs(posDiff.x) < math.abs(negDiff.x) then
  105. return Enum.NormalId.Right
  106. else
  107. return Enum.NormalId.Left
  108. end
  109. elseif minDiff.y <= minDiff.z then -- On y-axis
  110. if math.abs(posDiff.y) < math.abs(negDiff.y) then
  111. return Enum.NormalId.Top
  112. else
  113. return Enum.NormalId.Bottom
  114. end
  115. else -- On z-axis
  116. if math.abs(posDiff.z) < math.abs(negDiff.z) then
  117. return Enum.NormalId.Back
  118. else
  119. return Enum.NormalId.Front
  120. end
  121. end
  122. end
  123.  
  124.  
  125. local function GetNormal(part, point)
  126. local normal = ClassifySurface(part, point)
  127. return ((part.CFrame-part.CFrame.p)*Vector3.FromNormalId(normal))
  128. end
  129.  
  130. local function AngleFromFlat(vec1)
  131. local vec1 = vec1.unit
  132. local flatVec = (vec1 * Vector3.new(1,0,1)).unit
  133. local angle = math.acos(vec1:Dot(flatVec))
  134. -- if the angle is nan then assume flat surface
  135. if angle ~= angle then
  136. return math.rad(90)
  137. end
  138. return math.rad(90) - angle
  139. end
  140.  
  141. ------ RAYCASTING FUNCTIONS ---------
  142.  
  143. -- Defaulted ray ignore check if none specified
  144. local function RayIgnoreCheck(hit, pos)
  145. return false
  146. end
  147.  
  148. local function RayIgnoreCamera(hit, pos)
  149. if hit then
  150. if hit.CanCollide == false then return true end
  151. end
  152. return false
  153. end
  154.  
  155. -- @preconditions: vec should be a unit vector, and 0 < rayLength <= 1000
  156. local function RayCast(startPos, vec, rayLength, ignoreFunc, ignoreList)
  157. ignoreFunc = ignoreFunc or RayIgnoreCheck
  158. ignoreList = ignoreList or {GetCharacter()}
  159. vec = vec.unit
  160. local ray = Ray.new(startPos, vec*rayLength)
  161. local hitObject, hitPos = Workspace:FindPartOnRayWithIgnoreList(ray, ignoreList)
  162. if hitObject and hitPos then
  163. if ignoreFunc(hitObject, hitPos) then
  164. table.insert(ignoreList, hitObject)
  165. return RayCast(startPos, vec, rayLength, ignoreFunc, ignoreList)
  166. end
  167. end
  168. return hitObject, hitPos
  169. end
  170.  
  171. ------ END RAYCASTING FUNCTIONS ---------
  172.  
  173.  
  174. local function GetGroundBelowCharacter(character)
  175. local torso = GetTorso(character)
  176. local leftLeg = GetLeftLeg()
  177. if torso and leftLeg then
  178. local torsoCFrame = torso.CFrame
  179. local hitData = {}
  180. for z = -1, 1, 2 do
  181. for x = -1, 1, 2 do
  182. local hit, pos = RayCast(
  183. torsoCFrame.p + torsoCFrame:vectorToWorldSpace(Vector3.new(torso.Size.X/2*x,0,torso.Size.Z/2*z)),
  184. Vector3.new(0,-1,0),
  185. torso.Size.Y/2 + leftLeg.Size.Y + 6,
  186. RayIgnoreCamera)
  187. if hit and pos then
  188. table.insert(hitData, {['Pos'] = CFrame.new(Vector3.new(torsoCFrame.p.X, pos.Y + 3, torsoCFrame.p.Z)), ['Part'] = hit})
  189. end
  190. end
  191. end
  192. table.sort(hitData, function(a,b) return a['Pos'].p.Y > b['Pos'].p.Y end)
  193. if #hitData > 0 then
  194. return hitData[1]['Pos'], hitData[1]['Part']
  195. end
  196. return torsoCFrame, nil
  197. end
  198. end
  199.  
  200.  
  201. local function StudsPerSToMetersPerS(studs)
  202. return studs / 2
  203. end
  204.  
  205. local function MetersPerSToStudsPerS(meters)
  206. return meters * 2.5
  207. end
  208.  
  209. local LastUpdate = nil
  210. local State = "Stopped"
  211. local LastStateTime = tick()
  212. --[[
  213. Cd*Ap = 0.11 for an upright body, minimal frontal area
  214. Cd*Ap = 0.84 for a horizontal body, maximal frontal area
  215. Cd*Ap = 0.46 for a body in tuck position
  216. --]]
  217. -- http://www.math.utah.edu/~eyre/rsbfaq/physics.html
  218. local function UpdateCharacter()
  219. local now = tick()
  220. if LastUpdate == nil then
  221. LastUpdate = now
  222. return
  223. end
  224. local char = GetCharacter()
  225. local torso = char and char:FindFirstChild('Torso')
  226. if char and torso then
  227. local groundHit, groundPart = GetGroundBelowCharacter(char)
  228. if groundHit and groundPart then
  229. local normal = GetNormal(groundPart, groundHit.p)
  230. -- orient you so you are standing on the surface
  231. if BodyGyro then
  232. if normal:Dot(Vector3.new(0,1,0)) < 0.7 then -- we would trip here so abort
  233. BodyGyro.cframe = CFrame.new()
  234. else
  235. local newCFrame = CFrame.new(Vector3.new(), normal) * CFrame.Angles(-math.pi/2,0,0)
  236. BodyGyro.cframe = newCFrame
  237. end
  238. end
  239. local theta = AngleFromFlat(normal) --[[ Angle of slope --]]
  240. local deltaTime = now - LastUpdate
  241. -- on flat, if speed is slow need to push
  242. if normal.unit:Dot(Vector3.new(0,1,0)) > 0.9 and BodyVelocity.velocity.magnitude < 22 then
  243. -- use poles!
  244. if State ~= "Poles" and tick() - LastStateTime > 0.5 then
  245. print'Poles State engage'
  246. TuckTrack:Stop()
  247. SwingTrack:Play()
  248. State = "Poles"
  249. LastStateTime = tick()
  250. end
  251. local skiOrientation = (torso.CFrame.lookVector * Vector3.new(1,0,1)).unit
  252. if BodyVelocity then
  253. BodyVelocity.maxForce = Vector3.new(100000000, 0, 10000000)
  254. if math.abs(math.acos(skiOrientation:Dot(BodyVelocity.velocity.unit))) > math.pi/3 then
  255. BodyVelocity.velocity = BodyVelocity.velocity * (1 - 0.55 * deltaTime)
  256. end
  257. BodyVelocity.velocity = (BodyVelocity.velocity + (skiOrientation * 19 * deltaTime))
  258. end
  259. else -- on the slope
  260. if State ~= "Tuck" and tick() - LastStateTime > 0.5 and (State ~= "Poles" or BodyVelocity.velocity.magnitude > 24) then
  261. print'Tuck State engage'
  262. SwingTrack:Stop()
  263. TuckTrack:Play()
  264. State = "Tuck"
  265. LastStateTime = tick()
  266. end
  267.  
  268. local mu = KineticSkiSnow --[[ dynamic coeff of snow --]]
  269. local g = 9.81 --[[ gravity --]]
  270. local CdAp = 0.65 --[[ Drag coeff with frontal area --]]
  271. --[[ Density of air, http://en.wikipedia.org/wiki/Density_of_air --]]
  272. local rho = 1.3413 --[[ kg*m^3 --]]
  273. local V = StudsPerSToMetersPerS(torso.Velocity).magnitude --[[ current velocity --]]
  274. local m = 65 --[[ mass --]]
  275.  
  276. local downhillVec = Vector3.new(0,1,0):Cross(normal):Cross(normal)
  277.  
  278. local skiOrientation = (torso.CFrame.lookVector * Vector3.new(1,0,1)).unit
  279. local angleBetweenLookAndHill = math.acos((downhillVec * Vector3.new(1,0,1)).unit:Dot(skiOrientation))
  280. if math.abs(angleBetweenLookAndHill) > math.rad(90) then -- if we are pointed uphill, flip direction
  281. skiOrientation = skiOrientation * -1
  282. angleBetweenLookAndHill = math.acos((downhillVec * Vector3.new(1,0,1)).unit:Dot(skiOrientation))
  283. end
  284.  
  285. local accel = g*math.sin(theta) - mu*g*math.cos(theta) - (CdAp*rho*(V*V))/(2*m)
  286. if BodyVelocity then
  287. BodyVelocity.maxForce = Vector3.new(100000000, 0, 10000000)
  288. if math.abs(math.acos(skiOrientation:Dot(BodyVelocity.velocity.unit))) > math.pi/3 then
  289. BodyVelocity.velocity = BodyVelocity.velocity * (1 - 0.55 * deltaTime)
  290. end
  291. BodyVelocity.velocity = (BodyVelocity.velocity + ((skiOrientation + Vector3.new(0,0.0001,0)).unit * accel) * deltaTime)
  292. end
  293. end
  294.  
  295.  
  296. LastUpdate = now
  297. else
  298. --[[
  299. if State ~= "Falling" and tick() - LastStateTime > 0.5 then
  300. SwingTrack:Stop()
  301. TuckTrack:Play()
  302. State = "Falling"
  303. LastStateTime = tick()
  304. end
  305. --]]
  306. if BodyGyro then
  307. BodyGyro.cframe = CFrame.new()
  308. end
  309. if BodyVelocity then
  310. --BodyVelocity.maxForce = Vector3.new()
  311. end
  312. end
  313.  
  314. end
  315. end
  316.  
  317. local function CreateSkis(leftLeg, rightLeg, leftArm, rightArm)
  318. DestroySkis()
  319. local leftSki = New'Part'
  320. {
  321. Name = 'LeftSki';
  322. FormFactor = 'Custom';
  323. Size = Vector3.new(0.7, 0.2, 5.5);
  324. TopSurface = 'Smooth';
  325. BottomSurface = 'Smooth';
  326. CanCollide = false;
  327. New'SpecialMesh'
  328. {
  329. TextureId = GetAssetUrl(SKI_TX2);
  330. MeshId = GetAssetUrl(SKI_MESH);
  331. Scale = Vector3.new(3,3,3);
  332. }
  333. }
  334. local rightSki = leftSki:Clone()
  335. rightSki.Name = 'RightSki';
  336.  
  337. Skis['left'] = leftSki
  338. Skis['right'] = rightSki
  339. --Skis['left'].CFrame = CFrame.new(0, 10, 0);
  340. --Skis['right'].CFrame = CFrame.new(3, 10, 0);
  341.  
  342. local leftLegWeld = New'ManualWeld'
  343. {
  344. Name = 'LeftSkiWeld';
  345. Part0 = leftLeg;
  346. Part1 = leftSki;
  347. C0 = CFrame.new(0,-leftLeg.Size.Y/2 + 0.1,-0.5);
  348. Parent = leftSki;
  349. }
  350. local rightLegWeld = New'ManualWeld'
  351. {
  352. Name = 'RightSkiWeld';
  353. Part0 = rightLeg;
  354. Part1 = rightSki;
  355. C0 = CFrame.new(0,-rightLeg.Size.Y/2 + 0.1,-0.5);
  356. Parent = rightSki;
  357. }
  358.  
  359. local leftPole = New'MeshPart'
  360. {
  361.  
  362. TextureId = GetAssetUrl(POLE_TEXTURE);
  363. MeshId = GetAssetUrl(POLE_MESH);
  364. Size = Vector3.new(0.337, 3.67, 0.35); --##
  365.  
  366. }
  367. local rightPole = leftPole:Clone()
  368. rightPole.Name = 'RightPole';
  369.  
  370. Skis['leftPole'] = leftPole
  371. Skis['rightPole'] = rightPole
  372.  
  373. local leftArmWeld = New'ManualWeld'
  374. {
  375. Name = 'LeftArmWeld';
  376. Part0 = leftArm;
  377. Part1 = leftPole;
  378. C0 = CFrame.new(0,-leftArm.Size.Y/2 + 0.1,1.8);-- * CFrame.Angles(math.pi,0,0);
  379. Parent = leftPole;
  380. }
  381. local rightArmWeld = New'ManualWeld'
  382. {
  383. Name = 'RightArmWeld';
  384. Part0 = rightArm;
  385. Part1 = rightPole;
  386. C0 = CFrame.new(0,-rightArm.Size.Y/2 + 0.1,1.8);-- * CFrame.Angles(math.pi,0,0);
  387. Parent = rightSki;
  388. }
  389.  
  390. Skis['left'].Parent = GetCharacter()
  391. Skis['right'].Parent = GetCharacter()
  392. Skis['leftPole'].Parent = GetCharacter()
  393. Skis['rightPole'].Parent = GetCharacter()
  394. end
  395.  
  396. function DestroySkis()
  397. for key, ski in pairs(Skis) do
  398. ski:Destroy()
  399. Skis[key] = nil
  400. end
  401. end
  402.  
  403. function OnTouched(hitPart)
  404.  
  405. end
  406.  
  407. function OnActivated()
  408. if not Tool.Enabled then return end
  409. Tool.Enabled = false
  410.  
  411. Tool.Enabled = true
  412. end
  413.  
  414. function ControlLoop()
  415. UpdateCharacter()
  416. end
  417.  
  418. local Equipped = false
  419.  
  420. function OnEquipped(mouse)
  421. Equipped = true
  422. Character, Torso, LeftLeg, RightLeg = GetCharacter(), GetTorso(), GetLeftLeg(), GetRightLeg()
  423. LeftArm, RightArm = GetLA(), GetRA()
  424. if LeftLeg and RightLeg then
  425. -- Spawn because welds
  426. Spawn(function()
  427. CreateSkis(LeftLeg, RightLeg, LeftArm, RightArm)
  428. BodyGyro = Instance.new('BodyGyro')
  429. BodyGyro.Parent = Torso
  430. BodyVelocity = Instance.new('BodyVelocity')
  431. BodyVelocity.maxForce = Vector3.new(100000000, 0, 10000000)
  432. BodyVelocity.velocity = Vector3.new()
  433. BodyVelocity.Parent = Torso
  434. end)
  435. end
  436. LastUpdate = nil
  437. local co = coroutine.create(function() while Equipped do ControlLoop() wait() end end)
  438. coroutine.resume(co)
  439. local humanoid = Character:WaitForChild('Humanoid')
  440. SwingTrack = humanoid:LoadAnimation(SKI_SWING_ANIM)
  441. TuckTrack = humanoid:LoadAnimation(SKI_TUCK_ANIM)
  442. SwingTrack:Play()
  443. Handle.Transparency = 1
  444. end
  445.  
  446. function OnUnequipped()
  447. Equipped = false
  448. Character, Torso, LeftLeg, RightLeg = nil, nil, nil, nil
  449. DestroySkis()
  450. if BodyVelocity then
  451. BodyVelocity:Destroy()
  452. BodyVelocity = nil
  453. end
  454. if BodyGyro then
  455. BodyGyro:Destroy()
  456. BodyGyro = nil
  457. end
  458. if SwingTrack then
  459. SwingTrack:Stop()
  460. SwingTrack = nil
  461. end
  462. if TuckTrack then
  463. TuckTrack:Stop()
  464. TuckTrack = nil
  465. end
  466. LastUpdate = nil
  467. Handle.Transparency = 0
  468. end
  469.  
  470.  
  471. Tool.Activated:connect(OnActivated)
  472. Tool.Equipped:connect(OnEquipped)
  473. Tool.Unequipped:connect(OnUnequipped)
Advertisement
Add Comment
Please, Sign In to add comment