Skip to content

Commit f842201

Browse files
committed
Refactor: Document rope physics, tune iterations
- Improves code readability and maintainability by adding extensive comments and documentation throughout the rope physics module. This includes module-level explanations, detailed function descriptions, and clarifications for complex logic. - Adjusts physics iteration counts for rope simulation, aiming to enhance accuracy for various rope lengths.
1 parent 55fbce4 commit f842201

File tree

1 file changed

+75
-15
lines changed

1 file changed

+75
-15
lines changed

Data/Base.rte/Devices/Tools/GrappleGun/Scripts/RopePhysics.lua

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,46 @@
1-
-- Rope Physics Module
2-
-- Ultra-rigid Verlet rope physics with pure position-based constraints
3-
-- No dampening, no force accumulation, no direct player manipulation
4-
-- EXTREMELY HARD TO BREAK: Rope only breaks at 500% stretch (5x original length)
1+
-- filepath: /home/cretin/git/Cortex-Command-Community-Project/Data/Base.rte/Devices/Tools/GrappleGun/Scripts/RopePhysics.lua
2+
--[[
3+
RopePhysics.lua - Advanced Rope Physics Module
4+
5+
Implementation of ultra-rigid Verlet rope physics with pure position-based constraints.
6+
Features:
7+
- No dampening for realistic rope behavior
8+
- No force accumulation, avoiding instability
9+
- No direct player manipulation, only physics-based interactions
10+
- Extremely durable: rope only breaks at 500% stretch (5x original length)
11+
- Optimized for performance in high-stress situations
12+
13+
This module handles all rope physics calculations for the grappling hook,
14+
including collision detection, tension forces, and segment constraints.
15+
--]]
516

617
local RopePhysics = {}
718

8-
-- Verlet collision resolution (optimized for many segments)
19+
--[[
20+
Verlet collision resolution (optimized for many segments)
21+
@param self The grapple instance
22+
@param h The index of the segment to process
23+
@param nextX The X component of the movement vector
24+
@param nextY The Y component of the movement vector
25+
]]
926
function RopePhysics.verletCollide(self, h, nextX, nextY)
10-
--APPLY FRICTION TO INDIVIDUAL JOINTS
27+
-- Apply friction to individual joints
1128
local ray = Vector(nextX, nextY)
1229
local startpos = Vector(self.apx[h], self.apy[h])
13-
local rayvec = Vector()
14-
local rayvec2 = Vector() -- This will store the surface normal
30+
local rayvec = Vector() -- Will store collision point
31+
local rayvec2 = Vector() -- Will store the surface normal
1532

1633
-- Skip collision check for very short movements to optimize performance
17-
if ray:MagnitudeIsLessThan(0.05) then -- Further reduced threshold
34+
if ray:MagnitudeIsLessThan(0.05) then -- Performance optimization threshold
1835
self.apx[h] = self.apx[h] + nextX
1936
self.apy[h] = self.apy[h] + nextY
2037
return
2138
end
2239

23-
rayl = SceneMan:CastObstacleRay(startpos, ray, rayvec, rayvec2, (self.parent and self.parent.ID or 0), self.Team, rte.airID, 0)
40+
-- Cast ray to detect terrain and objects, using the parent entity ID to avoid self-collision
41+
local rayl = SceneMan:CastObstacleRay(startpos, ray, rayvec, rayvec2,
42+
(self.parent and self.parent.ID or 0),
43+
self.Team, rte.airID, 0)
2444

2545
if type(rayl) == "number" and rayl >= 0 then
2646
-- Collision detected at rayvec
@@ -63,6 +83,10 @@ function RopePhysics.verletCollide(self, h, nextX, nextY)
6383
end
6484

6585
-- Calculate optimal segment count for a given rope length
86+
-- Dynamically adjusts segments based on rope length for performance optimization
87+
-- @param self The grapple instance
88+
-- @param ropeLength The current length of the rope
89+
-- @return The optimal number of segments for this rope length
6690
function RopePhysics.calculateOptimalSegments(self, ropeLength)
6791
-- Base calculation
6892
local baseSegments = math.ceil(ropeLength / self.segmentLength)
@@ -80,18 +104,23 @@ function RopePhysics.calculateOptimalSegments(self, ropeLength)
80104
end
81105

82106
-- Determine appropriate physics iterations based on segment count and distance
107+
-- @param self The grapple instance
108+
-- @return The number of physics iterations to use for this rope
83109
function RopePhysics.optimizePhysicsIterations(self)
84-
-- Base iteration count
110+
-- Base iteration count - balance between performance and physics accuracy
85111
if self.currentSegments < 15 and self.currentLineLength < 150 then
86-
return 5 -- More iterations for shorter, more active ropes
112+
return 36 -- More iterations for shorter, more active ropes (higher accuracy)
87113
elseif self.currentSegments > 30 or self.currentLineLength > 300 then
88-
return 3 -- Fewer for very long ropes to save performance
114+
return 9 -- Fewer iterations for very long ropes to save performance
89115
end
90116

91-
return 4 -- Default
117+
return 18 -- Default for medium-length ropes
92118
end
93119

94120
-- Resize the rope segments (add/remove/reposition)
121+
-- Handles interpolation between previous and new segment counts
122+
-- @param self The grapple instance
123+
-- @param segments The new number of segments to use
95124
function RopePhysics.resizeRopeSegments(self, segments)
96125
-- Get current positions to interpolate from
97126
local startPos = self.parent and self.parent.Pos or Vector(self.apx[0] or self.Pos.X, self.apy[0] or self.Pos.Y)
@@ -145,6 +174,8 @@ function RopePhysics.resizeRopeSegments(self, segments)
145174
end
146175

