Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
local module = {} module.__index = module --// Services local Players = game:GetService("Players") local RunService = game:GetService("RunService") local ReplicatedStorage = game:GetService("ReplicatedStorage") --// Assets local GKAnimations = ReplicatedStorage:WaitForChild("Animations"):WaitForChild("GK") --// Utility: Computes two axis-aligned positions forming a right angle from points A and B local function computeAxisAlignedRightPoints(A, B) local y = A.Y -- keep in the same horizontal plane local Cx = Vector3.new(A.X, y, B.Z) local Cz = Vector3.new(B.X, y, A.Z) return Cx, Cz end --// Utility: Difference in height between two points local function getHeightDifference(a: Vector3, b: Vector3): number return b.Y - a.Y end --// Utility: Returns absolute vertical distance between two points local function getAbsoluteHeightDifference(a: Vector3, b: Vector3): number return math.abs(b.Y - a.Y) end --// Calculates urgency-based dive speed depending on ball's horizontal distance to goal local function computeDiveSpeedFromGoal(ball, nearestGoalPoint, minSpeed, maxSpeed) local ballPos = ball.Position local ballSpeed = ball.Velocity.Magnitude * 0.5 -- Horizontal distance to goal in 3D space local dist = math.sqrt((ballPos.X - nearestGoalPoint.X)^2 + (ballPos.Y - nearestGoalPoint.Y) + (ballPos.Z - nearestGoalPoint.Z)^2) if dist == 0 then return maxSpeed end local raw = ballSpeed / dist return math.clamp(raw, minSpeed, maxSpeed) end --// Makes the goalkeeper dive in a ballistic arc from startPos to endPos local function diveToPosition(gkModel, startPos, endPos, peakHeight, arrivalThreshold, speed, ballspeed) speed = speed or 0.5 --// Get humanoid and root part local humanoid = gkModel:FindFirstChildOfClass("Humanoid") local rootPart = gkModel:FindFirstChild("HumanoidRootPart") or gkModel.PrimaryPart if not humanoid or not rootPart then return end --// Enter dive state humanoid.PlatformStand = true humanoid:ChangeState(Enum.HumanoidStateType.Freefall) --// Ballistic arc physics setup local g = workspace.Gravity or 196.2 local y0, y1 = startPos.Y, endPos.Y local h = peakHeight --// Ensure peak is above target local minH = y1 - y0 if h < minH then h = minH + 1 end --// Compute vertical velocity and flight time local v0y = math.sqrt(2 * g * h) local tUp = v0y / g local fallDistance = h + (y0 - y1) local tDown = math.sqrt(2 * math.max(fallDistance, 0) / g) local tTotal = tUp + tDown --// Horizontal velocity local displacement = endPos - startPos local v0xz = Vector3.new(displacement.X, 0, displacement.Z) / tTotal local initialVelocity = Vector3.new( v0xz.X * speed, v0y * speed, v0xz.Z * speed ) --// Apply impulse to dive rootPart.AssemblyLinearVelocity = initialVelocity --// Marker for dive state local DV = Instance.new("StringValue", gkModel.PrimaryPart) DV.Name = "DiveVelocity" --// Stop when close enough to destination local conn conn = RunService.Heartbeat:Connect(function() if (rootPart.Position - endPos).Magnitude <= arrivalThreshold then conn:Disconnect() DV:Destroy() -- Stop horizontal movement, keep vertical momentum local av = rootPart.AssemblyLinearVelocity rootPart.AssemblyLinearVelocity = Vector3.new(0, av.Y, 0) humanoid.PlatformStand = false end end) end --// Checks if goalkeeper collided with the ball while diving local function CheckForBall(Character: Model, data) local Ball: Part = data.Ball while true do if not Character.HumanoidRootPart then break end if not Character.HumanoidRootPart:FindFirstChild("DiveVelocity") then break end --// Create a temporary hitbox representing the goalkeeper's body local Hitbox = Instance.new("Part") Hitbox.CanCollide = false Hitbox.Anchored = true Hitbox.CFrame = Character:GetPivot() Hitbox.Size = Character:GetExtentsSize() Hitbox.Transparency = 1 Hitbox.Parent = workspace --// Detect proximity to ball local nearestPoint = Hitbox:GetClosestPointOnSurface(Ball.Position) if (Ball.Position - nearestPoint).Magnitude < 3 then Ball:Destroy() Character.HumanoidRootPart.AssemblyLinearVelocity *= 0.25 break end Hitbox:Destroy() task.wait(RunService.Heartbeat:Wait()) end end --// Default dive speed local DiveSpeed = 0.75 --// Action handlers local Actions = { ["DU"] = function(self, data, t, pos) local Character: Model = self.Character local FData = data.FieldData local Ball = FData.Ball local Humanoid = Character:FindFirstChildWhichIsA("Humanoid") --// Stop any current animation local PlayingAnimations = Humanoid:GetPlayingAnimationTracks() if PlayingAnimations[1] then PlayingAnimations[1]:Stop() end --// Play dive animation local Track = Humanoid:LoadAnimation(GKAnimations.LDive) Track:AdjustSpeed(2) Track:Play() Humanoid.Jump = true --// Start ragdoll after animation nears end task.spawn(function() repeat task.wait() until Track.TimePosition > Track.Length * 0.85 local Ragdoll = require(script.RagdollModule) Ragdoll:Ragdoll(Character) Character.PrimaryPart.AssemblyAngularVelocity = Vector3.new(180, 0, 0) end) --// Predict where the ball is going to end up local PredictedPosition local nearestGoalPos repeat PredictedPosition = Ball.Position + Ball.AssemblyLinearVelocity * RunService.Heartbeat:Wait() nearestGoalPos = FData.Zone.Goal:GetClosestPointOnSurface(Ball.Position) task.wait() until Character.PrimaryPart.Position.Y >= nearestGoalPos.Y or (PredictedPosition - nearestGoalPos).Magnitude < 3 --// Dynamically compute dive urgency local speed = computeDiveSpeedFromGoal(Ball, nearestGoalPos, 0.5, 1.25) --// Determine better final position via raycast local BetterPos local Params = RaycastParams.new() Params.FilterType = Enum.RaycastFilterType.Include Params.FilterDescendantsInstances = {FData.Zone.Goal} local rc = workspace:Raycast(Ball.Position, Ball.AssemblyLinearVelocity) if rc and rc.Instance then BetterPos = rc.Position end --// Compute required dive height local Height = getHeightDifference(Character.PrimaryPart.Position, BetterPos) if Height < 0 then Height = 0 end --// Compute arc mid-point local PosA = Character.PrimaryPart.Position local PosC = BetterPos local PosB = computeAxisAlignedRightPoints(PosA, PosC) PosB = Vector3.new(PosB.X, PosC.Y, PosB.Z) local O = (Vector2.new(PosA.X, PosA.Z) + Vector2.new(PosB.X, PosB.Z)) / 2 --// Optional: Visual debug local PartA = Instance.new("Part", workspace) PartA.Position = PosA PartA.Size = Vector3.new(1, 1, 1) PartA.Anchored = true PartA.CanCollide = false Instance.new("Highlight", PartA).FillColor = Color3.new(0.043, 0.09, 1) local PartB = Instance.new("Part", workspace) PartB.Position = PosB PartB.Size = Vector3.new(1, 1, 1) PartB.Anchored = true PartB.CanCollide = false Instance.new("Highlight", PartB).FillColor = Color3.new(0.118, 1, 0.22) --// Perform dive and check for ball save diveToPosition(Character, PosA, PosB, Height, 0.25, speed, Ball.AssemblyLinearVelocity.Magnitude * RunService.Heartbeat:Wait()) CheckForBall(Character, FData) end, } --// Initializes the goalkeeper module with a character model function module.Init(Model: Model) local self = setmetatable({}, module) self.Character = Model return self end --// Triggers a specific goalie action function module:DoAction(Action, PositionToHit, t) if Actions[Action] then Actions[Action](self, PositionToHit, t) end end return module
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)