147176
-- Update rope segments to form a straight line during flight
177+
-- Used when the grappling hook is in flight and needs a clean path
178+
-- @param self The grapple instance
148179
function RopePhysics.updateRopeFlightPath(self)
149180
if not (self.parent and self.apx and self.currentSegments > 0) then
150181
return
@@ -183,6 +214,11 @@ function RopePhysics.updateRopeFlightPath(self)
183214
end
184215

185216
-- Update the rope physics using Verlet integration with no dampening
217+
-- Core physics update that handles all rope segment movement
218+
-- @param grappleInstance The grapple instance to update
219+
-- @param startPos Position vector of the start anchor (player)
220+
-- @param endPos Position vector of the end anchor (hook)
221+
-- @param cablelength Current maximum length of the cable
186222
function RopePhysics.updateRopePhysics(grappleInstance, startPos, endPos, cablelength)
187223
local segments = grappleInstance.currentSegments
188224
if segments < 1 then return end
@@ -266,6 +302,11 @@ function RopePhysics.updateRopePhysics(grappleInstance, startPos, endPos, cablel
266302
end
267303

268304
-- Advanced force protection system for preventing actor death from rope forces
305+
-- Limits maximum force applied to actors to prevent unexpected deaths
306+
-- @param grappleInstance The grapple instance
307+
-- @param force_magnitude The original magnitude of the force
308+
-- @param force_direction The direction vector of the force
309+
-- @return The safe force magnitude and safe force vector
269310
function RopePhysics.calculateActorProtection(grappleInstance, force_magnitude, force_direction)
270311
-- Simplified - just return reduced values, no complex calculations
271312
local safe_force_magnitude = math.min(force_magnitude, 5.0) -- Hard cap at 5
@@ -274,13 +315,17 @@ function RopePhysics.calculateActorProtection(grappleInstance, force_magnitude,
274315
end
275316

276317
-- Apply stored forces gradually over time
318+
-- Currently disabled in pure Verlet implementation
319+
-- @param grappleInstance The grapple instance
277320
function RopePhysics.applyStoredForces(grappleInstance)
278321
-- Disabled - no stored forces in pure Verlet implementation
279322
end
280323

281324
-- Proper Verlet rope constraint satisfaction with rigid distance constraints
282325
-- Implements true non-stretchy rope behavior using position-based dynamics
283-
-- Now properly integrated with centralized length control
326+
-- @param grappleInstance The grapple instance to apply constraints to
327+
-- @param currentTotalCableLength The current total cable length
328+
-- @return true if rope should break, false otherwise
284329
function RopePhysics.applyRopeConstraints(grappleInstance, currentTotalCableLength)
285330
local segments = grappleInstance.currentSegments
286331
if segments == 0 then return false end
@@ -501,6 +546,9 @@ function RopePhysics.applyRopeConstraints(grappleInstance, currentTotalCableLeng
501546
end
502547

503548
-- Smooth the rope using weighted averaging to reduce jaggedness
549+
-- Applies limited averaging to intermediate points to create a smoother visual appearance
550+
-- without significantly affecting the physics behavior
551+
-- @param grappleInstance The grapple instance to smooth
504552
function RopePhysics.smoothRope(grappleInstance)
505553
local segments = grappleInstance.currentSegments
506554
if segments < 3 then return end
@@ -535,6 +583,10 @@ function RopePhysics.smoothRope(grappleInstance)
535583
end
536584

537585
-- Handle player pulling on the rope (manual or automatic)
586+
-- Manages player interactions with the rope when pulling
587+
-- @param grappleInstance The grapple instance
588+
-- @param controller The input controller (optional)
589+
-- @param terrCheck Flag to check terrain (optional)
538590
function RopePhysics.handleRopePull(grappleInstance, controller, terrCheck)
539591
local player = grappleInstance.parent
540592
local segments = grappleInstance.currentSegments
@@ -552,6 +604,8 @@ function RopePhysics.handleRopePull(grappleInstance, controller, terrCheck)
552604
end
553605

554606
-- Handle player extending the rope
607+
-- Manages player interactions with the rope when extending
608+
-- @param grappleInstance The grapple instance
555609
function RopePhysics.handleRopeExtend(grappleInstance)
556610
if grappleInstance.currentLineLength < grappleInstance.maxLineLength then
557611
-- Placeholder for rope extension logic
@@ -560,6 +614,10 @@ function RopePhysics.handleRopeExtend(grappleInstance)
560614
end
561615
end
562616

617+
-- Check if the rope should break due to extreme tension
618+
-- Uses simplified tension calculation based on segment stretching
619+
-- @param grappleInstance The grapple instance
620+
-- @return Sets grappleInstance.shouldBreak = true if rope should break
563621
function RopePhysics.checkRopeBreak(grappleInstance)
564622
-- Calculate tension (simplified)
565623
local tension = 0
@@ -577,4 +635,6 @@ function RopePhysics.checkRopeBreak(grappleInstance)
577635
end
578636
end
579637

638+
-- Return the module for inclusion in other files
639+
-- This module can be imported using: local RopePhysics = require("Base.rte/Devices/Tools/GrappleGun/Scripts/RopePhysics")
580640
return RopePhysics

0 commit comments

Comments
 (0)